javascript, jquery

console.log(“Hello World”);

04.20.08 | 2 Comments

Riporto un piccolo e inutile plugin jQuery.
Si è veramente inutile!
Il plugin crea box ridimensionabili arricchiti di una “toolbar”.
I tasti di questa toolbar permetteranno di navigare la cronologia dei ridimensionamenti.

Mi è servito solamente per capire come integrare la consueta programmazione orientata agli oggetti
con i vantaggi portati dalla libreria jQuery.

Finora avevo scritto in jQuery plugin dotati solamente di metodi statici.
Ora mi è interessato capire come programmare ad oggetti e far comunicare questi oggetti con gli elementi DOM coinvolti dai plugin.

Un conto è applicare quindi ad un insieme di DIV azioni, stili, comportamenti.
Un conto è sviluppare oggetti complessi e saperli collegare alle “catene” jQuery.

jQuery Resizible

In una pagina HTML creo una toolbar con due “tasti”.
I due tasti aggiungono dei div con class=”box” alla pagina.
Il tutto utilizzando jQuery.


$(document).ready(function(){
    var add = jQuery('<a href="#">ADD BOX</a>').click(function(){
            var count = jQuery(".box").length + 1;
            var id_div = "div" + count;
            jQuery("#playground").append("<h1>"+ id_div +"</h1><div id=\""+id_div+"\" class=\"box\"></div>");
            jQuery("#" + id_div).resizable({ transparent: true});
    });
    var add5 = jQuery('<a href="#">ADD 5 BOX</a>').click(function(){
        var count = jQuery(".box").length + 1;
        for(var x = 0;x < 5;x++){
            var id_div = "div" + (count + x);
            jQuery("#playground").append("<h1>"+ id_div +"</h1><div id=\""+ id_div +"\" class=\"box\"></div>");
            jQuery("#" + id_div).resizable({ transparent: true});
        }
    });
    jQuery("#top").append(add , "  | ");
    jQuery("#top").append(add5 , "  | ");
});

Demo

ResizeRecorder

Vorrei agganciare al resize di ogni contenitore aggiunto alla pagina, un oggetto indipendente che tenga memorizzate le varie posizioni avute.


ResizeRecorder = (function(){

    //private static attributes
    var recorders = 0;

    return function(elem){

        //private attrs
        var _style;
        var _position = 0;
        var _stack = new Array();

         //public attrs
        this.ref = elem.get(0);

        //private methods
        function _init_style(style){
             style = style || "";
             _style = style;
             _stack.push(_style);
             _position = _stack.length;
        }

        //privileged methods
        this.log = function(){
            console.log("Stile attuale: " + _style);
            console.log("Posizione history: " + _position);
            console.log("Lunghezza history: " + _stack.length);
        }
        //code constructor
        recorders++;
        console.log("Incremento il contatore statico di istanze : " + recorders);
        _init_style(jQuery(elem).attr("style"));
        this.log();
    }

})();

$(document).ready(function(){
    new ResizeRecorder(jQuery("#div1"));
});

Se avete firebug cliccando sulla demo vedrete questo log:

Incremento il contatore statico di istanze : 1
Stile attuale: position: relative; top: 0px; left: 0px; width: 343px; height: 150px;
Posizione history: 1
Lunghezza history: 1

Demo

stop : function(){}

L’interfaccia resizable espone un evento “stop” a cui si può agganciare una funzione.
Io vorrei agganciare un metodo della classe ResizeRecorder in modo da aggiornare lo stile del div ogni volta che ridimensiono.

Innanzitutto aggiungo al recorder il metodo privilegiato update().
Il metodo salva il nuovo stile, lo registra in uno stack e segna in _position la posizione del recorder nello stack.
Avendo salvato nell’istanza il riferimento al DOM non avrò bisogno di argomenti.


this.update = function(){
    //@samba fix :)
    if(_position < _stack.length)
         _stack = _stack.slice(0,_position);

    _style = jQuery(this.ref).attr("style");
    _stack.push(_style);
    _position = _stack.length;
}

Vediamo come agganciare ora il resize.


$(document).ready(function(){
    var elem = jQuery("#div1");
    var ref = elem.get(0);
    //istanza del recorder
    var recorder = new ResizeRecorder(elem);
    //aggancio all'elemento DOM il recorder
    ref.recorder = recorder;
    //inizializzo resizable e allo stop del resize invoco on_resize() dell'oggetto appena "agganciato"
    elem.resizable({ transparent: true, stop : function(){this.recorder.on_resize()}});
});

Creo un metodo pubblico on_resize().


ResizeRecorder.prototype  = {
    on_resize: function(){
        //invoco update()
        this.update();
        //loggo sulla console
        this.log();
    }
};

Se avete firebug cliccando sulla demo vedrete questo log:

