Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use HTML5 (datalist) autocomplete with 'contains' approach, not just 'starts with'

(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/

  • HTMLWG's specs on [list]
  • W3's specs on datalist
  • DavidWalsh example
  • HONGKIAT's summary on behaviors..?
like image 997
Rudie Avatar asked Mar 19 '15 20:03

Rudie


People also ask

How is autocomplete different from a 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.

Which element provides the autocomplete feature in a textbox Datalist?

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.

What is the use of Datalist tag in HTML?

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.

Which of the following is the new tag in HTML5 form button option Datalist?

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.


1 Answers

'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>
like image 168
Nina Scholz Avatar answered Oct 03 '22 13:10

Nina Scholz