var mysite = {
    'url': "http://www.ajaxweb20.net",
    'author': "Giuseppe Raso",
    'xhtmlValid': true,
    'cssValid': true
}
Home > Blog

Posts Tagged ‘defineGetter’

Workaround per usare __defineGetter__ e __defineSetter__ su elementi HTML

Venerdì, Marzo 28th, 2008

defineGetter e defineSetter sono due metodi dannatamente utili supportati al momento da Firefox, Opera 9.5, Safari 3 e Konqueror. Essi permettono di manipolare le proprietà dichiarando un setter ( una funzione che viene eseguita opgni volta che settiamo una proprietà ) o un getter ( una funzione che viene usata ogni volta che prendiamo una proprietà in modo da manipolare il valore ritornato ).

Teoricamente potremmo usarlo per simulare innerText su Firefox:

HTMLElement.prototype.__defineSetter__("innerText", function(value) { this.textContent = value; })

Purtroppo in Firefox 2 ( con la versione 3 il problema non sussiste ) non è possibile definire ne getter ne setter sugli elementi HTML :(
Si tratta di uno strano bug che fortunatamente ha un workaround molto semplice, ovvero quello di applicare il getter/setter alla classe Node:

Node.prototype.__defineSetter__("innerText", function(value) { this.textContent = value; })

L’unico svantaggio è che così facendo stiamo applicando il setter a tutti i tipi di nodi, compresi nodi testo, commento e persino documento!

Ma anche in questo caso la soluzione è alquanto semplice:

Node.prototype.__defineSetter__("innerText", function(value) {
  if(this.nodeType == 1)
    this.textContent = value;
  else
    this.innerText = value;
})

Semplicemente controlliamo che il nodo sia veramente un elemento HTML ( con nodeType uguale a 1 ): se è vero settiamo la proprietà textContent ( il rispettivo di innerText in IE ) altrimenti ci comportiamo come se il setter non esistesse, ovvero settando la proprietà innerText manualmente.

Volendo possiamo “standardizzare” questa operazione tramite una funzione ( Ah che belle le closures :D ):

HTMLElement.$defineSetter = function(prop, fn) {
  Node.prototype.__defineSetter__(prop, function(value) {
    this.nodeType == 1
      ? fn.call(this, value)
      : this[prop] = value;
  })
}

Con poche modifiche possiamo creare una funzione che crea un getter:

HTMLElement.$defineGetter = function(prop, fn) {
  Node.prototype.__defineGetter__(prop, function() {
    retun this.nodeType == 1)
      ? fn.call(this, value)
      : this[prop];
  })
}

Per altri snippet stay tuned!