PageSourceSearch

https://theatre-chaillot.fr/core/misc/autocomplete.js?v=10.3.14

js theatre-chaillot.fr collected 2026-10-02 05:07:51 UTC 7,720 bytes, 283 lines download raw bytes

1/**
2 * @file
3 * Autocomplete based on jQuery UI.
4 */
5
6(function ($, Drupal) {
7  let autocomplete;
8
9  /**
10   * Helper splitting terms from the autocomplete value.
11   *
12   * @function Drupal.autocomplete.splitValues
13   *
14   * @param {string} value
15   *   The value being entered by the user.
16   *
17   * @return {Array}
18   *   Array of values, split by comma.
19   */
20  function autocompleteSplitValues(value) {
21    // We will match the value against comma-separated terms.
22    const result = [];
23    let quote = false;
24    let current = '';
25    const valueLength = value.length;
26    let character;
27
28    for (let i = 0; i < valueLength; i++) {
29      character = value.charAt(i);
30      if (character === '"') {
31        current += character;
32        quote = !quote;
33      } else if (character === ',' && !quote) {
34        result.push(current.trim());
35        current = '';
36      } else {
37        current += character;
38      }
39    }
40    if (value.length > 0) {
41      result.push(current.trim());
42    }
43
44    return result;
45  }
46
47  /**
48   * Returns the last value of a multi-value textfield.
49   *
50   * @function Drupal.autocomplete.extractLastTerm
51   *
52   * @param {string} terms
53   *   The value of the field.
54   *
55   * @return {string}
56   *   The last value of the input field.
57   */
58  function extractLastTerm(terms) {
59    return autocomplete.splitValues(terms).pop();
60  }
61
62  /**
63   * The search handler is called before a search is performed.
64   *
65   * @function Drupal.autocomplete.options.search
66   *
67   * @param {object} event
68   *   The event triggered.
69   *
70   * @return {boolean}
71   *   Whether to perform a search or not.
72   */
73  function searchHandler(event) {
74    const options = autocomplete.options;
75
76    if (options.isComposing) {
77      return false;
78    }
79
80    const term = autocomplete.extractLastTerm(event.target.value);
81    // Abort search if the first character is in firstCharacterBlacklist.
82    if (term.length > 0 && options.firstCharacterBlacklist.includes(term[0])) {
83      return false;
84    }
85    // Only search when the term is at least the minimum length.
86    return term.length >= options.minLength;
87  }
88
89  /**
90   * JQuery UI autocomplete source callback.
91   *
92   * @param {object} request
93   *   The request object.
94   * @param {function} response
95   *   The function to call with the response.
96   */
97  function sourceData(request, response) {
98    const elementId = this.element.attr('id');
99
100    if (!(elementId in autocomplete.cache)) {
101      autocomplete.cache[elementId] = {};
102    }
103
104    /**
105     * Filter through the suggestions removing all terms already tagged and
106     * display the available terms to the user.
107     *
108     * @param {object} suggestions
109     *   Suggestions returned by the server.
110     */
111    function showSuggestions(suggestions) {
112      const tagged = autocomplete.splitValues(request.term);
113      const il = tagged.length;
114      for (let i = 0; i < il; i++) {
115        const index = suggestions.indexOf(tagged[i]);
116        if (index >= 0) {
117          suggestions.splice(index, 1);
118        }
119      }
120      response(suggestions);
121    }
122
123    // Get the desired term and construct the autocomplete URL for it.
124    const term = autocomplete.extractLastTerm(request.term);
125
126    /**
127     * Transforms the data object into an array and update autocomplete results.
128     *
129     * @param {object} data
130     *   The data sent back from the server.
131     */
132    function sourceCallbackHandler(data) {
133      autocomplete.cache[elementId][term] = data;
134
135      // Send the new string array of terms to the jQuery UI list.
136      showSuggestions(data);
137    }
138
139    // Check if the term is already cached.
140    if (autocomplete.cache[elementId].hasOwnProperty(term)) {
141      showSuggestions(autocomplete.cache[elementId][term]);
142    } else {
143      const options = $.extend(
144        { success: sourceCallbackHandler, data: { q: term } },
145        autocomplete.ajax,
146      );
147      $.ajax(this.element.attr('data-autocomplete-path'), options);
148    }
149  }
150
151  /**
152   * Handles an autocomplete focus event.
153   *
154   * @return {boolean}
155   *   Always returns false.
156   */
157  function focusHandler() {
158    return false;
159  }
160
161  /**
162   * Handles an autocomplete select event.
163   *
164   * @param {jQuery.Event} event
165   *   The event triggered.
166   * @param {object} ui
167   *   The jQuery UI settings object.
168   *
169   * @return {boolean}
170   *   Returns false to indicate the event status.
171   */
172  function selectHandler(event, ui) {
173    const terms = autocomplete.splitValues(event.target.value);
174    // Remove the current input.
175    terms.pop();
176    // Add the selected item.
177    terms.push(ui.item.value);
178
179    event.target.value = terms.join(', ');
180    // Return false to tell jQuery UI that we've filled in the value already.
181    return false;
182  }
183
184  /**
185   * Override jQuery UI _renderItem function to output HTML by default.
186   *
187   * @param {jQuery} ul
188   *   jQuery collection of the ul element.
189   * @param {object} item
190   *   The list item to append.
191   *
192   * @return {jQuery}
193   *   jQuery collection of the ul element.
194   */
195  function renderItem(ul, item) {
196    return $('<li>').append($('<a>').html(item.label)).appendTo(ul);
197  }
198
199  /**
200   * Attaches the autocomplete behavior to all required fields.
201   *
202   * @type {Drupal~behavior}
203   *
204   * @prop {Drupal~behaviorAttach} attach
205   *   Attaches the autocomplete behaviors.
206   * @prop {Drupal~behaviorDetach} detach
207   *   Detaches the autocomplete behaviors.
208   */
209  Drupal.behaviors.autocomplete = {
210    attach(context) {
211      // Act on textfields with the "form-autocomplete" class.
212      once('autocomplete', 'input.form-autocomplete', context).forEach(
213        (element) => {
214          const $autocomplete = $(element);
215          // Allow options to be overridden per instance.
216          const blacklist = $autocomplete.attr(
217            'data-autocomplete-first-character-blacklist',
218          );
219          $.extend(autocomplete.options, {
220            firstCharacterBlacklist: blacklist || '',
221          });
222          // Use jQuery UI Autocomplete on the textfield.
223          $autocomplete.autocomplete(autocomplete.options).each(function () {
224            $(this).data('ui-autocomplete')._renderItem =
225              autocomplete.options.renderItem;
226          });
227
228          // Use CompositionEvent to handle IME inputs. It requests remote server on "compositionend" event only.
229          $autocomplete.on('compositionstart.autocomplete', () => {
230            autocomplete.options.isComposing = true;
231          });
232          $autocomplete.on('compositionend.autocomplete', () => {
233            autocomplete.options.isComposing = false;
234          });
235        },
236      );
237    },
238    detach(context, settings, trigger) {
239      if (trigger === 'unload') {
240        $(
241          once.remove('autocomplete', 'input.form-autocomplete', context),
242        ).autocomplete('destroy');
243      }
244    },
245  };
246
247  /**
248   * Autocomplete object implementation.
249   *
250   * @namespace Drupal.autocomplete
251   */
252  autocomplete = {
253    cache: {},
254    // Exposes options to allow overriding by contrib.
255    splitValues: autocompleteSplitValues,
256    extractLastTerm,
257    // jQuery UI autocomplete options.
258
259    /**
260     * JQuery UI option object.
261     *
262     * @name Drupal.autocomplete.options
263     */
264    options: {
265      source: sourceData,
266      focus: focusHandler,
267      search: searchHandler,
268      select: selectHandler,
269      renderItem,
270      minLength: 1,
271      // Custom options, used by Drupal.autocomplete.
272      firstCharacterBlacklist: '',
273      // Custom options, indicate IME usage status.
274      isComposing: false,
275    },
276    ajax: {
277      dataType: 'json',
278      jsonp: false,
279    },
280  };
281
282  Drupal.autocomplete = autocomplete;
283})(jQuery, Drupal);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.