javascript, jquery

Persistenza tramite window.unload

04.23.08 | Comment?

Continua da

Intanto la demo di queste parole alla rinfusa.
Se non siete sviluppatori difficilmente vi interesserà. Cliccare direttamente sul link (non aprire in altro tab).
Con Firefox e firebug attivo. Alla faccia del “crossbrowser”.
Senza Firefox non ci sarebbe innovazione. Il crossbrowser è un tema che non mi interessa.

DEMO

Dopo vari tentativi sono riuscito a spostare la trasmissione di dati ad un singolo evento.

window.unload

Per evitare di avere problemi di implementazioni tra i vari browser scelgo sempre la soluzione wrappata da jQuery sperando che funzioni anche con i browser scadenti della Microsoft.
Questo esempio come il precedente non funziona su Internet Explorer (almeno sulla mia versione emulata).
Il motivo è principalmente questo: ho usato 2/3 metodi dell’oggetto Array di javascript 1.6 (Explorer è fermo a 1.5) .

Usando i sugar arrays di Dustin Diaz la demo continua a non funzionare. Non ho tempo e voglia di interpretare gli errori di Explorer (riga 55 cos’è?).

Nel precedente post… il mio piccolo esperimento di programmazione OO agganciata ai plugin jQuery iniziava a dare segni di utilità. Sembrava quasi un proto Window Manager.
In realtà il pattern Lazy Loading applicato tramite l’evento hover non era una cattiva idea… ma i metodi “disable” e “enable” delle librerie UI resizable e draggable… non sono state evindentemente pensate per risparmiare risorse.
Il risultato era un rallentamento delle prestazioni.

Cercherò di applicare il pattern Lazy Loading in altri casi.

Poi avevo applicato il pattern Observer grazie al libro di Hermes e Diaz. E’ stata veramente una scoperta per me.


function Publisher(){
    this.subscribers = [];
}
Publisher.prototype.deliver = function(data){
    this.subscribers.forEach(
        function(fn){
            fn(data);
        }
    );
    return this;
};
Function.prototype.subscribe = function(publisher){
    var that = this;
    var alreadyExists = publisher.subscribers.some(
        function(el){
            if(el === that){
                return;
            }
        }
    );
    if(!alreadyExists){
        publisher.subscribers.push(this);
    }
    return this;
}
Function.prototype.unsubscribe = function(publisher){
    var that = this;
    publisher.subscribers = publisher.subscribers.filter(
        function(el){
            if(el !== that){
                return el;
            }
        }
    );
    return this;
}

Per cercare una persistenza dello stile tra un refresh e l’altro della demo… però avevo usato l’evento sbagliato per trasmettere le modifiche. Ad ogni stop di resize e di drag, trasmettevo lo stile del box con una chiamata. Era un metodo che avevo adottato anche in un vecchio pregetto (Deskweb).

Scadendo le prestazioni mi sono chiesto se fosse possibile adottare una strategia migliore per la trasmissione e il salvataggio dello stile. Ho provato l’evento unload. Non lo avevo mai usato.

Non funziona proprio come mi aspettavo… ma il risultato è più che positivo.
Non viene eseguito (almeno su firefox) alla chiusura della finestra o alla chiusura del tab (magari qualcuno mi smentirà) ma viene eseguito al refresh.
E il risultato è ottimo. Ho poche trasmissioni ajax e ho una persistenza sul refresh.

Quindi l’oggetto Lazy è stato rinominato in BoxUI (una sorta di wrapper a tutte le interfacce ui che applico al box).

Questo oggetto registra due “Publisher” uno per il singolo cambiamento di stile, uno per lo stato dello stile all’unload della finestra.


JBoxUi = {
    build : function(options)
    {
        return this.each(
            function(nr)
            {
                this.publishers = {};
                this.publishers.style = new Publisher();
                this.publishers.unload = new Publisher();

                jQuery(this)
                .draggable({ stop : function(){this.publishers.style.deliver();}})//this.recorder.on_resize()
                .resizable({ stop : function(){this.publishers.style.deliver();}, transparent: true })
                .JStyleRecorder()
                .JStyleObserver();
            }
        );
    }
};
jQuery.fn.JBoxUi = JBoxUi.build;

Resize e Drag scatenano deliver() solo al recorder dello stile (l’inutile history creata nel primo post).
Il deliver() sull’unload invece viene invocato all’unload.


jQuery(window).unload(
    function () {
        jQuery(".box").each(
            function(){
                //console.log("hi");
                this.publishers.unload.deliver();
            }
        );
    }
);

Quindi lo StyleRecorder sottoscrive solamente il Publisher “style”


JStyleRecorder = {
    build : function(options)
    {
        return this.each(
            function(nr)
            {
                var that = this;
                this.recorder = new StyleRecorder(jQuery(this));
                var subscriber = function(){
                    that.recorder.on_change();
                }
                subscriber.subscribe(this.publishers.style);
                JStyleRecorder.toolbar(this);
            }
        );
    },

Mentre lo JStyleObserver osserva il Publisher “unload” e registra tramite chiamata al server gli stili di ogni box.


JStyleObserver = {
   build : function(options)
    {
        return this.each(
            function(nr)
            {
                var that = this;
                var subscriber = function(){
                    JStyleObserver.send(that);
                }
                subscriber.subscribe(this.publishers.unload);
                JStyleObserver.send(this);
            }
        );
    },
    send : function(elem){
        var style = jQuery(elem).attr("style");
        var id = jQuery(elem).attr("id");
        jQuery.ajax({
            type: "POST",
            url: "server.php",
            data: "style=" + style + "&id=" + id,
            dataType: "json",
            success: function(msg){
                console.log(msg);
            }
        });
    },
    get : function(){
        jQuery.ajax({
            url: "server.php",
            dataType : "json",
            success: function(data){
                console.log(data);
                if(!data.error)
                    for(x in data){
                        console.log(x + " : " + data[x]);

                        jQuery("#playground").append("<div id=\""+ x +"\" class=\"box\"></div>");
                        var elem = jQuery("#" + x);
                        elem.attr("style",data[x]);
                        elem.JBoxUi();
                    }
            }
        });
    }
};
jQuery.fn.JStyleObserver = JStyleObserver.build;

Ecco il codice triviale di server.php.
Per il JSON ho usato questo


require_once(dirname(__FILE__) . '/JSON.php');
$json = new Services_JSON();
session_start();

if(!isset($_REQUEST['id']) || !isset($_REQUEST['style'])){
    if(sizeof($_SESSION)>0)
        echo $json->encode($_SESSION);
    else
        echo "{error:'nodata'}";

} else {

    $style = $_REQUEST['style'];
    $id = $_REQUEST['id'];
    $_SESSION[$id] = $style;
    echo "{".$id.":'".$style."'}";

}

Popularity: 2% [?]

Post a Comment

Your email is never shared. Required fields are marked *

*
*