Entfernen von Optionen aus ausgewählten und angehängten Änderungen

8

Ich habe gerade ein seltsames Verhalten beim Entfernen und erneuten Anhängen von Optionen an ein ausgewähltes Element festgestellt. Wenn eine der Optionen ausgewählt ist, wird nach dem Anhängen der nächste Eintrag anstelle des ursprünglichen ausgewählt. Betrachten Sie den folgenden HTML:

%Vor% %Vor%

(Oder als Geige )

Es wird die Option mit dem Wert "D" ausgewählt und nicht die Option mit dem Wert "C" , wie ursprünglich definiert. Beachten Sie die in der Konsole gedruckten Optionen, das Attribut selected wird nach der Methode remove() geändert.

Warum passiert das?

Hinweis: Ich kann das Problem beheben oder es umgehen, das ist nicht die Frage. Die Frage ist, warum passiert es?

    
DontVoteMeDown 25.09.2015, 12:46
quelle

1 Antwort

4

Faszinierende Frage.

Ich glaube, dass der Browser automatisch eine Option auswählt, wenn die einzige ausgewählte Option entfernt wird, und was dann passiert, wenn Sie eine Option in eine Box einfügen, für die das Flag selected gesetzt ist. Es scheint auch browserspezifisch zu sein, was uns wahrscheinlich nicht überraschen sollte. Aber mehr noch, Chrome variiert sein Verhalten, je nachdem, wie genau wir es sehen. Diese überraschte mich . Details unten.

Zuerst verwenden wir etwas wie Ihr aktualisiertes Beispiel, aber wo dasjenige, mit dem wir anfangen, ist weder das erste noch das letzte und sehen Sie, wo wir landen. Also haben wir A, B, C, D und E und beginnen mit B ausgewählt:

%Vor% %Vor%

Die Ergebnisse, die wir beobachten, variieren je nach Browser:

  • Chrome endet auf C, der eine nach derjenige, der am Anfang ausgewählt wurde (nicht der letzte).
  • IE11 endet auf B, was bedeutet, dass nicht erscheint, um die ausgewählten Flags beim Entfernen / Hinzufügen zu ändern.
  • Firefox landet auf E (der letzte).

Zu allem Überfluss variiert das Verhalten von Chrome , je nachdem, ob wir die Eigenschaft selected der Elemente beobachten oder nicht. Heisenbug! Wenn wir es beobachten, endet es damit, was Firefox (E) statt C tut.

Das gibt uns einen großen Hinweis darauf, was in Chrome passiert. Aber fangen wir mit den einfachen an:

IE11

Es sieht so aus, als ob IE11 die Flags einfach alleine lässt, wahrscheinlich weil es sich nicht darum kümmert, sie zu aktualisieren, während der JavaScript-Code läuft, nur wenn es zurückgibt und IE seine Benutzeroberfläche aktualisiert.

Firefox

Firefox macht Sinn, wenn es proaktiv ist, das selected -Flag auf eine Option zu setzen, wenn in der Box keine ausgewählt ist (weil wir die ausgewählte entfernt haben):

  1. Wir entfernen A, B bleibt ausgewählt.
  2. Wir entfernen B, C wird ausgewählt, weil B nicht mehr in der Box ist und die Box mindestens eine ausgewählte Option haben muss. Das Flag der entfernten Option bleibt gesetzt, was in einer Minute wichtig ist
  3. Schritt 2 wird wiederholt, wenn wir C und D entfernen.
  4. Wir entfernen E. An diesem Punkt haben C, D und E das Flag gesetzt.
  5. Wir fügen A zur Box hinzu. Da es die einzige Option der Box ist, wird ihr selected Flag gesetzt.
  6. Wir fügen B zur Box hinzu. Da Bs selected -Flag gesetzt ist, wird es zur ausgewählten Eigenschaft und A wird deaktiviert.
  7. Schritt 6 wiederholt sich, wenn wir C, D und E hinzufügen.
  8. Wir enden mit E ausgewählt.

