3 * Linkit Autocomplete based on jQuery UI.
6 (function ($, Drupal, _, document) {
13 * JQuery UI autocomplete source callback.
15 * @param {object} request
16 * @param {function} response
18 function sourceData(request, response) {
19 var elementId = this.element.attr('id');
21 if (!(elementId in autocomplete.cache)) {
22 autocomplete.cache[elementId] = {};
26 * @param {object} suggestions
28 function showSuggestions(suggestions) {
29 response(suggestions.matches);
33 * Transforms the data object into an array and update autocomplete results.
35 * @param {object} data
37 function sourceCallbackHandler(data) {
38 autocomplete.cache[elementId][term] = data;
39 showSuggestions(data);
42 // Get the desired term and construct the autocomplete URL for it.
43 var term = request.term;
45 // Check if the term is already cached.
46 if (autocomplete.cache[elementId].hasOwnProperty(term)) {
47 showSuggestions(autocomplete.cache[elementId][term]);
50 var options = $.extend({success: sourceCallbackHandler, data: {q: term}}, autocomplete.ajax);
51 $.ajax(this.element.attr('data-autocomplete-path'), options);
56 * Handles an autocomplete select event.
58 * @param {jQuery.Event} event
63 function selectHandler(event, ui) {
64 if (ui.item.hasOwnProperty('path')) {
65 event.target.value = ui.item.path;
67 $(document).trigger('linkit.autocomplete.select', [event, ui]);
72 * Override jQuery UI _renderItem function to output HTML by default.
75 * The <ul> element that the newly created <li> element must be appended to.
76 * @param {object} item
80 function renderItem(ul, item) {
81 var $line = $('<li>').addClass('linkit-result');
82 $line.append($('<span>').html(item.title).addClass('linkit-result--title'));
84 if (item.description !== null) {
85 $line.append($('<span>').html(item.description).addClass('linkit-result--description'));
88 return $line.appendTo(ul);
92 * Override jQuery UI _renderMenu function to handle groups.
95 * An empty <ul> element to use as the widget's menu.
96 * @param {array} items
97 * An Array of items that match the user typed term.
99 function renderMenu(ul, items) {
100 var self = this.element.autocomplete('instance');
102 var grouped_items = _.groupBy(items, function (item) {
103 return item.hasOwnProperty('group') ? item.group : '';
106 $.each(grouped_items, function (group, items) {
108 ul.append('<li class="linkit-result--group">' + group + '</li>');
111 $.each(items, function (index, item) {
112 self._renderItemData(ul, item);
118 * Attaches the autocomplete behavior to all required fields.
120 * @type {Drupal~behavior}
122 Drupal.behaviors.linkit_autocomplete = {
123 attach: function (context) {
124 // Act on textfields with the "form-autocomplete" class.
125 var $autocomplete = $(context).find('input.form-linkit-autocomplete').once('linkit-autocomplete');
126 if ($autocomplete.length) {
127 $.widget('custom.autocomplete', $.ui.autocomplete, {
128 _create: function () {
130 this.widget().menu('option', 'items', '> :not(.linkit-result--group)');
132 _renderMenu: autocomplete.options.renderMenu,
133 _renderItem: autocomplete.options.renderItem
136 // Use jQuery UI Autocomplete on the textfield.
137 $autocomplete.autocomplete(autocomplete.options);
138 $autocomplete.autocomplete('widget').addClass('linkit-ui-autocomplete');
141 detach: function (context, settings, trigger) {
142 if (trigger === 'unload') {
143 $(context).find('input.form-linkit-autocomplete')
144 .removeOnce('linkit-autocomplete')
145 .autocomplete('destroy');
151 * Autocomplete object implementation.
157 renderItem: renderItem,
158 renderMenu: renderMenu,
159 select: selectHandler,
167 })(jQuery, Drupal, _, document);