Une ligne ne renvoie pas pareil sur Chrome et sur Firefox. Chez moi, je ne la vois que sur des HTMLSelectElement
.
En fait j’ai l’impression que les HTMLSelectElement
n’ont pas le même type de constructeur entre Firefox et Chrome. sur Chrome, le test typeof(obj.constructor) == 'function'
renverra true
pour un HTMLSelectElement
. Sur Firefox, il renverra false
.
Sauf que pour le coup, c’est le résultat de Firefox que je veux obtenir sous Chrome. Donc je veux que dans le cas d’un HTMLSelectElement
, Chrome me renvoie false
.
Exemple : Prenez un select dans votre page, et faites un truc genre :
<select name="shipping_country_id" id="shipping_country_id" onfocus="isCollection(this);" > <option title="France métropolitaine" value="FR" selected="selected">France métropolitaine</option> <option title="Royaume uni" value="RK">Royaume uni</option> </select>
En fait, c’est le inCollection(this)
qui va créer un HTMLSelectElement
(ce que ferait également un document.getElementById('shipping_country_id')
, mais pas un $('#shipping_country_id')
).
La ligne :
isCollection = function(obj) { var bool = (obj && (obj.constructor == Object || typeof(obj.constructor) == 'function') && typeof(obj.add) == 'function' && typeof(obj.remove) == 'function' && typeof(obj.length) == 'number'); Util.Debug(bool); if(bool){ Util.Debug("obj : "+obj); Util.Debug("obj.constructor : "+obj.constructor); Util.Debug("obj.innerHTML : "+obj.innerHTML); //permets de retrouver l'element dans la page car le toString du obj ne renvoie souvent pas grand chose Util.Debug("typeof(obj.add) : "+typeof(obj.add)); Util.Debug("typeof(obj.remove) : "+ typeof(obj.remove)); Util.Debug("typeof(obj.length) : "+typeof(obj.length)); } return bool; }
Avec une fonction Util.Debug ressemblant à ça :
Util.Debug = function(message){ if (typeof(console) != "undefined") { // firebug, safari if (!console.debug) { // console Safari window.console.log(message); } else { // Firebug window.console.debug(message); } } }
La correction
Rajouter le test obj.constructor != HTMLSelectElement
pour la variable bool
, qui devient du coup :
var bool = (obj && (obj.constructor == Object || (typeof(obj.constructor) == 'function' && obj.constructor != HTMLSelectElement))) && typeof(obj.add) == 'function' && typeof(obj.remove) == 'function' && typeof(obj.length) == 'number');
Alors on peut aussi dire que l’instruction suivante fonctionne très bien :
var bool = (obj && obj.constructor == Object) && typeof(obj.add) == 'function' && typeof(obj.remove) == 'function' && typeof(obj.length) == 'number');
Sauf que dans ce cas, les objets itérables envoyés par Jquery ne sont pas considérés comme des collections. D’où la necéssité de rajouter d’abord le typeof(obj.constructor) == 'function'
afin qu’ils soient pris en compte, puis de corriger l’effet de bord sur les objets HTMLSelectElement
avec obj.constructor != HTMLSelectElement
.
Un problème vu ailleurs mais avec les NodeList
Notez que j’ai cherché plusieurs jours avant de trouver mon problème, et j’ai notamment vu chez StackOverFlow que la gestion par Chrome et Firefox des NodeList
n’était pas la même :
the value of result in chrome / safari / opera is ‘[object NodeList]’.
In firefox and IE 9 , it is ‘[object HTMLCollection]’.
Donc il y a des chances que d’autres objets soient dans ce cas…