Wir können IE11 und Firefox beobachten, da sie ihr Verhalten nicht ändern, je nachdem, ob wir sie beobachten:

%Vor% %Vor% %Vor%

Chrome

Was uns zu dem schwierigen bringt: Chrome. Chrome ändert sein Verhalten basierend darauf, ob wir die selected -Eigenschaft beobachten, während wir fortfahren. Insbesondere ändert es sein Verhalten, wenn wir selected auf den Optionen beobachten, die sich noch im Auswahlfeld befinden, wenn wir sie entfernen. Es macht nichts, wenn wir selected auf die entfernten schauen, und es ist uns egal, ob wir selected so betrachten, wie wir uns anhängen. Genau wie wir entfernen, und nur diejenigen, die wir noch nicht entfernt haben.

Erstens, hier ist der Beweis:

%Vor% %Vor% %Vor%

Wenn Sie eine Drehung machen (natürlich in Chrome), werden Sie bemerken, dass Sie auf C landen, unabhängig davon, was Sie mit dem ersten oder letzten Kästchen tun. Wenn Sie das mittlere Kästchen markieren, landen Sie bei E.

Das gibt uns genügend Daten, um eine Erklärung zu folgern . Ich kann es eigentlich nicht sagen ist die Erklärung, nur dass es zu den verfügbaren Daten passt. Wenn jemand genauer sein möchte, könnte er in einem Debug-Build den internen Code von Chrome durchlaufen. Ich entschied, dass das Overkill war.

Hier ist meine Antwort, die ich noch einmal betonen möchte: abgeleitet :

  1. Chrome legt die selected -Eigenschaft für die HTMLOptionElement -Instanz träge fest. Das heißt, wenn Sie den Wert der Eigenschaft nicht lesen, überprüft Chrome nicht, ob die Eigenschaft den aktuellen Status widerspiegelt.
  2. Er liest die Eigenschaft selected , wenn ein change -Ereignis in die Warteschlange gestellt wird.
  3. Es wird kein change -Ereignis in die Warteschlange gestellt, wenn für diese Auswahlbox bereits eine aussteht.

Darauf basiert, was ich denke, passiert in Chrome:

  1. Wir entfernen A, B bleibt ausgewählt. Kein change -Ereignis, da sich der Wert nicht geändert hat.
  2. Wir entfernen B, C wird ausgewählt, weil B nicht mehr in der Box ist und die Box mindestens eine ausgewählte Option haben muss. Dadurch wird ein Ereignis change in die Warteschlange gestellt, das selected beobachtet und somit die Eigenschaft auf C setzt.
  3. Wir entfernen C.D wird ausgewählt (in gewissem Sinne), aber da ein change -Ereignis aussteht, wird kein neues change -Ereignis in die Warteschlange gestellt, und daher wird Ds selected nicht beobachtet und sein Wert wird nicht aktualisiert. Es bleibt false , obwohl wenn wir es lesen, würde es true .
  4. werden
  5. Gleich wieder beim Entfernen von D. Kein Änderungsereignis, keine Beobachtung.
  6. Am Ende haben wir die Optionselemente mit selected als true für B und C, aber keine für die anderen, weil D und E nicht beobachtet wurden, während sie die ausgewählte Option waren, und ihren Wert nicht aktualisiert haben . Wir wissen, dass dies ihre Werte sind, weil wir sie an diesem Punkt beobachten dürfen.
  7. Wir fügen die Elemente der Reihe nach wieder hinzu, und wie bei Firefox wird das vorherige Element durch das Hinzufügen eines Elements mit selected = true , wenn ein anderes Element bereits ausgewählt ist, deaktiviert. Also wird B abgewählt, wenn C hinzugefügt wird. C wird in Ruhe gelassen, wenn wir D und E hinzufügen, weil ihre Eigenschaft selected false ist.

Puh , das hat Spaß gemacht, das herauszufinden.

    
T.J. Crowder 25.09.2015, 12:58
quelle

Tags und Links