Incremento il contatore statico di istanze : 1
Stile attuale: position: relative; top: 0px; left: 0px; width: 343px; height: 150px;
Posizione history: 1
Lunghezza history: 1

E ridimensionando ogni volta avrete :

Stile attuale: position: relative; top: 0px; left: 0px; width: 421px; height: 150px;
Posizione history: 2
Lunghezza history: 2

Demo

next() e prev()

Creo una pulsantiera sotto il div.


//pulsantiera per navigare lo stack del recorder
jQuery("#manager1").append('<a href="#" id="prev1">prev</a>');
jQuery("#manager1").append('   ');
jQuery("#manager1").append('<a href="#" id="next1">next</a>');

jQuery("#prev1").click(function(){ResizeRecorder.go_prev(ref);return false;});
jQuery("#next1").click(function(){ResizeRecorder.go_next(ref);return false;});

Al click su indietro e al click su avanti invoco i 2 metodi statici del recorder passando la reference all’elemento DOM “div1″.


ResizeRecorder.go_next = function(ref){
    ref.recorder.next();
    ref.recorder.log();
};
ResizeRecorder.go_prev = function(ref){
    ref.recorder.prev();
    ref.recorder.log();
};

Nella classe creo altri due metodo privilegiati next() e prev()


this.prev = function(){
    if(_position > 1){
        _position--;
        _style = _stack[(_position - 1)];
        jQuery(this.ref).attr("style", _style);
    }
};
this.next = function(){
    if(_position < _stack.length){
        _position++;
        _style = _stack[(_position - 1)];
        jQuery(this.ref).attr("style", _style);
    }
};

Demo

Chinability e DOM

Ora cercherò di rendere il mio oggetto pluggabile e concatenabile a oggetti jQuery.
Per prima cosa creo la struttura del plugin.


JResizeRecorder = {
    build : function(options)
    {
        return this.each(
            function(nr)
            {
            }
        );
    }
};
jQuery.fn.JResizeRecorder = JResizeRecorder.build;

Torniamo al codice del passo 1. I due tasti creavano box dimensionabili.
Ora “in catena” istanzio il mio plugin .JResizeRecorder();


var add = jQuery('<a href="#">ADD BOX</a>').click(function(){
    var count = jQuery(".box").length + 1;
    var id_div = "div" + count;
    jQuery("#playground").append("<h1>"+ id_div +"</h1><div id=\""+id_div+"\" class=\"box\"></div>");
    var elem = jQuery("#" + id_div);
    elem.resizable({ transparent: true, stop : function(){this.recorder.on_resize()} }).JResizeRecorder();
});
var add5 = jQuery('<a href="#">ADD 5 BOX</a>').click(function(){
    var count = jQuery(".box").length + 1;
    for(var x = 0;x < 5;x++){
        var id_div = "div" + (count + x);
        jQuery("#playground").append("<h1>"+ id_div +"</h1><div id=\""+ id_div +"\" class=\"box\"></div>");
        var elem = jQuery("#" + id_div);
        elem.resizable({ transparent: true, stop : function(){this.recorder.on_resize()} }).JResizeRecorder();
    }
});
jQuery("#top").append(add , "  | ");
jQuery("#top").append(add5 , "  | ");

Prima il collegamento tra la reference DOM e recorder l’avevo creata nel document.ready ora la creo nel plugin.
Chiaramente se stacco i due plugin resizable e JResizeRecorder, questo genererà un errore

stop : function(){this.recorder.on_resize()}


build : function(options)
{
    return this.each(
        function(nr)
        {
            this.recorder = new ResizeRecorder(jQuery(this));
            JResizeRecorder.toolbar(this);
        }
    );
}

Nel plugin dopo aver istanziato il Recorder creo la toolbar invocando il metodo statico del plugin “toolbar”.
I due tasti come prima invocano i metodi statici go_prev e go_next passando come argomento la reference al div
passato da build.


toolbar: function(elem)
{
    var id = 'manager_' + jQuery(elem).attr("id");

    jQuery(elem).after("<div id=\""+id+"\"></div>");
    var prev = jQuery('<a href="#">prev</a>').click(function(){
        ResizeRecorder.go_prev(elem);
        return false;
    });
    var next = jQuery('<a href="#">next</a>').click(function(){
        ResizeRecorder.go_next(elem);
        return false;
    });

    jQuery("#"+id).append(prev);
    jQuery("#"+id).append('   ');
    jQuery("#"+id).append(next);
}

La Demo finale

Popularity: 3% [?]

2 Trackbacks

  1. [...] Questa è la continuazione del post precedente [...]

  2. By (function() { : Samba! Primo commento on 9 May 2008 at 08:14

    [...] console.log(”Hello World”); [...]

Post a Comment

Your email is never shared. Required fields are marked *

*
*
© 2010 Massimiliano Balestrieri | Thanks, WordPress | Sandbox theme | Standards Compliant XHTML & CSS | RSS Posts & Comments