
Rendre son Javascript compatible
Vous êtes ici : Accueil
/ Articles
/ Formations en Javascript
Le Javascript est un langage qui a été longtemps délaissé par les développeurs web en raison de ses problèmes de compatibilité, à tel point qu’il était souvent nécessaire de créer un script en fonction de chaque navigateur. La création du DOM a grandement contribué à normaliser les langages. Actuellement, il est possible de créer du code compatible, sous peine de prendre quelques précautions.
Cet article ne présentera pas une liste exhaustive des incompatibilités Javascript entre les navigateurs, mais servira plus à donner une solution globale de résolution des divergences de syntaxe.
Les navigateurs étudiés seront Mozilla Firefox et Microsoft Internet Explorer. La plupart des autres navigateurs est compatible avec Firefox.
Il est à noter que le Javascript manipulant du html et du CSS, il est nécessaire de rendre compatible ces autres langages pour que l’affichage soit le même. Nous ne traiterons ici que du langage Javascript.
Résolution de petites incompatibilités
Il existe un certain nombre de petites incompatibilités entre les navigateurs étudiés. Nous allons prendre un exemple et le résoudre.
Prenons le cas des classes CSS :
Sous Mozilla Firefox, on accède à la propriété par le code suivant :
var classe = document.getElementById( 'monId' ).getAttribute('class');
Sous Internet Explorer, le code précédent ne retournera rien. Il faut utiliser un autre code :
var classe = document.getElementById( 'monId' ).className;
Comme vous le voyez, il semble nécessaire de devoir créer 2 codes différents en fonction du navigateur. Pour résoudre ce problème, il faut maîtriser la notion de prototypes :
Le javascript n’est pas un langage orienté objet, mais orienté prototype. Cela permet notamment de gérer l’héritage et de définir des méthodes pour tous les objets d’un même type.
Un prototype est un objet dont les propriétés et méthodes seront appelées si celles de la classe enfant n’existent pas.
Exemple d’utilisation de prototype :
function MonPrototype() {
this.sayHello = function() {
alert( 'Hello' );
}
}
function MaClasse() {
}
MaClasse.prototype = new MonPrototype();
var a = new MaClasse();
a.sayHello();
Les prototypes présentent en outre l’avantage de ne stocker la méthode qu’à un seul endroit dans la mémoire puisque l’objet prototype est partagé par toutes les instances de la classe.
Mozilla Firefox met à notre disposition les classes à l’origine des objets HTML. Par exemple, un div est une instance de HTMLDivElement.
Nous allons donc pouvoir modifier le comportement de toutes les balises div en changeant le prototype de l’objet HTMLElement sous Mozilla Firefox.
Une seconde notion à assimiler est les Setters et les Getters sous Mozilla Firefox. Un getter est une méthode appelée lors de la lecture d’une propriété. Un setter est une méthode appelée lors de son écriture. La syntaxe est la suivante :
var monObjet = { _propriete : 1 };
monObjet.__defineGetter__( 'propriete', function() {
return this._propriete;
} );
monObjet.__defineSetter__( 'propriete', function( valeur ) {
this._propriete = valeur;
} );
alert( monObjet.propriete );
Les getters et les setters présentent l’avantage de pouvoir controler totalement la manipulation des propriétés.
Voici donc une solution au problème de compatibilité :
<div id="monDiv" class="test"></div>
<script type="text/javascript">
if( typeof HTMLElement != 'undefined' ) {
HTMLElement.prototype.__defineGetter__( 'className', function() {
return this.getAttribute( 'class' );
} );
}
var o = document.getElementById( 'monDiv' );
alert( o.className );
</script>
La syntaxe précédente semble bien plus lourde qu’une simple condition et l’utilisation d’une syntaxe pour chaque navigateur. Cette première partie a servi à faire comprendre le principe de résolution de problèmes par un cas concret. Nous allons maintenant aborder la question d’un point de vue plus général bien que le principe soit le même.
Méthode globale de résolution
La méthode globale de résolution de problèmes de compatibilité réside en la création de ce qu’on appelle une couche de virtualisation. Cela consiste à créer un ensemble de fonctions au plus bas niveau du navigateur pour creer un navigateur générique, disposant d’un certain nombre de fonctionnalités, peu importe la manière dont il est implémenté pour chaque navigateur.
Cette technique, largement répandue dans le monde du développement, est certainement une des meilleurs solutions. Si vous observez le code source de windows live hotmail, vous remarquerez la présence de fichiers spécifiques à chaque navigateur, ne définissant pas de fonctions au niveau métier, mais uniquement des lignes de codes pour augmenter la compatibilité.
La question logique qui s’ensuit est : comment implémenter cette couche de virtualisation ?
Il est inutile de créer un script pour chaque navigateur : il suffit d’en prendre un pour référence et de créer les fonction nécessaires pour que les autres navigateurs disposent des mêmes fonctionnalités. Attention, ne tombez pas dans le piège du choix du meilleur navigateur ou de celui présentant les fonctionnalités les plus puissantes :
Le premier mouvement, et il est tout à fait compréhensible, serait de vouloir faire tendre Internet Explorer vers Mozilla Firefox, lequel est beaucoup plus maniable et corresponds plus aux normes du W3C. Cependant, pour créer une couche de virtualisation, il faut que le navigateur aie une capacité suffisament grande à évoluer et certaines fonctionnalités de Mozilla Firefox ( notamment les getters, les setters et les prototypes de éléments html ) le rendent plus apte à tendre vers Internet Explorer que l’inverse.
La solution serait donc d’émuler Internet Explorer sous Mozilla Firefox. Les partisans convaincus de la primauté légitime de Firefox se consoleront en pensant que ces histoires de compatibilité ne sont que temporaires et que nous tendons vers une normalisation toujours plus stricte.
Et maintenant ?
La complexité de la création de scripts Javascript n’est pas un problème récent. Ce problème existe depuis longtemps et des développeurs compétents se sont déjà penchés sur la question et ont développé des solutions sous formes de framework.
Parmi les plus connus, Prototype, jQuery, Archetype..
Il est intéressant de connaître les dessous des choses, mais évitez de réinventer la roue et pensez à réutiliser le travail fourni par des personnes qui connaissent parfaitement ces problèmes et sont donc bien plus habilités à les résoudre.
Commentaires
Gros a dit le 23 décembre 2009
Même si je suis assez d’accord avec l’histoire du tour de roue et que, comme tout le monde, je "m’inspire" de quelques gourous, je ne vois pas l’utilité d’utiliser une surcharge sur les fonctions, propriétés, methodes de la part de frameworks ou librairies qui alourdit le code et n’apporte pas un gain syntaxique flagrant. Cela dit, ça fait quelques temps que je vous ai bookmarké, j’ai pris un peu la peine de m’arrêter un peu plus aujourd’hui sur votre blog, et tout ca pour vous dire que je le trouve intéressant même si complètement largué lorsqu’il s’agit de maths ;-) Bonne continuation..
Ludovic PATEY a dit le 23 décembre 2009
Merci pour votre intérêt.
En ce qui concerne les frameworks, on leur trouve un intérêt lorsque l’on commence à utiliser pleinement leurs fonctionnalités. Pour ma part, ma productivité a augmenté d’au moins 50% depuis que j’utilie jQuery.