vendredi 19 février 2010

Internet Explorer Element prototyping dans PyJS

Non, ceci n'est pas une nouvelle complainte sur les bugs d'IE, même si ça concerne un problème qui lui est spécifique. En effet, lors du développement de ma petite librairie PyJS, j'ai été confronté à ce problème.

Piqûre de rappel
Le prototypage des éléments du DOM se fait simplement sur la plupart des navigateurs, il suffit de modifier le prototype de l'objet Element
Element.prototype.myMethod = function () {
alert('useful method here');
};
Ainsi, tout les élément du DOM auront cette méthode :
var el = document.getElementById('some_id');
el.myMethod();
C'est assez génial, mais malheureusement, ça ne marche pas sous IE...

The IE way

La méthode pour modifier les élements du DOM sous Internet Explorer est assez particulière, et elle est limitée, nous verrons cela juste après. Voyons tout d'abord le Javascript :
// For IE
if (typeof Element === "undefined") {
Element = function(){};
}

Element.prototype.myMethod = function () {
alert('do something usefull here');
};
Evidemment, sous IE, le type Element n'existe pas. Maintenant, il faut lier les noeuds du document avec les méthodes de notre prototype. Nous allons avoir besoin d'un fichier spécial HTC. Par exemple :
<PUBLIC:COMPONENT>
<PUBLIC:METHOD NAME="myMethod" INTERNALNAME="_myMethod" />;
<script type="text/javascript">
var el = new Element;
_myMethod = el.myMethod;
</script>
</PUBLIC:COMPONENT>
Pour que ce fichier soit chargé, il faut utiliser une règle CSS :
<style>
* {
behavior: url(/lien/vers/le/fichier.htc);
}
</style>
Et là, magie, les noeuds du document courant possède tous la méthode myMethod.

Limitations de cette méthode

Encore une fois, IE va nous embêter. Les élements créés par la suite - que ce soit par la méthode crado innrtHTML ou en utilisant document.createElement - ne possèderont pas les méthodes précédemment liées. Il nous faut donc encore ajouter des hacks... Pour document.createElement, c'est simple, il nous suffit de remplacer la méthode native, par exemple comme ceci :
if (isIE) {
document._nativeCreateElement = document.createElement;

document.createElement = function(tag) {
var el = document._nativeCreateElement(tag);
el.myMethod = Element.prototype.myMethod;
return el;
};
}
Je vous laisse le soins de faire une boucle du meilleur cru pour assigner les méthodes du prototype Element. Pour ce qui est de la méthode innerHTML, deux solutions, soit l'éviter comme beaucoup le préconise, soit faire un parseur qui se charge de lier les méthodes aux éléments contenus. Pour les plus feignants d'entre vous, ma librairie contient un parseur basique ici.

0 commentaires:

Enregistrer un commentaire