2012-08-10 16 views
14

per curiosità e per aumentare le mie conoscenze, ho voluto implementare una sorta di associazione di dati bidirezionale tra elementi dom e variabili javascript.Plain Javascript bidirezionale Associazione dati

ho avuto la fortuna di trovare una risposta eccellente per la metà del mio problema qui @ StackOverflow che mi ha portato a questa sostanza https://gist.github.com/384583, ma io ancora non riesco a ottenere la cosa fatta al 100%.

Ecco un esempio del mio codice: http://jsfiddle.net/bpH6Z/

Se si tenta di eseguire il violino e clicca su "view Valori" trova indefinito, mentre io voglio ottenere il valore effettivo della attributo dell'oggetto

Probabilmente sto facendo qualcosa di sbagliato a causa della mia mancanza di esperienza con javascript, ma hai qualche idea del perché non riesco a leggere correttamente l'attributo 'segreto' dopo le chiamate _bind() e _watch()?

DISCLAIMER: come ho detto, lo sto facendo perché voglio una migliore conoscenza di javascript e non scriverò il mio framework. Quindi qualsiasi "USE FRAMEWORK X" è completamente inutile, dato che potrei fare il lavoro con angularjs.

+0

+1 per JS pianura;) – metadings

+0

ist $ riferendosi a jQuery? Quindi non è semplice JS huh – daslicht

+0

Possibile duplicato di [Come implementare il binding dei dati DOM in JavaScript] (http://stackoverflow.com/questions/16483560/how-to-implement-dom-data-binding-in-javascript) – Beginner

risposta

5

Si prega di provare http://jsfiddle.net/bpH6Z/4/

Ho aggiornato il vostro getter/setter ridefinito in vigilanza Object.prototype .__, anche al momento il gestore ha la necessità di restituire il nuovo valore.

Aggiornamento: Ora il gestore non è tenuto a restituire il nuovo valore impostato.

codice attuale:

//Got this great piece of code from https://gist.github.com/384583 
Object.defineProperty(Object.prototype, "__watch", { 
    enumerable: false, 
    configurable: true, 
    writable: false, 
    value: function(prop, handler) { 
     var val = this[prop], 
      getter = function() { 
       return val; 
      }, 
      setter = function(newval) { 
       val = newval; 
       handler.call(this, prop, newval); 
       return newval; 
      }; 

     if (delete this[prop]) { // can't watch constants 
      Object.defineProperty(this, prop, { 
       get: getter, 
       set: setter, 
       enumerable: true, 
       configurable: true 
      }); 
     } 
    } 
}); 

var Controller = function() { 
    //The property is changed whenever the dom element changes value 
    //TODO add a callback ? 
    this._bind = function (DOMelement, propertyName) { 
     //The next line is commented because priority is given to the model 
     //this[propertyName] = $(DOMelement).val(); 
     var _ctrl = this; 
     $(DOMelement).on("change input propertyChange", function(e) { 
      e.preventDefault(); 
      _ctrl[propertyName] = DOMelement.val(); 
     }); 

    }; 

    //The dom element changes values when the propertyName is setted 
    this._watch = function(DOMelement, propertyName) { 
     //__watch triggers when the property changes 
     this.__watch(propertyName, function(property, value) { 
      $(DOMelement).val(value); 
     }); 
    }; 
}; 

var ctrl = new Controller(); 
ctrl.secret = 'null'; 
ctrl._bind($('#text1'), 'secret'); // I want the model to reflect changes in #text1 
ctrl._watch($('#text2'), 'secret'); // I want the dom element #text2 to reflect changes in the model 
$('#button1').click(function() { 
    $('#output').html('Secret is : ' + ctrl.secret); //This gives problems 
}); 

HTML attuale:

<html> 
<head></head> 
<body> 
    value: <input type="text" id="text1" /><br /> 
    copy: <input type="text" id="text2" /><br /> 
    <input type="button" id="button1" value="View value"><br /> 
    <span id="output"></span> 
</body> 
</html> 
+0

+1 per la rilavorazione – fatmatto

+0

Questo funziona con IE8 come defineProperty funziona solo sugli oggetti DOM? – Integralist

+0

@Integralist molto probabilmente no, ma dovresti provarlo - devi riavviare xp – metadings

3

Il gestore che si passa alla funzione manca un'istruzione return.

this._watch = function(DOMelement, propertyName) { 
    //__watch triggers when the property changes 
    this.__watch(propertyName, function(property, value) { 
     $(DOMelement).val(value); 
     return value; 
    }) 

} 

Perché newval è impostato su ciò che è tornato dal gestore, sarà undefined senza quella.

+0

+1. Spot on, mi ha battuto per questo ... Ho appena notato questo finalmente anche –

+0

+1 per rimuovere il mio mal di testa – fatmatto

0

ho migliorato per multi-watchers.

http://jsfiddle.net/liyuankui/54vE4/

//The dom element changes values when the propertyName is setted 
this._watch = function(DOMelement, propertyName) { 
    //__watch triggers when the property changes 
    if(watchList.indexOf(DOMelement)<0){ 
     watchList.push(DOMelement); 
    } 
    this.__watch(propertyName, function(property, value) { 
     for(var i=0;i<watchList.length;i++){ 
      var watch=watchList[i]; 
      $(watch).val(value); 
      $(watch).html(value); 
     } 
    }); 
}; 
Problemi correlati