Est-ce que selectedOptions est cassé ou …?

Remarque: cette question n'a rien à voir avec Knockout.js, mais il s'agit de l'attribut selectedOptions des éléments <select> place. C'est la référence:

Http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#dom-select-selectedoptions

Je pense que c'est une fonctionnalité intéressante pour les développeurs de Javascript. Le soutien est assez limité, mais il augmente de toute façon. Chrome, Opera et Safari devraient déjà le supporter.

Le problème, c'est que je ne peux pas comprendre comment cela fonctionne. Le comportement devrait être assez simple, en donnant une collection en direct des options sélectionnées, mais il s'avère que ce n'est pas le cas. Vous imaginez que SelectedOptions change chaque fois que l'utilisateur sélectionne une option, n'est-ce pas? Faux. J'ai préparé un cas de test:

Http://jsfiddle.net/f39cC/5/

Dans cet exemple, Opera 11.64 renvoie toujours la première valeur sélectionnée, peu importe ce que vous faites après, alors que Chrome 21 dev et 19 stable ont un comportement étrange. Effectuez les étapes suivantes:

  1. Sélectionnez 'One'. Dans la sortie et la console, vous obtenez "One", comme prévu.
  2. Sélectionnez 'Deux' aussi, en utilisant Ctrl. Dans la console, vous obtenez "One, Two", en sortie, il est encore "One".
  3. Sélectionnez 'Trois' aussi. Dans la console c'est "One, Two, Three", en sortie, il est "One, Two".
  4. Sélectionnez maintenant 'Deux' seulement. Dans la console, vous obtenez "Two", dans la sortie "Two ,," (remarquez les deux virgules).

Toutefois , si vous commentez la ligne console.log , vous obtenez toujours la bonne sortie. Vous pouvez obtenir le comportement attendu dans la console et la sortie si vous permettez les deux instructions, ou si vous stockez la valeur dans une chaîne séparée, comme dans ceci:

Http://jsfiddle.net/f39cC/2/

Alors, est-ce que je manque quelque chose sur selectedOptions ? Est-il trop tôt pour compter sur cette propriété, qui a probablement une implémentation de buggy? console.log est-il en console.log créer le problème sur Chrome? Y at-il quelque chose que je ne connais pas sur HTMLCollection s?

Je n'ai pas installé Safari, quelqu'un peut-il vérifier son comportement?

MISE À JOUR 18/2/2013 : Je ne sais pas quand les choses ont changé, mais Chrome 24.0.1312.57 et Opera 12.14 semblent bien fonctionner maintenant. Firefox 18.0.2 et Internet Explorer 10 doivent toujours implémenter la propriété.

MISE à JOUR 17/9/2013 : Firefox 24 et IE 11 preview doivent encore supporter la propriété. C'est une solution de rechange facile pour Firefox et IE8-11:

 Object.defineProperty(HTMLSelectElement.prototype, "selectedOptions", { get: (function() { try { document.querySelector(":checked"); return function() { return this.querySelectorAll(":checked"); }; } catch (e) { return function() { if (!this.multiple) { return this.selectedIndex >= 0 ? [this.options[this.selectedIndex]] : []; } for (var i = 0, a = []; i < this.options.length; i++) if (this.options[i].selected) a.push(this.options[i]); return a; }; } })() }); 

Pour IE8, il ne renvoie qu'un Array et non un NodeList .

MISE À JOUR 28/5/2014 : Il semble que Firefox a commencé à implémenter SelectedOptions depuis r25.

Il semble que le problème soit un peu plus profond qu'un simple bogue. Le fait que WebKit et Presto n'ont pas réussi à supporter selectedOptions correctement nous donne l'indice que cela dépend du fait que la propriété est censée être une HTMLCollection .

Maintenant, HTMLCollection s ont leur comportement en direct parce qu'ils sont invalidés par le moteur de rendu quand quelque chose arrive au DOM (le changement d'une classe, le retrait d'un nœud, etc.). Mais la propriété selected d'une option ne déclenche pas l'invalidation de la collection, ce qui rend sa fiabilité absolue.

Je suppose que le problème ici est de créer une nouvelle façon de rendre les collections en direct invalidées, et cela peut ne pas être très simple car cela peut affecter toute la manière dont le DOM est interprété et traité.

À l'heure actuelle, Chrome 21.0.1180.4 a la propriété de supprimer.

Je pense que cela n'a rien à voir avec JavaScript ou avec l'objet <select> DOM mais avec le shell de jsfiddle. Cependant, il ne devrait pas être le cas, il ne met pas à jour correctement la valeur de l'attribut innerHTML de la division de sortie. En insérant output.innerHTML = ''; En tant que première ligne de la fonction de gestionnaire d'événements, vous obtenez les résultats escomptés.