2015-03-19 5 views
25

(ich es nicht finden können, aber dann wieder, weiß ich wirklich nicht, wie es zu suchen.)Verwenden HTML5 (Datalist) zum automatischen Vervollständigung mit ‚enthält‘ Ansatz, nicht nur ‚beginnt mit‘

I möchte <input list=xxx> und <datalist id=xxx> verwenden, um Autovervollständigung zu erhalten, ABER ich möchte, dass der Browser alle Optionen nach "enthält" Ansatz statt "beginnt mit", die Standard zu sein scheint. Gibt es einen Weg?

Wenn nicht einfach, gibt es eine Möglichkeit, Vorschläge zu erzwingen, die ich zeigen möchte, nicht diejenigen, die der Browser angepasst hat? Sagen wir, ich tippe "foo" und möchte die Optionen "bar" und "baz" anzeigen. Kann ich das dem Benutzer aufzwingen? Wenn ich den Datalist nur mit denen (mit JS) fülle, wird der Browser immer noch die "Starts mit" Prüfung durchführen und sie herausfiltern.

Ich möchte die ultimative Kontrolle darüber, wie die Datenlistenoptionen zeigen. NICHT über seine Benutzeroberfläche, Flexibilität, Zugänglichkeit usw., also möchte ich es nicht komplett neu machen. Schlagen Sie nicht einmal ein jQuery-Plugin vor.

Wenn ich Formelement-Validierung ultimativ kontrollieren kann, warum nicht Autovervollständigung, richtig?

bearbeiten: Ich sehe jetzt, dass Firefox die 'enthält' Ansatz verwendet ... Das ist nicht einmal ein Standard? Irgendeine Möglichkeit, dies zu erzwingen? Kann ich den Weg von Firefox ändern?

edit: ich dies gemacht zu illustrieren, was Ich mag würde: http://jsfiddle.net/rudiedirkx/r3jbfpxw/

+2

Keine Hilfe zu diesem Thema? Kaum zu glauben ... das war das erste, woran ich dachte, als ich einen Datenspezialisten brauchte. –

+0

das Problem ist, ist der Datenlisten nicht editierbar, zumindest in ie11. Dann bekomme ich diesen Fehler: '0x800a13b5 - JavaScript Laufzeitfehler: Zuweisung zu schreibgeschützten Eigenschaften ist im strikten Modus nicht erlaubt'. –

+0

@NinaScholz Wann bekommen Sie diesen Fehler? Was was zuweisen? Kannst du eine Geige machen? – Rudie

Antwort

11

'enthält' Ansatz

Vielleicht ist das, was Sie suchen (Teil 1 Ihrer Frage).

Es geht mit der Begrenzung von "beginnt mit" und ändert sich, wenn eine Auswahl getroffen wird.

'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>

bearbeiten

Ein anderer Ansatz, die Suche Inhalt angezeigt wird, klar zu machen, was passiert. Dies funktioniert auch in Chrome. Inspiriert von 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>

+0

Das ist schlau! Und es funktioniert, aber es sieht so aus: http://screencast.com/t/igeQtYJ2 Das ist nicht schön, besonders bei einer Suche wie "Ameri". Dies ist ein großer Fehler in der Autocomplete-Funktion IMO. Wir verbringen Zeit für bessere 3D-Animationen, aber nicht Verbesserung der Funktionalität wie diese = ( – Rudie

+0

welchen Browser verwenden Sie? –

+0

Chrome auf Windows. Gleiches in Canary. Firefox sieht besser aus, aber Firefox verwendet bereits den "enthält" -Ansatz. – Rudie

1

diese fiddle here hat geknackt, was Sie für fragen Aber ich bin nicht sicher, wie es ohne diese Abhängigkeit machen arbeiten, wie die Benutzeroberfläche etwas seltsam aussieht und fehl am Platz, wenn zusammen mit Bootstrap verwendet.

elem.autocomplete({ 
    source: list.children().map(function() { 
     return $(this).text(); 
    }).get() 
+2

Dies verwendet' Autocomplete 'von jQuery UI Autocomplete überhaupt. Ich hatte gehofft 2016 Autocomplete wäre besser = ( – Rudie

+0

Das macht lustige Dinge für mich, wenn in einem Bootstrap 3 Seite verwendet –

1

Dieser Thread wurde vor etwa 2 Jahren gepostet.aber wenn Sie diesen Thread lesen, müssen Sie vielleicht eine neuere Version Ihres Browsers überprüfen:

Aktuelle Spezifikation: https://html.spec.whatwg.org/multipage/forms.html#the-list-attribute

User agents are encouraged to filter the suggestions represented by the suggestions source element when the number of suggestions is large, including only the most relevant ones (e.g. based on the user's input so far). No precise threshold is defined, but capping the list at four to seven values is reasonable. If filtering based on the user's input, user agents should use substring matching against both the suggestions' label and value.

Und wenn dieser Beitrag geschrieben, das Verhalten von Firefox (51) und Chrome (56) wurde bereits geändert, um der Spezifikation zu entsprechen.

was bedeutet, was op will, sollte gerade jetzt funktionieren.

+0

Ja, tut es, aber ich hätte es immer noch gemocht, wenn ich etwas Kontrolle darüber hätte. Meine nächste Autocomplete könnte sein muß ‚beginnt mit‘, aber es gibt keine Möglichkeit der automatische Vervollständigung Funktionalität außer Kraft zu setzen Was für eine Schande – Rudie

+0

Diese Antwort einfach zu kurz ist ... Bitte reflektiert auch den Abschnitt über die automatische Füllen:.. https://www.w3.org/TR /html/sec-forms.html#autofill (Vor allem, was Mantel das Attribut * ist zu tragen, wenn das 'autocomplete' Attribut weggelassen wird *, sondern auch der Unterschied zwischen„** ** Erwartung Mantel“und„** Anker ** Mantel „) - und nicht verpassen: https://www.w3.org/TR/html/sec-forms.html#ref-for-autofill-expectation-mantle-4 – yckart

+0

@yckart' autocomplete' Attribut ist nur Eine andere Geschichte, die nicht mit dieser Frage in Verbindung steht IMO: Vielleicht möchten Sie eine andere Antwort oder vielleicht eine andere Frage stellen mögen. – tsh

Verwandte Themen