jquery-ui.combobox.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /* Adapted from http://jqueryui.com/autocomplete/#combobox */
  2. /* and http://www.learningjquery.com/2010/06/a-jquery-ui-combobox-under-the-hood/ */
  3. (function($) {
  4. $.widget( "ui.combobox", {
  5. _create: function() {
  6. var self = this;
  7. var select = this.element.hide(),
  8. selected = select.children( ":selected" ),
  9. value = selected.val() ? selected.text() : "";
  10. var input = $( "<input />" )
  11. .insertAfter(select)
  12. .addClass("ui-combobox-input ui-state-default")
  13. .focus(function() {
  14. input.removeClass('ui-state-default');
  15. input.autocomplete("search", "");
  16. })
  17. .blur(function() {
  18. input.addClass('ui-state-default');
  19. })
  20. .val( value )
  21. .keydown(function(evt) {
  22. var text, start;
  23. if (evt.keyCode == $.ui.keyCode.BACKSPACE
  24. && (start = input[0].selectionStart) > 0
  25. && (end = input[0].selectionEnd) != start
  26. && end == (text = input.val()).length) {
  27. input.val(text = text.substring(0, start - 1));
  28. evt.preventDefault();
  29. return false;
  30. }
  31. })
  32. .autocomplete({
  33. delay: 0,
  34. minLength: 0,
  35. source: function(request, response) {
  36. var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex(request.term), "i" );
  37. options = select.children("option").map(function() {
  38. var text = $( this ).text();
  39. if ( this.value && ( !request.term || matcher.test(text) ) )
  40. return {
  41. label: text.replace(
  42. new RegExp(
  43. "(?![^&;]+;)(?!<[^<>]*)(" +
  44. $.ui.autocomplete.escapeRegex(request.term) +
  45. ")(?![^<>]*>)(?![^&;]+;)", "gi"),
  46. "<strong>$1</strong>"),
  47. value: text,
  48. option: this
  49. };
  50. });
  51. response(options);
  52. if (request.term.length && options.length) {
  53. var text = options[0].value;
  54. input.val(text);
  55. input[0].selectionStart = request.term.length;
  56. input[0].selectionEnd = text.length;
  57. options[0].option.selected = true;
  58. } else {
  59. select.val('');
  60. }
  61. },
  62. select: function( event, ui ) {
  63. ui.item.option.selected = true;
  64. self._trigger( "selected", event, {
  65. item: ui.item.option
  66. });
  67. },
  68. change: function(event, ui) {
  69. if ( !ui.item ) {
  70. var valid = false;
  71. findMatch = function(matcher) {
  72. select.children( "option" ).each(function() {
  73. if ( this.value.match( matcher ) ) {
  74. this.selected = valid = true;
  75. input.val(this.value);
  76. return false;
  77. }
  78. });
  79. };
  80. var escapedMatcher = $.ui.autocomplete.escapeRegex( $(this).val() );
  81. findMatch(new RegExp( "^" + escapedMatcher + "$", "i" ));
  82. if ( !valid ) {
  83. findMatch(new RegExp( "^" + escapedMatcher, "i" ));
  84. }
  85. if ( !valid ) {
  86. // remove invalid value, as it didn't match anything
  87. $( this ).val( "" );
  88. select.val( "" );
  89. return false;
  90. }
  91. }
  92. }
  93. })
  94. .addClass("ui-widget ui-widget-content ui-corner-all ui-combobox");
  95. input.data( "ui-autocomplete" )._renderItem = function( ul, item ) {
  96. return $( "<li></li>" )
  97. .data( "item.autocomplete", item )
  98. .append( "<a>" + item.label + "</a>" )
  99. .appendTo( ul );
  100. };
  101. select.change(function(evt) {
  102. input.val(select.val());
  103. });
  104. }
  105. });
  106. })(jQuery);
  107. /*
  108. (function( $ ) {
  109. $.widget( "custom.combobox", {
  110. _create: function() {
  111. this.wrapper = $( "<span>" )
  112. .addClass( "custom-combobox" )
  113. .insertAfter( this.element );
  114. this.element.hide();
  115. this._createAutocomplete();
  116. this._createShowAllButton();
  117. },
  118. _createAutocomplete: function() {
  119. var selected = this.element.children( ":selected" ),
  120. value = selected.val() ? selected.text() : "";
  121. this.input = $( "<input>" )
  122. .appendTo( this.wrapper )
  123. .val( value )
  124. .attr( "title", "" )
  125. .addClass( "custom-combobox-input ui-widget ui-widget-content ui-state-default ui-corner-left" )
  126. .autocomplete({
  127. delay: 0,
  128. minLength: 0,
  129. source: $.proxy( this, "_source" )
  130. // })
  131. // .tooltip({
  132. // tooltipClass: "ui-state-highlight"
  133. });
  134. // this._on( this.input, {
  135. $( this.input ).on({
  136. autocompleteselect: function( event, ui ) {
  137. ui.item.option.selected = true;
  138. $( this ).trigger( "select", event, {
  139. item: ui.item.option
  140. });
  141. },
  142. autocompletechange: this._removeIfInvalid.bind(this)
  143. });
  144. },
  145. _createShowAllButton: function() {
  146. var input = this.input,
  147. wasOpen = false;
  148. $( "<a>" )
  149. .attr( "tabIndex", -1 )
  150. .attr( "title", "Show All Items" )
  151. // .tooltip()
  152. .appendTo( this.wrapper )
  153. .button({
  154. icons: {
  155. primary: "ui-icon-triangle-1-s"
  156. },
  157. text: false
  158. })
  159. .removeClass( "ui-corner-all" )
  160. .addClass( "custom-combobox-toggle ui-corner-right" )
  161. .mousedown(function() {
  162. wasOpen = input.autocomplete( "widget" ).is( ":visible" );
  163. })
  164. .click(function() {
  165. input.focus();
  166. // Close if already visible
  167. if ( wasOpen ) {
  168. return;
  169. }
  170. // Pass empty string as value to search for, displaying all results
  171. input.autocomplete( "search", "" );
  172. });
  173. },
  174. _source: function( request, response ) {
  175. var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
  176. response( this.element.children( "option" ).map(function() {
  177. var text = $( this ).text();
  178. if ( this.value && ( !request.term || matcher.test(text) ) )
  179. return {
  180. label: text,
  181. value: text,
  182. option: this
  183. };
  184. }) );
  185. },
  186. _removeIfInvalid: function( event, ui ) {
  187. // Selected an item, nothing to do
  188. if ( ui.item ) {
  189. return;
  190. }
  191. // Search for a match (case-insensitive)
  192. var value = this.input.val(),
  193. valueLowerCase = value.toLowerCase(),
  194. valid = false;
  195. this.element.children( "option" ).each(function() {
  196. if ( $( this ).text().toLowerCase() === valueLowerCase ) {
  197. this.selected = valid = true;
  198. return false;
  199. }
  200. });
  201. // Found a match, nothing to do
  202. if ( valid ) {
  203. return;
  204. }
  205. // Remove invalid value
  206. this.input
  207. .val( "" );
  208. // .attr( "title", value + " didn't match any item" )
  209. // .tooltip( "open" );
  210. this.element.val( "" );
  211. // $(this).delay(function() {
  212. // this.input.tooltip( "close" ).attr( "title", "" );
  213. // }, 2500 );
  214. console.log(this.input);
  215. console.log(this.input.data('ui-autocomplete'));
  216. this.input.data( "ui-autocomplete" ).term = ""; // TODO
  217. },
  218. _destroy: function() {
  219. this.wrapper.remove();
  220. this.element.show();
  221. }
  222. });
  223. })( jQuery );
  224. */