(I can't find it, but then again I don't really know how to search for it.)
I want to use <input list=xxx>
and <datalist id=xxx>
to get autocompletion, BUT I want the browser to match all options by 'contains' approach, instead of 'starts with', which seems to be standard. Is there a way?
If not simply, is there a way to force-show suggestions that I want to show, not those that the browser matched? Let's say I'm typing "foo" and I want to show options "bar" and "baz". Can I force those upon the user? If I just fill the datalist with those (with JS), the browser will still do its 'starts with' check, and filter them out.
I want ultimate control over HOW the datalist options show. NOT over its UI, flexibility, accessibility etc, so I don't want to completely remake it. Don't even suggest a jQuery plugin.
If I can ultimate-control form element validation, why not autocompletion, right?
edit: I see now that Firefox does use the 'contains' approach... That's not even a standard?? Any way to force this? Could I change Firefox's way?
edit: I made this to illustrate what I'd like: http://jsfiddle.net/rudiedirkx/r3jbfpxw/
[list]
datalist
So what's the difference between the autocomplete attribute and datalists? The autocomplete attribute tells the browser whether to give a user options for completion based on previous input and whether to store the entered value for future completion.
The <datalist> tag is used to provide an "autocomplete" feature for <input> elements. Users will see a drop-down list of pre-defined options as they input data.
The <datalist> tag is used to provide autocomplete feature in the HTML files. It can be used with an input tag so that users can easily fill the data in the forms using select the data.
The HTML <datalist> tag is is used to provide an auto complete feature on form element. It provides a list of predefined options to the users to select data. The datalist tag is introduced in HTML5. The <datalist> tag should be used with an <input< element that contains a "list" attribute.
'contains' approach
Maybe this is what you are looking for (part 1 of your question).
It goes with the limitation of "starts with" and changes when a selection is made.
'use strict'; function updateList(that) { if (!that) { return; } var lastValue = that.lastValue, value = that.value, array = [], pos = value.indexOf('|'), start = that.selectionStart, end = that.selectionEnd, options; if (that.options) { options = that.options; } else { options = Object.keys(that.list.options).map(function (option) { return that.list.options[option].value; }); that.options = options; } if (lastValue !== value) { that.list.innerHTML = options.filter(function (a) { return ~a.toLowerCase().indexOf(value.toLowerCase()); }).map(function (a) { return '<option value="' + value + '|' + a + '">' + a + '</option>'; }).join(); updateInput(that); that.lastValue = value; } } function updateInput(that) { if (!that) { return; } var value = that.value, pos = value.indexOf('|'), start = that.selectionStart, end = that.selectionEnd; if (~pos) { value = value.slice(pos + 1); } that.value = value; that.setSelectionRange(start, end); } document.getElementsByTagName('input').browser.addEventListener('keyup', function (e) { updateList(this); }); document.getElementsByTagName('input').browser.addEventListener('input', function (e) { updateInput(this); });
<input list="browsers" name="browser" id="browser" onkeyup="updateList();" oninput="updateInput();"> <datalist id="browsers"> <option value="Internet Explorer"> <option value="Firefox"> <option value="Chrome"> <option value="Opera"> <option value="Safari"> </datalist>
Edit
A different approach of displaying the search content, to make clear, what happens. This works in Chrome as well. Inspired by Show datalist labels but submit the actual value
'use strict'; var datalist = { r: ['ralph', 'ronny', 'rudie'], ru: ['rudie', 'rutte', 'rudiedirkx'], rud: ['rudie', 'rudiedirkx'], rudi: ['rudie'], rudo: ['rudolf'], foo: [ { value: 42, text: 'The answer' }, { value: 1337, text: 'Elite' }, { value: 69, text: 'Dirty' }, { value: 3.14, text: 'Pi' } ] }, SEPARATOR = ' > '; function updateList(that) { var lastValue = that.lastValue, value = that.value, array, key, pos = value.indexOf('|'), start = that.selectionStart, end = that.selectionEnd; if (lastValue !== value) { if (value !== '') { if (value in datalist) { key = value; } else { Object.keys(datalist).some(function (a) { return ~a.toLowerCase().indexOf(value.toLowerCase()) && (key = a); }); } } that.list.innerHTML = key ? datalist[key].map(function (a) { return '<option data-value="' + (a.value || a) + '">' + value + (value === key ? '' : SEPARATOR + key) + SEPARATOR + (a.text || a) + '</option>'; }).join() : ''; updateInput(that); that.lastValue = value; } } function updateInput(that) { var value = that.value, pos = value.lastIndexOf(SEPARATOR), start = that.selectionStart, end = that.selectionEnd; if (~pos) { value = value.slice(pos + SEPARATOR.length); } Object.keys(that.list.options).some(function (option) { var o = that.list.options[option], p = o.text.lastIndexOf(SEPARATOR); if (o.text.slice(p + SEPARATOR.length) === value) { value = o.getAttribute('data-value'); return true; } }); that.value = value; that.setSelectionRange(start, end); } document.getElementsByTagName('input').xx.addEventListener('keyup', function (e) { updateList(this); }); document.getElementsByTagName('input').xx.addEventListener('input', function (e) { updateInput(this); });
<input list="xxx" name="xx" id="xx"> <datalist id="xxx" type="text"></datalist>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With