【问题标题】:Custom autocomplete function in jqueryjquery中的自定义自动完成功能
【发布时间】:2016-07-25 20:33:04
【问题描述】:

更新

@Ziv Weissman@Fribu 的帮助和建议下,我重新编写了整个自动完成功能。

如果有人需要,他/她可以从here下载。

感谢 StackOverFlow 社区。​​p>


我正在创建一个 jquery 自动完成功能。我创建的函数在单个文本框上运行良好。但是,一旦我在同一页面的另一个文本框中实现它,它的行为就会出乎意料。它打开和关闭自动完成列表。

这是我的 autofill.js 代码:

function setUl(result) {
    var $ul = $('<ul>');
    if (result !== undefined) {
        $.each(result, function (k, v) {
            $ul.append('<li data-value="' + v.value + '">' + v.label + '</li>');
        });
    }
    return $ul;
}
$.fn.autofill = function (options) {
    if (options == undefined) {
        options = {};
    }
    var $currentInput = $(this);
    var autoCompleteData = $currentInput.data('autofill');
    var listId='autofill-' + (new Date().getTime()).toString(16);
    $currentInput.on('keyup focus', function (e) {

        var query = $(this).val();
        var result = $.grep(autoCompleteData, function (v) {
            return v.label.search(new RegExp(query, 'i')) !== -1;
        });
        $ul = setUl(result, $currentInput);
        $ul.attr('id', listId);
        $ul.addClass('autofill-show');
        $ul.attr('data-target',$currentInput.attr('id'));
        var position = $currentInput.position();
        $ul.css({
            width: $currentInput.width() + parseInt($currentInput.css('padding-left'), 10) + parseInt($currentInput.css('padding-right'), 10),
            position: 'absolute',
            top: position.top + $currentInput.outerHeight(),
            left: position.left
        });
        if ($ul.find('li').length >= 6) {
            $ul.css({
                height: '130px',
                'overflow-y': 'scroll'
            });
        }
        if (result !== undefined) {
            if ($(e.target).attr('id') !== $currentInput.attr('id') && $($(e.target).parent()[0]).attr('id') !== listId) {
                destroy($ul);
            }
            $currentInput.after($ul);
        }
        $currentInput.trigger('onChange', [query, result]);
    });
    $(document).on('click', '.autofill-show li', function (e) {
        if($ul!==undefined && $($(this).parent()[0]).attr('id')==$ul.attr('id')){
            $ul.trigger('onSelect', [$(this).text(), $(this).data('value')]);
        }
        e.stopImmediatePropagation();
    });
    $(document).on('onSelect', '#'+listId,function (e, label, value) {
        $currentInput.val(label);
        if ($.isFunction(options.onSelect)) {
            options.onSelect(label, value);
        }
        if ($(e.target).attr('id') !== $currentInput.attr('id') && $($(e.target).parent()[0]).attr('id') !== listId) {
            destroy($ul);
        }
        e.stopImmediatePropagation();
    });
    $(document).on('onChange', '#'+$currentInput.attr('id'), function (e, query, result) {
        if($ul!==undefined && $($(this).parent()[0]).attr('id')==$ul.attr('id')) {
            result = $.grep(autoCompleteData, function (v) {
                return v.label.search(new RegExp('\^' + query + '\$', "gi")) !== -1;
            });
            if ($.isFunction(options.onChange)) {
                options.onChange(query, result[0]);
            }
        }
        e.stopImmediatePropagation();
    });
    $(document).on('click', function (e) {
        console.log($(e.target));
        if ($(e.target).attr('id') !== $currentInput.attr('id') && $($(e.target).parent()[0]).attr('id') !== listId) {
            destroy($ul);
        }
        e.stopImmediatePropagation();
    });
};
function destroy($ul) {
    $ul.remove();
}

这是我的 CSS:

.autofill-show{
    list-style: outside none none;
    padding: 0;
    border: 1px solid #ccc;
    margin:0;
    z-index: 9999999;
}
.autofill-show li{
    border: 1px solid #ccc;
    text-align: center;
    background: #fff;
}

.autofill-show li:hover{
    background: #9bcea3;
    cursor: pointer;
}

这就是我调用函数的方式:

$('#autofill').autofill();
$('#autofill_2').autofill();

这里是小提琴链接。 https://jsfiddle.net/saineshmamgain/cs6g13q9/2/

