Include en javascript

Du nouveau dans la gestion du javascript, avec la découverte d'une astuce qui répond parfaitement aux besoins de ce site : appeler un fichier javascript à la manière des « include » PHP.

Rappelons d'abord les principes d'utilisation du javascript sur ce site : améliorer le comportement des pages, faciliter la consultation des documents mais sans que celle-ci en soit dépendante. Ainsi, tout le contenu reste accessible même si la gestion du javascript est désactivée dans votre navigateur (exception faite du moteur de recherche).

L'utilisation du javascript est donc ponctuelle : certaines fonctions sont présentes sur toutes les pages (le style switcher, le champ de recherche), d'autres sont plus spécifiques (les notes de bas de page en popup, les galeries d'images).

Jusque là, j'avais intégré les fonctions communes dans le fichier « script.js », qui était appelé dans toutes les pages. Suivait ensuite un appel de fichier spécifique en fonction des besoins : les fonctions nécessaires aux articles étaient par exemple placées dans « article.js », celles utiles aux brèves dans « breve.js », etc. Ce système avait cependant des défauts :

  • J'insérais dans certaines pages des fonctions dont elles n'avaient pas besoin. La fonction qui affiche les notes de bas de page en popup n'est par exemple utile que pour les articles qui possèdent de telles notes, ce qui n'est pas le cas de tous. Elle était pourtant présente dans tous les articles avec l'appel du fichier « article.js ».
  • La situation n'était pas dramatique avec des fonctions de petite taille. Mais voilà, j'ai développé une méthode de coloration syntaxique en javascript un peu plus complexe et un peu plus lourde. Placer cette fonction dans le même fichier que celle pour les notes en popup ou pour les galeries de photos rendait ce fichier « article.js » de moins en moins facile à manipuler.
  • Enfin, quelques fonctions devaient maintenant être appelées dans des documents différents : la coloration syntaxique était par exemple utilisée à la fois dans certains articles et dans certaines brèves.

La solution paraissait donc évidente : il fallait placer chaque fonction dans des fichiers distincts, un pour les notes en popup, un pour les galeries photos, un autre pour le style switcher, etc. 2 voies s'ouvraient ensuite à moi :

  • soit je configurais « Autoit-CMS » pour écrire les appels de fichiers javascript là où c'était nécessaire. Solution plutôt bancale et difficile à maintenir à long terme.
  • soit je trouvais un moyen d'insérer en javascript des appels de scripts.

Je réfléchissais depuis quelque temps à un équivalent à la fonction PHP include, qui permet d'insérer du code dans des pages web selon les besoins. En javascript, on peut très facilement lancer une fonction dans une page uniquement si une condition est respectée. On peut par ailleurs manipuler l'arborescence d'un document web à travers le DOM et y créer de nouveaux contenus (paragraphe, liens, listes, etc.). Insérer l'appel d'un fichier javascript si une condition lambda est remplie (« si la page est un article ou une brève et qu'il y a du code préformaté, alors insérer l'appel du script de la coloration syntaxique ») ne devait donc pas être très compliqué.

La réponse était à portée de main, mais comme souvent avec une idée que vous ne faites qu'effleurer, d'autres ont déjà trouver la solution. Et c'est le cas ici : après une brève recherche sur le web, je suis tombé sur un article de Stoyan Stefanov répondant point par point à ma demande.

La technique décrite par S. Stefanov et déclinée pour répondre à de multiples cas d'utilisation est d'une simplicité enfantine : pour insérer un appel de fichier javascript dans l'en-tête d'une page web, il suffit d'agir de la même manière que lorsqu'on crée n'importe quel autre noeud dans l'arborescence dom. Cette technique peut d'ailleurs s'appliquer aussi à l'insertion d'un appel à un fichier CSS :

// Insérer l'appel d'un fichier javascript ou css
// exemple : incFile('script.js');
function incFile(file) {
    var ext = file.substring(file.lastIndexOf('.')+1);
    switch (ext) {
        case 'js':
            var inc = document.createElement('script');
            inc.setAttribute('type','text/javascript');
            inc.setAttribute('src',file);
            break;
        case 'css':
            var inc = document.createElement('link');
            inc.setAttribute('type','text/css');
            inc.setAttribute('rel','stylesheet');
            inc.setAttribute('media','screen');
            inc.setAttribute('href',file);
            break;
        }
    document.getElementsByTagName('head').item(0).appendChild(head_inc);        
}

Dorénavant, les pages ne portent plus qu'un seul appel de fichier javascript dans leur code, script.js, qui fait office de « tour de contrôle » permettant d'insérer les appels de scripts quand il le faut.

Cette mutation a aussi entraîné la réécriture de certaines fonctions, réécriture qui sera décrite dans les brèves suivantes.

A lire :

STEFANOV, Stoyan. Javascript includes - yet another way of RPC-ing. PHPied.com,