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

Archive for the ‘Javascript’ Category

Bug di IE nella gestione di array contenenti elementi XML.

Sabato, Aprile 26th, 2008

Faccio veramente fatica a capire il bug che vi sto per illustrare, e qualcosa mi dice che per voi non sarà diverso :D

Supponiamo di avere una funzione che carica un documento xml; in Internet Explorer siamo costretti a usare un ActiveX: scomodo, ma almeno fin qui funziona tutto.

var xml = new ActiveXObject("Microsoft.XMLDOM");
xml.async = false;
xml.load("myfile.xml")

Bene, ora supponiamo di voler creare un array contenente alcuni degli elementi che abbiamo ottenuto:

var arr = [];
arr[0]= xml.documentElement;
arr[1] = xml.childNodes[1]

Qual’è il bug?
Stranamente, una volta inserito uno o più elementi xml nell’array, i metodi toString e join di quest’ultimo non funzioneranno più.
In altre parole:

arr.toString() //Restituisce "[object]", una stringa assolutamente inutile
arr.join(",") //dà addirittura errore!

Onestamente non riesco proprio a capire come ciò possa accadere. Non posso fare altro che complimentarmi col team di IE: una “funzionalità” che io ho difficolta anche a concepire loro sono riusciti a realizzarla non volendo!

Super Mario in 14 kb di Javascript.

Mercoledì, Aprile 9th, 2008

Recentemente Jacob Seidelin è riuscito a ricreare il gioco di Super Mario in soli 14 kb. Si tratta più che altro di un esperimento visto che è presente solo il primo livello.
Ciò che è interessante e mette in luce le potenzialità di Javascript è il fatto che per realizzarlo non sono state usate ne immagini ne file audio.

Come è possibile?
Per le figure è stato usato il tag canvas, e per simularlo in IE sono stati utilizzati dei div.
La musica invece è stata codificata in base64, anche se ciò non è simulabile in alcun modo su IE.

Javascript: Usare apply per passare vari argomenti a un costruttore.

Lunedì, Marzo 31st, 2008

Apply come già sicuramente saprete permette di passare degli argomenti ad una funzione sotto forma di array; tra l’altro lo stesso apply permette di specificare l’oggetto contesto della funzione, in altra parole l’oggetto che si potrà richiamare mediante l’operatore this.

function fn() {
  for(var i = 0, l = arguments.length; i!=l; i++) {
    this[i] = arguments[i] + "xyz";
  }
}

fn.apply([], ["a", "b", "c"]);

Qualcuno si sarà chiesto se sia possibile usare apply con i costruttori, qualcuno magari avrà provato anche a scrivere il seguente codice ricevendo in cambio l’errore “xxx is not a constructor”:

function miaClasse() {
  this.method = function() {
  }
  this.str = arguments[0] || ;
}

new miaClasse.apply(null, ["str"]) //Attenzione, questo codice NON funziona!!!

Fortunatamente non è molto difficile arrivare a una prima soluzione:

miaClasse.apply(new miaClasse, ["a"]); //Questo invece funziona!!!

Resta ancora un problema: il codice all’interno della classe miaClasse viene eseguito inutilmente due volte, e tra l’altro a causa dell’assenza di argomenti non è detto che non possa causare un errore.

La soluzione è quella di creare un’altra classe che erediti le proprietà dalla classe originaria e usare l’oggetto creato con questa classe:

function klass() {
  miaClasse.apply(new this, arguments)
}

function intermediate() {
}

intermediate.prototype = miaClasse.prototype;

klass.prototype = new intermediate;

//Esempio

klass.apply(null, [/*arguments…*/])

Notare che la proprietà constructor non viene corretta ( solitamente lo si fa in ogni ereditarietà ) proprio perchè potrebbe essere utile considerare l’oggetto restituito da miaClasse come se fosse un’istanza di miaClasse invece che di klass.

Infine come buona norma astrattizziamo il codice e trasformiamolo in funzione, anzi, visto che ci siamo che ne dite di un prototipo con un bel lazy pattern? :D

Function.prototype.instance = function(args) {

  var this_ = this;
  function klass() {
    this_.apply(new this, arguments[0])
  }

  function intermediate() {
  }

  intermediate.prototype = miaClasse.prototype;

  klass.prototype = new intermediate;

  this_.instance = klass;

  this_.instance(args);

}

Enjoy :)

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!

Una guida completa sull’erediterietà in Javascript.

Mercoledì, Marzo 26th, 2008

Per chi sta iniziando adesso ad addentrarsi nei meandri di questo potente linguaggio di scripting, ma anche ai più esperti ( non si smette mai di imparare :) ) consiglio caldamente la lettura di questa guida ( in inglese ) sull’ereditarietà in Javascript.

Tra le guide inerenti l’argomento che abbia mai letto questa è senza ombra di dubbio la più completa, e tra l’altro riassume gli studi fatti recentemente dallo stesso Giammarchi e da altri javascripter di fama internazionale.

L’unico neo rilevante della guida è che forse la lettura potrebbe apparire alquanto oscura a chi ha poca o nulla dimestichezza con l’argomento…
Nel caso vi riconosciate in questa categoria vi consiglio caldamente di leggere anche questo vecchio post.

