Ajout dynamique de code Javascript, différences entre les navigateurs (canHaveChildren)

Introduction

L'implémentation du bouton Google +1 est réalisée simplement avec le code ci-dessous :

<script type="text/javascript" src="https://apis.google.com/js/plusone.js">
      {lang:'fr', parsetags:'explicit'}
</script>

Pour réaliser dynamiquement en Javascript l'inclusion du script https://apis.google.com/js/plusone.js, la méthode createElement est utilisée. À propos de l'ajout et de la suppression d'éléments dans un arbre DOM : Ajout et suppression d'éléments avec Javascript - Suppression de document.write.

Avec la méthodologie de l'inclusion dynamique d'un script Javascript, l'ajout des paramètres {lang:'fr', parsetags:'explicit'} au script plusone.js présente en revanche quelques différences selon le navigateur utilisé (Internet Explorer, Firefox, Chrome, Opera...).

Cet article présente une méthode générique interopérable entre les navigateurs pour ajouter dynamiquement le code Javascript {lang:'fr', parsetags:'explicit'} et ceci grâce à la propriété canHaveChildren qui n'existe que pour Microsoft Internet Explorer

La problématique

L'inclusion avec createElement

L'inclusion dynamique du script plusone.js dans l'entête de la page ne présente pas de problème particulier une fois habitué à l'utilisation de la méthode createElement en Javascript :

v_head = document.getElementsByTagName("head")[0];
v_script_plusone = document.createElement ("script");
v_script_plusone.setAttribute("type","text/javascript");
v_script_plusone.setAttribute("async","true");
v_script_plusone.setAttribute("src","https://apis.google.com/js/plusone.js");
v_head.appendChild(v_script_plusone);

La propriété canHaveChildren de Microsoft Internet Explorer

L'ajout des paramètres {lang:'fr', parsetags:'explicit'} peut ensuite être envisagé tout naturellement avec les méthodes createTextNode et appendChild sur l'objet script créé dynamiquement à l'étape précédente :

var v_parms = document.createTextNode('{lang:"fr", parsetags:"explicit"}');
v_script_plusone.appendChild(v_parms);

Cette méthode fonctionne très bien pour FireFox et Chrome, en revanche Internet Explorer lève une erreur Javascript "Demande d'accès à la méthode ou aux propriétés inattendues".

Pour Internet Explorer (7 et 8), l'ajout d'un élément avec appendChild sur un objet de type script est interdit. Pour que cela fonctionne avec IE, le code Javascript est donné dans la propriété text de l'objet script :

var v_parms = '{lang:"fr", parsetags:"explicit"}';
v_script_plusone.text = v_parms;

La propriété canHaveChildren propriétaire à Internet Explorer s'avère très utile pour gérer le contexte multi navigateurs :

  • canHaveChildren retourne false sous IE pour un objet de type script.
  • canHaveChildren est indéfini (null) pour FireFox ou Chrome.

D'où le code final qui fonctionne pour tous les navigateurs en analysant l'existence de la propriété canHaveChildren :

v_parms = '{lang:"fr", parsetags:"explicit"}';

if (v_script_plusone.canHaveChildren == null 
              || v_script_plusone.canHaveChildren)
{
  /* Firefox, Chrome */
  v_script_plusone.appendChild(document.createTextNode(v_parms));
}
else { 
  /* Internet Explorer */
  v_script_plusone.text = v_parms;
}