IE6 — 3 fonctions Javascript pour lutter contre le bug des classes multiples

Parmi les nombreux bugs qui affectent Internet Explorer 6, le bug des classes multiples apparait lorsqu’on utilise au moins deux classes CSS simultanément. Par exemple `.classe1.classe2` pour adresser des propriétés CSS aux éléments possédant à la fois `.classe1` et `.classe2`, ce qui est très pratique. Malheureusement, IE6 ne tient compte que de la dernière classe, soit `.classe2`, en l’occurrence. Une pratique répandue consiste simplement à se passer des classes multiples, ce que je fais depuis des années.

Malgré des débuts prometteurs, en 10 ans de bons et loyaux services sévices, Internet Explorer 6 ne s’est pas fait que des amis… [Illustration ci-contre par Mike Rohde]
«Die IE6, DIE!» Par Mike Rohde (rohdesign.com). Sous Licence CC.

Toutefois, il se trouve que dans le cadre d’un projet utilisant WordPress, j’avais besoin de styler différemment les images selon qu’elles possèdent une légende  ou pas, qu’elles soient alignées à droite, à gauche, au centre, pas du tout (à la folie, passionnément, etc.) et selon leur taille. Ce qui donne un nombre de combinaisons suffisamment important pour justifier l’utilisation des classes multiples, y compris dans IE6. En effet, dans mon cas, l’alignement des images fait partie intégrante du design qui doit (Must vs. Should) passer aussi dans IE6. Et non, en l’occurrence, le script kickie6.js n’est pas envisageable 😀

