rules.autocomplete.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. // Registers the rules namespace.
  2. Drupal.rules = Drupal.rules || {};
  3. (function($) {
  4. Drupal.behaviors.rules_autocomplete = {
  5. attach: function(context) {
  6. var autocomplete_settings = Drupal.settings.rules_autocomplete;
  7. $('input.rules-autocomplete').once(function() {
  8. var input = this;
  9. new Drupal.rules.autocomplete(input, autocomplete_settings[$(input).attr('id')]);
  10. });
  11. }
  12. };
  13. /**
  14. * Rules autocomplete object.
  15. */
  16. Drupal.rules.autocomplete = function(input, settings) {
  17. this.id = settings.inputId;
  18. this.uri = settings.source;
  19. this.jqObject = $('#' + this.id);
  20. this.cache = new Array();
  21. this.jqObject.addClass('ui-corner-left');
  22. this.opendByFocus = false;
  23. this.focusOpens = true;
  24. this.groupSelected = false;
  25. this.button = $('<span>&nbsp;</span>');
  26. this.button.attr( {
  27. 'tabIndex': -1,
  28. 'title': 'Show all items'
  29. });
  30. this.button.insertAfter(this.jqObject);
  31. this.button.button( {
  32. icons: {
  33. primary: 'ui-icon-triangle-1-s'
  34. },
  35. text: false
  36. });
  37. // Don't round the left corners.
  38. this.button.removeClass('ui-corner-all');
  39. this.button.addClass('ui-corner-right ui-button-icon rules-autocomplete-button');
  40. this.jqObject.autocomplete();
  41. this.jqObject.autocomplete("option", "minLength", 0);
  42. // Add a custom class, so we can style the autocomplete box without
  43. // interfering with other jquery autocomplete widgets.
  44. this.jqObject.autocomplete("widget").addClass('rules-autocomplete');
  45. // Save the current rules_autocomplete object, so it can be used in
  46. // handlers.
  47. var instance = this;
  48. // Event handlers
  49. this.jqObject.focus(function() {
  50. if (instance.focusOpens) {
  51. instance.toggle();
  52. instance.opendByFocus = true;
  53. }
  54. else {
  55. instance.focusOpens = true;
  56. }
  57. });
  58. // Needed when the window is closed but the textfield has the focus.
  59. this.jqObject.click(function() {
  60. // Since the focus event happens earlier then the focus event, we need to
  61. // check here, if the window should be opened.
  62. if (!instance.opendByFocus) {
  63. instance.toggle();
  64. }
  65. else {
  66. instance.opendByFocus = false;
  67. }
  68. });
  69. this.jqObject.bind("autocompleteselect", function(event, ui) {
  70. // If a group was selected then set the groupSelected to true for the
  71. // overridden close function from jquery autocomplete.
  72. if (ui.item.value.substring(ui.item.value.length - 1, ui.item.value.length) == ":") {
  73. instance.groupSelected = true;
  74. }
  75. instance.focusOpens = false;
  76. instance.opendByFocus = false;
  77. });
  78. this.jqObject.autocomplete("option", "source", function(request, response) {
  79. if (request.term in instance.cache) {
  80. response(instance.cache[request.term]);
  81. return;
  82. }
  83. $.ajax( {
  84. url: instance.uri + '/' + request.term,
  85. dataType: "json",
  86. success: function(data) {
  87. instance.success(data, request, response);
  88. }
  89. });
  90. });
  91. // Newer versions of jQuery UI use element.data('ui-autocomplete'), older
  92. // versions use element.data('autocomplete').
  93. var autocompleteDataKey = typeof(this.jqObject.data('autocomplete')) === 'object' ? 'autocomplete' : 'ui-autocomplete';
  94. // Since jquery autocomplete by default strips html text by using .text()
  95. // we need our own _renderItem function to display html content.
  96. this.jqObject.data(autocompleteDataKey)._renderItem = function(ul, item) {
  97. return $("<li></li>").data("item.autocomplete", item).append("<a>" + item.label + "</a>").appendTo(ul);
  98. };
  99. // Override close function
  100. this.jqObject.data(autocompleteDataKey).close = function (event) {
  101. var value = this.element.val();
  102. // If the selector is not a group, then trigger the close event an and
  103. // hide the menu.
  104. if (value === undefined || instance.groupSelected === false) {
  105. clearTimeout(this.closing);
  106. if (this.menu.element.is(":visible")) {
  107. this._trigger("close", event);
  108. this.menu.element.hide();
  109. // Use deactivate for older versions of jQuery UI.
  110. if (typeof(this.menu.deactivate) === 'function') {
  111. this.menu.deactivate();
  112. }
  113. }
  114. }
  115. else {
  116. // Else keep all open and trigger a search for the group.
  117. instance.jqObject.autocomplete("search", instance.jqObject.val());
  118. // After the suggestion box was opened again, we want to be able to
  119. // close it.
  120. instance.groupSelected = false;
  121. }
  122. };
  123. this.button.click(function() {
  124. instance.toggle();
  125. });
  126. };
  127. /**
  128. * Success function for Rules autocomplete object.
  129. */
  130. Drupal.rules.autocomplete.prototype.success = function(data, request, response) {
  131. var list = new Array();
  132. jQuery.each(data, function(index, value) {
  133. list.push( {
  134. label: value,
  135. value: index
  136. });
  137. });
  138. this.cache[request.term] = list;
  139. response(list);
  140. };
  141. /**
  142. * Open the autocomplete window.
  143. * @param searchFor The term for will be searched for. If undefined then the
  144. * entered input text will be used.
  145. */
  146. Drupal.rules.autocomplete.prototype.open = function(searchFor) {
  147. // If searchFor is undefined, we want to search for the passed argument.
  148. this.jqObject.autocomplete("search", ((searchFor === undefined) ? this.jqObject.val() : searchFor));
  149. this.button.addClass("ui-state-focus");
  150. };
  151. /**
  152. * Close the autocomplete window.
  153. */
  154. Drupal.rules.autocomplete.prototype.close = function() {
  155. this.jqObject.autocomplete("close");
  156. this.button.removeClass("ui-state-focus");
  157. };
  158. /**
  159. * Toggle the autocomplete window.
  160. */
  161. Drupal.rules.autocomplete.prototype.toggle = function() {
  162. if (this.jqObject.autocomplete("widget").is(":visible")) {
  163. this.close();
  164. this.focusOpens = true;
  165. }
  166. else {
  167. var groups = this.jqObject.val().split(":");
  168. var selector = "";
  169. for (var i=0; i<groups.length-1; i++) {
  170. selector = selector.concat(groups[i]) + ":";
  171. }
  172. this.focusOpens = false;
  173. this.jqObject.focus();
  174. this.open(selector);
  175. }
  176. };
  177. })(jQuery);