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

前端 未结 4 729
清歌不尽
清歌不尽 2020-11-29 05:03

(I can\'t find it, but then again I don\'t really know how to search for it.)

I want to use and

4条回答
  •  独厮守ぢ
    2020-11-29 05:59

    '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 '';
            }).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);
    });
    
    
        

    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 '';
            }).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);
    });
    
    

提交回复
热议问题