Dans l’idéal, il faudrait une fonction Javascript  pour détecter les classes multiples passées en paramètres afin d’obtenir en retour la concaténation des deux classes séparée par un tiret (ex. `.classe1-classe2`. N’étant pas développeur Javascript, j’ai fais appel aux bonnes volontés présentes sur Twitter. Quelques heures plus tard, plusieurs propositions surgirent.

Petit mais costaud, c’est jQuery

Quand on joue sur le web, jQuery est souvent de la partie. Il devient assez rare de faire l’économie d’un framework Javascript, quel qu’il soit. Voici deux méthodes pour ajouter une classe CSS afin de pallier les insuffisances d’Internet Explorer 6 en matière de gestion des classes multiples.

  1. La solution fournie par Florian (@_Florian_R) a le mérite de la simplicité et de l’efficacité. Il suffit de passer les classes multiples à la fonction `jQuery()` et d’ajouter la classe de son choix avec la méthode `addClass()`. Seul petit bémol, cette méthode oblige à parcourir tout le document à la recherche des deux classes.
    $(document).ready(function() {
        $(".classe1.classe2").addClass("classe1-classe2");
    });
  2. Allons plus loin avec Stéphane Rouillé (@stfr) — Web Developper, PHP and jQuery addictSa fonction permet,  au choix,  de remplacer les deux classes précédemment utilisées par une nouvelle classe (replace : true;) ou de les garder (replace : false;). Il est possible de spécifier le noeud DOM pour éviter de parcourir l’ensemble du document afin de ne pas gréver inutilement les performances déjà limitées de notre très cher (coûteux) IE6 !
    /*
    *	Merge multiple CSS classes in one.
    *	Just use : $('body').multipleClassCombiner();  in order to apply this filter on all multiple classes elements
    *	Take care : $('h1').multipleClassCombiner() will apply this filter on <h1>'s childrens. But you can easily modify it.
    *	Default delimiter : "-"
    *	Have Fun !
    *	@author Stéphane Rouillé (Twitter: @stfr)
    *	@date 2011-02-08
    *	Free to use, distribute, modify, etc etc...
    */
    (function($) {
    	$.fn.multipleClassCombiner=function(params){
    		var options={
    			delimiter:'-',
    			replace : true
    		};
    		$.extend(options,params);
    		var multipleClassElements=$(this).find("*[class*=' ']");	/* Oh god ! */
    		multipleClassElements.each(function(){
    			var classes=$(this).attr('class').trim().split(' ');
    			if(options.replace){
    				$(this).attr('class',classes.join(options.delimiter));
    			}else{
    				$(this).attr('class',$(this).attr('class')+' '+classes.join(options.delimiter));
    			}
    		});
    	}
    })(jQuery);

Regarde Maman, sans jQuery !

jQuery est souvent une bonne idée, mais de nombreux projets de sites internet ne nécessitent pas de framework. Mettre en place jQuery *juste* pour gérer les classes multiples dans IE6 n’est pas très raisonnable :  les utilisateurs de ce navigateur obsolète utilisent déjà des configurations assez modestes… Inutile, donc, de charger la mule 😉

C’est Edouard Cunibil (@DuaelFr) — Développeur web freelance certifié PHP — qui nous offre une fonction en pur Javascript. Pour utiliser `patchMultipleClass()`, il suffit de passer les classes multiples en paramètres, en ajoutant, le cas échéant, le noeud DOM impliqué dans la recherche. Par défaut, la fonction parcours tout le DOM à partir de `body`, mais rien ne vous empêche de limiter les dégâts à `#content`, par exemple.

function patchMultipleClass(classNames, parent)
{
    var children, current, classes, found, subfound, splitClassNames, joinClassNames;
    var i, j, k;
    splitClassNames = classNames.substr(1).split('.');
    joinClassNames  = splitClassNames.join('-');
    if (!parent) { parent = document.getElementsByTagName('body')[0]; }
    children = parent.children;
    for (i = 0 ; i < children.length ; ++i) {
        current = children[i];
        classes = current.className.split(' ');
        found   = true;
        for (j = 0 ; j < splitClassNames.length ; ++j) {
            subfound = false;
            for (k = 0 ; k < classes.length ; ++k) {
                if (classes[k] == splitClassNames[j]) {
                    subfound = true;
                    break;
                }
            }
            if (!subfound) {
                found = false;
                break;
            }
        }
        if (found) {
            if (current.className.indexOf(joinClassNames) == -1) {
                current.className += ' ' + joinClassNames;
            }
        }
        patchMultipleClass(classNames, current);
    }
}
if (window.attachEvent) {
   window.attachEvent("onload", function() {
       var parentElt = document.getElementById('content');
       patchMultipleClass('.wp-caption.alignright', parentElt);
       patchMultipleClass('.wp-caption.alignleft', parentElt);
       patchMultipleClass('.wp-caption.alignnone', parentElt);
       patchMultipleClass('.wp-caption.aligncenter', parentElt);
   });
}

Cibler uniquement IE6

Pour réserver ce traitement Javascript aux seuls navigateurs ne prenant pas en charge les classes multiples (IE5 — IE6), j’utilise les commentaires conditionnels :

<!--[if lte IE 6]>
    <script src="<?php bloginfo( 'stylesheet_directory' ); ?>/js/functions-ie6.js""></script>
<![endif]-->

Voilà, c’est fini !

J’espère que ces quelques précisions sur ces quelques fonctions Javascript permettant de gérer les classes multiples dans Internet Explorer 6 vous permettront de vous amuser. Je tiens une nouvelle fois à remercier Florian (@_Florian_R), Stéphane Rouillé (@stfr) et Edouard Cunibil (@DuaelFr) pour avoir planché nuitamment sur ce problème 🙂

N’hésitez pas à partager vos découvertes sur ce sujet, elles seront les bienvenues.

Merci également à tous ceux qui ont répondu d’une manière ou d’une autre à l’appel : @mgeoffray, @Remzz, @Tchesssss, @JeuneVeteran, @phenxdesign, @burninghat, @jcbrebion, @Darklg, @LDZintegratore, @naholyr, @piouPiouM, @cafenoirdesign, @rickdog, @studiohypehope.

Retrouvez-moi sur Twitter avec @br1o !