Reputation: 255
My goal is to update a filter pane with server data corresponding to a dynamic input pane. The filter is rendered by Django Admin's filter_horizontal option. I thought it might be simpler and more lightweight to use Javascript rather than django-autocomplete-lite (also used here with filters, which I didn't understand).
To that end, I found some excellent code which interfaces with SelectBox.js (SelectBox is used by Django) which I use to update the filter pane after fetching data dynamically from the server based on the entered item.
The remaining piece to be done is to query the server based on the input. I wrote an Ajax function triggered by change events on the input pane. However, capturing events doesn't work because when 'Input' has autocomplete defined, Django (or SelectBox.js/SelectFilter.js) doesn't use a regular html input element but a span with ARIA roles attached.
<span class="select2-selection__rendered" id="select2-id_customer-container" role="textbox" aria-readonly="true" title="John Doe">John Doe</span>
Concerning roles such as the textbox role used here, see ARIA roles:
If you are implementing a composite widget, such as a combobox composed of a text box and a listbox, you need to manage the aria-activedescendant attribute using a handler.
According to the aria-activedescendant docs, it's something you add to the element to allow focus when surrounded by parent elements. If I just insert it as an element attribute using document.setAttribute() will it break something else in SelectFilter2.js or SelectBox.js, used by Django?
But even with that the input element is not listening to events. 'Click' works intermittently, 'change' and 'input' events not at all:
function detectCustomerDropdownChange() {
/* parent: */
document.getElementById('id_customer').setAttribute("aria-activedescendant", "select2-id_customer-container");
/* child: */
document.getElementById('select2-id_customer-container').setAttribute("aria-readonly", "false");
document.getElementById('select2-id_customer-container').addEventListener('input', updateFilterList);
}
(updateFilterList has an event.stopPropagation() as its first line)
UPDATE: I threw everything at this span, setting aria-readonly=false, aria-disabled=true, and contenteditable=true. Result: still no response to the 'input' event registered on the span.
Here's the complete code that Django/Select2/SelectBox + my attribute changes generates:
<select name="customer" data-placeholder="Start typing a name" required="" id="id_customer" class="admin-autocomplete select2-hidden-accessible" data-ajax--cache="true" data-ajax--delay="250" data-ajax--type="GET" data-ajax--url="/admin/autocomplete/" data-app-label="giraffe" data-model-name="appointment" data-field-name="customer" data-theme="admin-autocomplete" data-allow-clear="false" lang="en" data-select2-id="id_customer" tabindex="-1" aria-hidden="true" aria-activedescendant="select2-id_customer-container">
<option value="30" data-select2-id="26">John Doe</option>
</select>
<span class="select2 select2-container select2-container--admin-autocomplete select2-container--below select2-container--focus" dir="ltr" data-select2-id="1" style="width: 280px;">
<span class="selection">
<span class="select2-selection select2-selection--single" role="combobox" aria-haspopup="true" aria-expanded="false" tabindex="0" aria-disabled="false" aria-labelledby="select2-id_customer-container">
/* THE SPAN IN QUESTION */
<span class="select2-selection__rendered" id="select2-id_customer-container" role="textbox" aria-readonly="false" contenteditable="true" aria-disabled="true" title="John Doe">John Doe</span>
<span class="select2-selection__arrow" role="presentation"><b role="presentation"></b></span></span></span>
<span class="dropdown-wrapper" aria-hidden="true"></span>
</span>
(Please ignore missing closing span tags, too hard to edit with markdown.)
Upvotes: 0
Views: 288