使用非常大的选择列表加速jqueryui自动完成组合框

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用非常大的选择列表加速jqueryui自动完成组合框相关的知识,希望对你有一定的参考价值。

With the current combobox implementation, the full list is emptied and re-rendered every time you expand the dropdown. Also you are stuck with setting the minLength to 0, because it has to do an empty search to get the full list.

Here is my own implementation extending the autocomplete widget. It renders the full list just once, and reuses it whenever the dropdown button is clicked. This also removes the dependence of the option minLength = 0. It also works with arrays, and ajax as list source. Also if you have multiple large list, the widget initialization is added to a queue so it can run in the background, and not freeze the browser.
  1. (function ($) {
  2. $.widget('ui.combobox', $.ui.autocomplete,
  3. {
  4. options: {
  5. minLength: 2,
  6. ajaxGetAll: { get: 'all' }
  7. },
  8.  
  9. _create: function () {
  10. if (this.element.is('SELECT')) {
  11. this._selectInit();
  12. return;
  13. }
  14.  
  15. $.ui.autocomplete.prototype._create.call(this);
  16. var input = this.element;
  17. input.addClass('ui-widget ui-widget-content ui-corner-left');
  18.  
  19. this.button = $('<button type="button">&nbsp;</button>')
  20. .attr('tabIndex', -1)
  21. .attr('title', 'Show All Items')
  22. .insertAfter(input)
  23. .button({
  24. icons: { primary: 'ui-icon-triangle-1-s' },
  25. text: false
  26. })
  27. .removeClass('ui-corner-all')
  28. .addClass('ui-corner-right ui-button-icon')
  29. .click(function (event) {
  30. if (input.combobox('widget').is(':visible')) {
  31. input.combobox('close');
  32. return;
  33. }
  34. var data = input.data('combobox');
  35. clearTimeout(data.closing);
  36. if (!input.isFullMenu) {
  37. data._swapMenu();
  38. input.isFullMenu = true;
  39. }
  40. input.combobox('widget').css('display', 'block')
  41. .position($.extend({ of: input },
  42. data.options.position
  43. ));
  44. input.focus();
  45. data._trigger('open');
  46. });
  47.  
  48. $(document).queue(function () {
  49. var data = input.data('combobox');
  50. if ($.isArray(data.options.source)) {
  51. $.ui.combobox.prototype._renderFullMenu.call(data, data.options.source);
  52. } else if (typeof data.options.source === 'string') {
  53. $.getJSON(data.options.source, data.options.ajaxGetAll, function (source) {
  54. $.ui.combobox.prototype._renderFullMenu.call(data, source);
  55. });
  56. } else {
  57. $.ui.combobox.prototype._renderFullMenu.call(data, data.source());
  58. }
  59. });
  60. },
  61.  
  62. _renderFullMenu: function (source) {
  63. var self = this,
  64. input = this.element,
  65. ul = input.data('combobox').menu.element,
  66. lis = [];
  67. source = this._normalize(source);
  68. input.data('combobox').menuAll = input.data('combobox').menu.element.clone(true).appendTo('body');
  69. for (var i = 0; i < source.length; i++) {
  70. lis[i] = '<li class="ui-menu-item" role="menuitem"><a class="ui-corner-all" tabindex="-1">' + source[i].label + '</a></li>';
  71. }
  72. ul.append(lis.join(''));
  73. this._resizeMenu();
  74. setTimeout(function () {
  75. self._setupMenuItem.call(self, ul.children('li'), source);
  76. }, 0);
  77. input.isFullMenu = true;
  78. },
  79.  
  80. _setupMenuItem: function (items, source) {
  81. var self = this,
  82. itemsChunk = items.splice(0, 500),
  83. sourceChunk = source.splice(0, 500);
  84. for (var i = 0; i < itemsChunk.length; i++) {
  85. $(itemsChunk[i])
  86. .data('item.autocomplete', sourceChunk[i])
  87. .mouseenter(function (event) {
  88. self.menu.activate(event, $(this));
  89. })
  90. .mouseleave(function () {
  91. self.menu.deactivate();
  92. });
  93. }
  94. if (items.length > 0) {
  95. setTimeout(function () {
  96. self._setupMenuItem.call(self, items, source);
  97. }, 0);
  98. } else {
  99. $(document).dequeue();
  100. }
  101. },
  102.  
  103. _renderItem: function (ul, item) {
  104. var label = item.label.replace(new RegExp(
  105. '(?![^&;]+;)(?!<[^<>]*)(' + $.ui.autocomplete.escapeRegex(this.term) +
  106. ')(?![^<>]*>)(?![^&;]+;)', 'gi'), '<strong>$1</strong>');
  107. return $('<li></li>')
  108. .data('item.autocomplete', item)
  109. .append('<a>' + label + '</a>')
  110. .appendTo(ul);
  111. },
  112.  
  113. destroy: function () {
  114. if (this.element.is('SELECT')) {
  115. this.input.remove();
  116. this.element.removeData().show();
  117. return;
  118. }
  119. $.ui.autocomplete.prototype.destroy.call(this);
  120. this.element.removeClass('ui-widget ui-widget-content ui-corner-left');
  121. this.button.remove();
  122. },
  123.  
  124. search: function (value, event) {
  125. var input = this.element;
  126. if (input.isFullMenu) {
  127. this._swapMenu();
  128. input.isFullMenu = false;
  129. }
  130. $.ui.autocomplete.prototype.search.call(this, value, event);
  131. },
  132.  
  133. _change: function (event) {
  134. abc = this;
  135. if (!this.selectedItem) {
  136. var matcher = new RegExp('^' + $.ui.autocomplete.escapeRegex(this.element.val()) + '$', 'i'),
  137. match = $.grep(this.options.source, function (value) {
  138. return matcher.test(value.label);
  139. });
  140. if (match.length) {
  141. match[0].option.selected = true;
  142. } else {
  143. this.element.val('');
  144. if (this.options.selectElement) {
  145. this.options.selectElement.val('');
  146. }
  147. }
  148. }
  149. $.ui.autocomplete.prototype._change.call(this, event);
  150. },
  151.  
  152. _swapMenu: function () {
  153. var input = this.element,
  154. data = input.data('combobox'),
  155. tmp = data.menuAll;
  156. data.menuAll = data.menu.element.hide();
  157. data.menu.element = tmp;
  158. },
  159.  
  160. _selectInit: function () {
  161. var select = this.element.hide(),
  162. selected = select.children(':selected'),
  163. value = selected.val() ? selected.text() : '';
  164. this.options.source = select.children('option[value!=""]').map(function () {
  165. return { label: $.trim(this.text), option: this };
  166. }).toArray();
  167. var userSelectCallback = this.options.select;
  168. var userSelectedCallback = this.options.selected;
  169. this.options.select = function (event, ui) {
  170. ui.item.option.selected = true;
  171. if (userSelectCallback) userSelectCallback(event, ui);
  172. if (userSelectedCallback) userSelectedCallback(event, ui);
  173. };
  174. this.options.selectElement = select;
  175. this.input = $('<input>').insertAfter(select)
  176. .val(value).combobox(this.options);
  177. }
  178. }
  179. );
  180. })(jQuery);

以上是关于使用非常大的选择列表加速jqueryui自动完成组合框的主要内容,如果未能解决你的问题,请参考以下文章

jQueryUI 自动完成选项 - 样式问题

jQuery UI 自动完成:如何让 TAB 选择列表中的第一个选项?

jQuery UI - 加速自动完成

jQueryUI 自动完成组合框太长

JqueryUI 自动完成输入字段

jqueryui 自动完成过滤器结果(来自远程数据源)“开始于”输入