JQuery AutoComplete附加到打开列表

时间:2012-10-18 01:07:25

标签: javascript jquery jquery-ui autocomplete widget

我测试了JQuery自动完成UI小部件,并注意到在处理大量数据时,自动完成在IE中的性能极差。我的客户使用Internet Explorer 7.

我找到了一个缓解性能问题的解决方案。而不是返回自动完成搜索的所有匹配,我只返回前40个匹配。代码

source: function (request, response) {
                var matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(request.term), "i");
                var select_el = select.get(0); // get dom element
                var rep = new Array(); // response array
                var maxRepSize = 40; // maximum response size
                // simple loop for the options
                var looper = 0;
                for (var i = 0; i < select_el.length; i++) {
                    var text = select_el.options[i].text;
                    if (!request || request == '') {
                        // add element to result array
                        rep[looper++] = {
                            label: text,
                            value: text,
                            option: select_el.options[i]
                        };
                    }
                    else if ( select_el.options[i].value && matcher.test(text)   ) {
                        // add element to result array
                        rep[looper++] = {
                            label: text,
                            value: text,
                            option: select_el.options[i]
                        };
                    }
                    if ( rep.length > maxRepSize ) {
                        needMoreItems = true;
                        break;
                    }
                 }
                 // send response
                 response( rep );
            },

客户要求我将“更多结果”项附加到自动填充列表中。如果有超过40个与搜索匹配的项目,则“更多结果”项目将显示在列表的底部。如果用户点击“更多结果”项,则自动完成下拉菜单将展开以包含接下来的40个匹配项。我尝试了jQuery自动完成功能,并且我能够使用接下来的40个项目填充自动建议列表,但是当用户单击其中一个动态添加的项目时,我无法将click事件绑定到自动完成UI小部件的Select事件。代码如下:

open: function( event, ui ) {

                if (needMoreItems) {

                    needMoreItems = false;
                    $('<li class="ui-menu-item" role="menuitem" id="yoADDMORE" ><a class="ui-corner-all" tabindex="-1">... more available<br/><br/></a></li>')
                    .bind({
                        click: function(e) {
                            var appendHtml = '';
                            var select_el = select.get(0);
                            var maxRepSize = 40; // maximum response size
                            // simple loop for the options
                            var looper = 0;
                            for (var i = 41; i < select_el.length; i++) {
                                appendHtml += '<li class="ui-menu-item" role="menuitem"><a class="ui-corner-all" tabindex="-1">' + select_el.options[i].text + '</a></li>';

                                if ( looper ++ > maxRepSize ) {
                                    needMoreItems = true;
                                    break;
                                }
                            }
                            if (needMoreItems)
                            appendHtml += '<li class="ui-menu-item" role="menuitem" id="yoADDMORE" ><a class="ui-corner-all" tabindex="-1">... more available<br/><br/></a></li>';
                            $('#yoADDMORE').remove();
                            $('ul.ui-autocomplete').html($('ul.ui-autocomplete').html() + appendHtml);

                            $('ul.ui-autocomplete > li')
                            .bind({
                                mouseenter: function(e) {
                                    // Hover event handler
                                   $("> a",this).attr('class','ui-corner-all ui-state-hover');
                                },
                                mouseleave: function(e) {
                                    // Hover event handler
                                    $("> a",this).attr('class','ui-corner-all');
                                }
                            });

                        },
                        mouseenter: function(e) {
                            // Hover event handler
                           $("> a",this).attr('class','ui-corner-all ui-state-hover');
                        },
                        mouseleave: function(e) {
                            // Hover event handler
                            $("> a",this).attr('class','ui-corner-all');
                        }



                   })
                   .appendTo('ul.ui-autocomplete');

               }                    

            },

指向jsFiddle的链接 http://jsfiddle.net/eyecode/sX4Ba/ 任何帮助,将不胜感激。

先谢谢

1 个答案:

答案 0 :(得分:1)

为了列出前20个项目底部带有“更多..”的前20个选项。一旦用户按下“更多...”链接。所有项目都将显示在下拉列表中。

