When the widget is disabled, and clearItems() is called when the widget has more than one tag, it leaves phantom tags in the widget.
To reproduce:
- Open the demos page and find the first TagMultiselectWidget. Open its command line.
- Enter widget.setValue( [ 'a', 'b' ] );
- The widget will be showing tags 'a' and 'b'.
- Enter widget.setDisabled( true );
- The widget will become disabled, and oddly will change the order of the tags.
- Enter widget.clearItems();.
- The widget will remove the 'b' tag, but 'a' will be left behind.
- Enter widget.getValue();
- The console will report that the value was "", despite the widget displaying 'a'.
- Enter widget.setDisabled( false );
- The widget will be enabled, but the phantom 'a' tag will remain disabled.
- Enter widget.setValue( [ 'c', 'd' ] );
- The widget will display normal tags 'c' and 'd' after the phantom 'a' tag.
Analysis:
This seems to have been caused by rGOJUaca140acaf80: TagMultiselectWidget: Handle disabled items.
When the TagMultiselectWidget widget is disabled, it disables all its tags. And when a tag fires its 'disabled' event, TagMultiselectWidget moves it to the start of its list. That explains the weird order changing in step 3.
In TagMultiselectWidget's clearItems() method, it loops over all the items to set the item's group to null and then detach it from the DOM.
for ( i = 0, len = this.items.length; i < len; i++ ) { this.items[ i ].setElementGroup( null ); this.items[ i ].$element.detach(); }
But the group setting triggers a call to updateDisabled(), which fires 'disabled', which causes TagMultiselectWidget to move the item to the start, so this.items[ i ] no longer refers to the same item for the detach() call.
IMO the best fix would be to change the "move any disabled item to the start" logic so it doesn't weirdly reorder all the tags when the widget as a whole is disabled. You could probably accomplish this by moving the newly-disabled item to just before the first still-enabled item.