【问题讨论】:

  • 如果您将其转换为代码 sn-p 或小提琴,它将帮助我们帮助您,还包括用于自动填充和 autofill-2 的 html(顺便说一句,建议更改为 autofill_2)
  • @ZivWeissman 添加了小提琴链接。谢谢。
  • 很可能您使用选择器定位相同的元素,您需要在选择器中添加每个元素 ID 唯一的内容,例如 currentId = '#' + $i.attr('id') ;以后有时间再看看吧
  • @CodeZilla 您的代码中有多个问题。您有多个事件绑定,并且如果您在一个列表中选择项目,它也将在另一个列表中写入...尝试重新考虑您的事件和结构...甚至可能是变量名称以获得清晰的画面。
  • @CodeZilla 问题是,您的代码将永远无法使用此语句 $(document).on('click', function (e) 在页面上至少两次。您想关闭如果用户在输入之外单击,则自动完成。但是...您必须确保仅绑定此事件一次。您可以:将绑定状态保存在全局变量中,确保命名是唯一的,因此没有其他插件通过错误或...将事件更改为其他内容。

标签: javascript jquery autocomplete


【解决方案1】:

正如我提到的,以及其他人的帮助,这是您的事件和选择器的问题。

一种解决方案可以是向创建的 UL 添加唯一 ID,而不是“基于日期时间”。 每次你都会破坏一个特定的 ID,然后重新创建它。 这些事件将通过 HTML 触发(添加 onclick=...)并使用 jQUERY 处理当前/父级别。

我已经更新了这个fiddle

它可能有一些东西是你小提琴的剩余物,我没有时间完善......我会留给你的。

解决方案如下所示:

function setUl(result) {
    var $ul = $('<ul>');
    if (result !== undefined) {
        $.each(result, function (k, v) {
            $ul.append('<li data-value="' + v.value + '" onclick="clickHandle(this)">' + v.label + '</li>');
        });
    }
    return $ul;
}

function clickHandle(ele){
var label = $(ele).text();
var value = $(ele).data('value');
var inputId = $(ele).parent("ul").attr("data-target");
$('#'+inputId).val(label);
        if ($.isFunction(options.onSelect)) {
            options.onSelect(label, value);
        }
}

$.fn.autofill = function (options) {
    if (options == undefined) {
        options = {};
    }
    var $currentInput = $(this);
    console.log($($currentInput).attr('id'));
    var autoCompleteData = $currentInput.data('autofill');
    var listId='autofill_' + $currentInput.attr('id');
    $currentInput.on('keyup focus', function (e) {

        var query = $(this).val();
        var result = $.grep(autoCompleteData, function (v) {
            return v.label.search(new RegExp(query, 'i')) !== -1;
        });
        if($('#'+listId)){
          $('#'+listId).remove();
        }
        $ul = setUl(result, $currentInput);
        $ul.attr('id',listId);
        $ul.addClass('autofill-show');
        $ul.attr('data-target',$currentInput.attr('id'));
        var position = $currentInput.position();
        $ul.css({
            width: $currentInput.width() + parseInt($currentInput.css('padding-left'), 10) + parseInt($currentInput.css('padding-right'), 10),
            position: 'absolute',
            top: position.top + $currentInput.outerHeight(),
            left: position.left
        });
        if ($ul.find('li').length >= 6) {
            $ul.css({
                height: '130px',
                'overflow-y': 'scroll'
            });
        }
        if (result !== undefined) {
            destroy($ul);
            $currentInput.after($ul);
        }
        $currentInput.trigger('onChange', [query, result]);
    });  
    //end key up 

    $('#'+listId).on('onSelect',function (e, label, value) {
        $currentInput.val(label);
        if ($.isFunction(options.onSelect)) {
            options.onSelect(label, value);
        }
        destroy($ul);
        e.stopImmediatePropagation();
    });
    $(document).on('onChange', '#'+$currentInput.attr('id'), function (e, query, result) {
        if($ul!==undefined && $($(this).parent()[0]).attr('id')==$ul.attr('id')) {
            result = $.grep(autoCompleteData, function (v) {
                return v.label.search(new RegExp('\^' + query + '\$', "gi")) !== -1;
            });
            if ($.isFunction(options.onChange)) {
                options.onChange(query, result[0]);
            }
        }
        e.stopImmediatePropagation();
    });
    $currentInput.on('blur', function (e) {
        window.setTimeout(function(){
        destroy($ul);
        }, 100);
    });
};
function destroy($ul) {
    $ul.remove();
}

【讨论】:

  • 感谢您的帮助。它解决了我的主要问题。我会做剩下的。
【解决方案2】:

如果我理解正确你的 quation(代码):

hidden

code

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-24
    • 2016-04-14
    • 1970-01-01
    • 2023-03-23
    • 2012-01-26
    • 2017-07-21
    相关资源
    最近更新 更多