22

When there is a long set of elements in a datalist, they will all get displayed with a scroll bar next to them. Is there an easy way to only display the top 5, and just cut the others off?

For example: http://jsfiddle.net/yxafa/

<input type="text" name="search" id="search" placeholder="type 'r'" list="searchresults" autocomplete="off">
<datalist id="searchresults">
    <option>Ray0</option>
    <option>Ray1</option>
    <option>Ray2</option>
    <option>Ray3</option>
    <option>Ray01</option>
    <option>Ray11</option>
    <option>Ray21</option>
    <option>Ray31</option>
    <option>Ray02</option>
    <option>Ray12</option>
    <option>Ray22</option>
    <option>Ray32</option>
    <option>Ray012</option>
    <option>Ray112</option>
    <option>Ray212</option>
    <option>Ray312</option>
    <option>Ray03</option>
    <option>Ray13</option>
    <option>Ray23</option>
    <option>Ray33</option>
    <option>Ray013</option>
    <option>Ray113</option>
    <option>Ray213</option>
    <option>Ray313</option>
    <option>Ray023</option>
    <option>Ray123</option>
    <option>Ray223</option>
    <option>Ray323</option>
    <option>Ray0123</option>
    <option>Ray1123</option>
    <option>Ray2123</option>
    <option>Ray3123</option>
</datalist>
unor
  • 87,575
  • 24
  • 195
  • 335
Gus
  • 1,797
  • 4
  • 20
  • 36
  • 1
    Come on! Interesting question, +1! Why there are no answers!? – Jacek Kowalewski May 28 '14 at 08:35
  • Well, i don't think this i possible atm. You can only reduce the set of displayed items by adding other requirement like `maxlength="4"` or `pattern="Ray[0123]\d"` – Möhre May 30 '14 at 09:57
  • Also note that, at the time of writing (May 2014) the `template` tag is only supported in Chrome, Opera Desktop, and Mozilla FF. [See here](http://caniuse.com/#search=template). Same for [`datalist`](http://caniuse.com/#search=datalist), + partial support for IE 10+ – webketje May 30 '14 at 12:20

3 Answers3

10

With some modern javascript and html you could do something like this.

Here's the document:

<template id="resultstemplate">
    <option>Ray0</option>
    <option>Ray1</option>
    <option>Ray2</option>
    <option>Ray3</option>
    <option>Ray01</option>
    <option>Ray11</option>
    <option>Ray21</option>
    <option>Ray31</option>
    <option>Ray02</option>
    <option>Ray12</option>
    <option>Ray22</option>
    <option>Ray32</option>
    <option>Ray012</option>
    <option>Ray112</option>
    <option>Ray212</option>
    <option>Ray312</option>
    <option>Ray03</option>
    <option>Ray13</option>
    <option>Ray23</option>
    <option>Ray33</option>
    <option>Ray013</option>
    <option>Ray113</option>
    <option>Ray213</option>
    <option>Ray313</option>
    <option>Ray023</option>
    <option>Ray123</option>
    <option>Ray223</option>
    <option>Ray323</option>
    <option>Ray0123</option>
    <option>Ray1123</option>
    <option>Ray2123</option>
    <option>Ray3123</option>
</template>
<input type="text" name="search" id="search"  placeholder="type 'r'" list="searchresults" autocomplete="off" />
<datalist id="searchresults"></datalist>

And here's the js:

var search = document.querySelector('#search');
var results = document.querySelector('#searchresults');
var templateContent = document.querySelector('#resultstemplate').content;
search.addEventListener('keyup', function handler(event) {
    while (results.children.length) results.removeChild(results.firstChild);
    var inputVal = new RegExp(search.value.trim(), 'i');
    var clonedOptions = templateContent.cloneNode(true);
    var set = Array.prototype.reduce.call(clonedOptions.children, function searchFilter(frag, el) {
        if (inputVal.test(el.textContent) && frag.children.length < 5) frag.appendChild(el);
        return frag;
    }, document.createDocumentFragment());
    results.appendChild(set);
});

And here's a live example: http://jsfiddle.net/gildean/yxafa/6/

Olli K
  • 1,610
  • 1
  • 16
  • 15
  • Just wonderin', why use `document.querySelector` in this case instead of `getElementById` when the latter is much faster & more efficient? http://jsperf.com/getelementbyid-vs-queryselector – webketje May 30 '14 at 12:14
  • 1
    It's just a nicer api to remember. And in this example we're only doing all of the selecting once, so it makes no difference. – Olli K May 30 '14 at 12:28
0

No javascript example:

  <input list="site" name="f" minlength="2" style="height:5.1em">
  <datalist id="site" style="height:5.1em;overflow:hidden">

Took me a minute :)

This uses CSS style and HTML attributes. PS: The minimum length should protect against empty submissions. However, you'll need to select the object and then hit backspace to see :|

Aeron R
  • 65
  • 7
  • 2
    a minute of experimenting, and a minute for explanation. I'm sure you can do better explanation of the settings. – Mike Castro Demaria Aug 07 '20 at 16:45
  • Oh yes, sorry. The extra entries will be hidden, because they will exceed the height of "5.1em". I've edited the example to include "overflow:hidden". – Aeron R Aug 12 '20 at 00:52
0

var search = document.querySelector('#search');
var results = document.querySelector('#searchresults');
var templateContent = document.querySelector('#resultstemplate').content;
search.addEventListener('keyup', function handler(event) {
    while (results.children.length) results.removeChild(results.firstChild);
    var inputVal = new RegExp(search.value.trim(), 'i');
    var clonedOptions = templateContent.cloneNode(true);
    var set = Array.prototype.reduce.call(clonedOptions.children, function searchFilter(frag, el) {
 if (inputVal.test(el.textContent) && frag.children.length < 5) frag.appendChild(el);
        return frag;
    }, document.createDocumentFragment());
    results.appendChild(set);
});
<template id="resultstemplate">
    <option>Ray0</option>
    <option>Ray1</option>
    <option>Ray2</option>
    <option>Ray3</option>
    <option>Ray01</option>
    <option>Ray11</option>
    <option>Ray21</option>
    <option>Ray31</option>
    <option>Ray02</option>
    <option>Ray12</option>
    <option>Ray22</option>
    <option>Ray32</option>
    <option>Ray012</option>
    <option>Ray112</option>
    <option>Ray212</option>
    <option>Ray312</option>
    <option>Ray03</option>
    <option>Ray13</option>
    <option>Ray23</option>
    <option>Ray33</option>
    <option>Ray013</option>
    <option>Ray113</option>
    <option>Ray213</option>
    <option>Ray313</option>
    <option>Ray023</option>
    <option>Ray123</option>
    <option>Ray223</option>
    <option>Ray323</option>
    <option>Ray0123</option>
    <option>Ray1123</option>
    <option>Ray2123</option>
    <option>Ray3123</option>
</template>
<input type="text" name="search" id="search"  placeholder="type 'r'" list="searchresults" autocomplete="off" />
<datalist id="searchresults"></datalist>