Annientare la razza umana tramite un popup… Lo so, è una frase priva di senso, ma in un telefilm succede realmente!

Domenica, Marzo 16th, 2008

Nel telefilm di fantascienza Stargate SG-1 il colonnello O-Neall e Samantha Carter devono vedersela con dei robot alieni a forma di ragno detti replicanti.
A un certo punto della loro missione entrano nel “core” del programma che gestisce i replicanti in modo da poterlo manipolare e sconfiggere così il temibile nemico.
A questo punto sorge spontanea la domanda: in quale linguaggio di programmazione super sofisticato sono stati scritti questi intelligentissimi robottini? C++? Assembler?
Guardate questo video e cercate di scoprirlo:

Se non ci siete riusciti ecco un’immagine che mostra il listato:

Aspetta un attimo, questo non è C, questo è Javascript!!!
Il codice pare avere una qualche forma di interazione con un web server e con Flash, ma onestamente dubito che sia possibile conquistare l’universo tramite un popup :D
Tra l’altro il codice è preso da un sito di una banca realmente esistente, la RBC Royal Bank, nel quale esso viene utilizzato per caricare un’animazione flash che ti assiste nella navigazione…
Assurdo, io non avrei mai pensato che con Javascript si potesse arrivare a tanto :o

Via : Worse Than Failure

Protoflow - l’effetto coverflow di iTunes realizzato in javascript con Prototype e Script.acolo.us.

Sabato, Marzo 15th, 2008

Protoflow è uno script Javascript che permette di scorrere tra varie immagini attraverso un gradevole effetto di transizione, in modo molto simile all’effetto coverflow di iTunes.
Addirittura è possibile attivare opzionalmente l’effetto specchio sulle immagini: molto 2.0 :D
Certamente è molto adatto per menu e photogallery, anche perchè grazie al fatto di essere perfettamente degradabile non mina la navigazione con javascript disabilitato.
Esso si appoggià sulla già collaudata accoppiata Prototype Scriptacolous ed è molto semplice da implementare.

Uno script simile era già disponibile per MooTools, anche se Protoflow pare essere nettamente più veloce.

WebCanvas: l’apoteosi del tag canvas e di javascript.

Venerdì, Febbraio 29th, 2008

WebCanvasL’elemento html canvas è sicuramente uno dei più innovativi, non a caso esso permette al browser di giocare con la grafica 2D/3D e ad ottenere risultati piuttosto sorprendenti.
A dimostrazione delle potenzialità offerte da canvas in combinazione con Javascript è stata lanciata una web application di nome WebCanvas che permette di disegnare su un muro virtuale utilizzando pennelli, gomme e matite, proprio come in paint.
La novità non stà tanto in quello che permette di fare l’applicazione ( un pò inutile in fondo visto che il muro è condiviso ) tanto nel fatto che essa è realizzata interamente in Javascript senza l’ausilio di Flash.

Starordinario, vero? :o

Ovviamente con IE il discorso è totalmente diverso, tale browser non supporta canvas e quindi l’applicazione sarà fruibile solo nella versione Flash ( di certo non è il problema principale a cui devono pensare a Redmond :D )

Arriva DOMAssistant 2.6: la sfida ai maggiori framework è lanciata.

Venerdì, Febbraio 22nd, 2008

DOMAssistant è un framework ( libreria? ) javascript di Robert Nyman. Pur essendo un progetto abbastanza maturo finora, a causa della poca pubblicità, aveva sempre trovato poco spazio tra gli sviluppatori.

Detto fatto: Robert ha pubblicato un sito dedicato al progetto e soprattutto ha creato una pagina di testing che mostra chiaramente come i selettori css siano enormemente più veloci in DOMAssistant che in altri framework più blasonati come jQuery ed Ext.

C’è da dire che le API di DOMAssistant sono parecchio più limitate se paragonate a quelle degli “avversari”, oltre a ciò nonostante il codice sia velocissimo alcune parti mi lasciano del tutto perplesso, come ad esempio una regex di 40-50 caratteri ripetuta due volte all’interno del codice…
Tali miei dubbi vengono confermati dal fatto che a parità di peso jQuery fa molte più cose.

Mi sa che Robert ci deve lavorare ancora un pò :D Comunque resta sempre un’ottima scelta se volete qualcosa di leggero e veloce.

Uno strano ( il + strano ) comportamento di Internet Explorer.

Sabato, Febbraio 16th, 2008

Questo è sicuramente uno dei comportamenti più strani che abbia mai visto in un browser. Guardate il seguente codice:

setInterval(function() {
  alert("test");
}, -1)

Esso invoca il setInterval con un intervallo negativo.
Come si comportano i browser in questo caso?
Firefox, Opera, Safari e i browser aderenti al W3C si comportano nel modo più logico eseguendo la funzione con l’intervallo di tempo più piccolo possibile.
In Internet Explorer tale codice si comporta in maniera assolutamente incredibile: la funzione viene eseguita ogni qual volta si clicca col tasto sinistro in un qualsiasi punto! :o
Io mi chiedo se dietro questi misteri ci sia una specie di logica perversa, ma onestamente preferisco non saperlo :)

Via: John resig