Tristan Jahier Tristan Jahier - 1 month ago 16
Javascript Question

Chosen: retrieve the UI container from the raw select DOM element

I use Harvest's Javascript library to enhance

<select>
elements.

https://github.com/harvesthq/chosen

This library creates a
<div>
element along with the original
<select>
. This
<div>
contains the Chosen enhanced UI:

<select multiple id="my-list" class="chosen">
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
<option value="4">Four</option>
<option value="5">Five</option>
</select>

<div class="chosen-container chosen-container-multi ..." id="my-list_chosen">
<ul class="chosen-choices">
<li class="search-choice">
<span>Three</span>
<a class="search-choice-close" data-option-array-index="2"></a>
</li>
<li class="search-choice">
<span>Five</span>
<a class="search-choice-close" data-option-array-index="4"></a>
</li>
....
</ul>
...
</div>


I would like to retrieve this Chosen UI container (the
<div>
), given that I only know the original
<select>
element. The challenge is that there may be more than 1 multiple select in the HTML document.

The easy case is when the
<select>
element has an ID, so the Chosen UI container has the same ID suffixed with
_chosen
, as you can see in the above snippet.

But Chosen does not require elements to have and ID attribute to work. So what about multiple
<select>
elements with no ID? What is the proper way to identify the Chosen UI container?

[EDIT] For those who wonder why I can't assume there is an "id" attribute on the
<select>
: I wrote a small plugin to handle selection order for Chosen, and I can't force users to put an ID on the
<select>
while Chosen does not require it itself.

Answer

Finally I've found a workaround. There is no proper way to get the container provided by Chosen.

[Update] : according to this comment on Github, there is "officially" no proper way to get the Chosen UI element with PrototypeJS.

With jQuery plugin

I've look into the CoffeeScript code of Chosen, and found something interesting. If you're using Chosen plugin for jQuery, the Chosen instance is stored locally thanks to jQuery data() function.

You can retrieve the Chosen UI container this way:

$(my_select).data("chosen").container[0]

The general case

Unfortunately, with PrototypeJS plugin, there is no trick like that.

But we can make an hypothesis in the general case: the Chosen UI container is the first next sibling of the raw <select> element. This assumption is quite strong because, unless something moves the <select> or the Chosen container dynamically, this will always be true.

Here is a not so bad solution, using the 2 different frameworks:

Using PrototypeJS

my_select.next(".chosen-container.chosen-container-multi")

Using jQuery

$(my_select).next(".chosen-container.chosen-container-multi").get(0)
Comments