(function ($) {
    $.widget("ui.typeaheadtextbox", {
        _create: function () {
            var self = this,
            select = this.element.hide(),
            theWidth = select.width(),
            selected = select.children(":selected"),
            value = selected.val() ? selected.text() : "";
      var _searchItem = '';
      var _more = false;
      var _lastIndex = 0;
      var _maxSize = 20;
      var _rep = null;
            var input = this.input = $("<input id='" + select[0].id + "_jq' style=\"width: " + theWidth + "px\">")
            .insertAfter(select)
            .val(value)
            .autocomplete({
                delay: 10,
                minLength: 0,
                source: function (request, response) {
                    var matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(request.term), "i");
                    var j = 0;
          _rep = response;
          _searchItem = request.term;
          var select_el = select.get(0); // get dom element
          var rep = new Array(); // response array
          for (var i = 0; i < select_el.length; i++) {
            var text = select_el.options[i].text;
            if (select_el.options[i].value && (!request.term || matcher.test(text))) {
              j++;
              if (j > _maxSize) {
                                _more = true;
                                _lastIndex = i;
                                break;
                            }
              // add element to result array
              rep[(j - 1)] = {
                                label: text.replace(new RegExp("^(?![^&;]+;)(?!<[^<>]*)(" + $.ui.autocomplete.escapeRegex(_searchItem) + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>"), value: text, option: select_el.options[i]
                            };
            }
          }
          return response(rep);
                },
                autoFocus:true,
                open: function(event, ui) {
                    if (_more) {
                        _more = false;
                        $('<li class="ui-menu-item_more" role="menuitem" id="' + select.get(0).id + '_ADDMORE_' + _lastIndex + '" ><a class="ui-corner-all" tabindex="-1"><img width="16" src="Content/themes/base/images/icon-search-small.png"/> <strong>View All</strong></a></li>')
                        .bind({
                            click: function(e) {
                                var response = _rep;
                                var matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(_searchItem), "i");
                                var select_el = select.get(0); // get dom element
                                var rep = new Array(); // response array
                                var j = 0;
                                for (var i = 0; i < select_el.length; i++) {
                                    var text = select_el.options[i].text;
                                    if (select_el.options[i].value && (!_searchItem || matcher.test(text))) {
                                        // add element to result array
                                        rep[j++] = {
                                            label: text.replace(new RegExp("^(?![^&;]+;)(?!<[^<>]*)(" + $.ui.autocomplete.escapeRegex(_searchItem) + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>"), value: text, option: select_el.options[i]
                                        };
                                    }
                                }
                                $(this).remove();
                                return _rep(rep);
                            },
                            mouseenter: function(e) { $("> a",this).attr('class','ui-corner-all ui-state-hover'); },
                            mouseleave: function(e) { $("> a",this).attr('class','ui-corner-all');}
                        })
                        .appendTo('ul.ui-autocomplete');
                        _lastIndex = 0;
                        return true;
                    }
                },
                select: function (event, ui) {
                    ui.item.option.selected = true;
                    self._trigger("selected", event, {
                        item: ui.item.option
                    });
                },
                change: function (event, ui) {
                    if (!ui.item) {
                        var matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex($(this).val()) + "$", "i"),
                            valid = false;
                        select.children("option").each(function () {
                            if ($(this).text().match(matcher)) {
                                this.selected = valid = true;
                                return false;
                            }
                        });
                        if (!valid) {
                            // remove invalid value, as it didn't match anything
                            $(this).val("");
                            select.val("");
                            input.data("autocomplete").term = "";
                            return false;
                        }
                    }
                }
            })
            .addClass("ui-widget ui-widget-content ui-corner-all");
            input.data("autocomplete")._renderMenu = function( ul, items ) {
            var self = this; var htm = ''; var beginHtm = '<li><a>'; var endHtm = '</a></li>';
          for(var i=0;i<items.length;i++) {
                htm += beginHtm + items[i].label +  endHtm;
          }
          ul[0].innerHTML = htm;
          var liTags = ul[0].getElementsByTagName('li');
          for(var i=0;i<liTags.length;i++) {
            $(liTags[i]).data("item.autocomplete", items[i]);
          }
          return true;
        };
        },
        destroy: function () {
            this.input.remove();
            this.element.show();
            $.Widget.prototype.destroy.call(this);
        },
        clear: function () {
            this.element.val("");
            this.input.val("");
        }
    });
})(jQuery);