Projet

Général

Profil

Paste
Télécharger (6,86 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / themes / bootstrap / js / misc / autocomplete.js @ 388c412d

1
(function ($) {
2

    
3
  /**
4
   * Attaches the autocomplete behavior to all required fields.
5
   */
6
  Drupal.behaviors.autocomplete = {
7
    attach: function (context) {
8
      var $context = $(context);
9
      var acdb = [];
10
      $context.find('input.autocomplete').once('autocomplete', function () {
11
        var uri = this.value;
12
        if (!acdb[uri]) {
13
          acdb[uri] = new Drupal.ACDB(uri);
14
        }
15
        var $input = $context.find('#' + this.id.substr(0, this.id.length - 13))
16
          .attr('autocomplete', 'OFF')
17
          .attr('aria-autocomplete', 'list');
18
        $context.find($input[0].form).submit(Drupal.autocompleteSubmit);
19
        $input.parents('.form-item')
20
          .attr('role', 'application')
21
          .append($('<span class="element-invisible" aria-live="assertive"></span>')
22
            .attr('id', $input.attr('id') + '-autocomplete-aria-live')
23
          );
24
        new Drupal.jsAC($input, acdb[uri], $context);
25
      });
26
    }
27
  };
28

    
29
  /**
30
   * Prevents the form from submitting if the suggestions popup is open
31
   * and closes the suggestions popup when doing so.
32
   */
33
  Drupal.autocompleteSubmit = function () {
34
    $('.form-autocomplete > .dropdown').each(function () {
35
      this.owner.hidePopup();
36
    });
37

    
38
    // Always return true to make it possible to submit even when there was an
39
    // autocomplete suggestion list open.
40
    return true;
41
  };
42

    
43
  /**
44
   * Highlights a suggestion.
45
   */
46
  Drupal.jsAC.prototype.highlight = function (node) {
47
    if (this.selected) {
48
      $(this.selected).removeClass('active');
49
    }
50
    $(node).addClass('active');
51
    this.selected = node;
52
    $(this.ariaLive).html($(this.selected).html());
53
  };
54

    
55
  /**
56
   * Unhighlights a suggestion.
57
   */
58
  Drupal.jsAC.prototype.unhighlight = function (node) {
59
    $(node).removeClass('active');
60
    this.selected = false;
61
    $(this.ariaLive).empty();
62
  };
63

    
64
  /**
65
   * Positions the suggestions popup and starts a search.
66
   */
67
  Drupal.jsAC.prototype.populatePopup = function () {
68
    var $input = $(this.input);
69
    // Show popup.
70
    if (this.popup) {
71
      $(this.popup).remove();
72
    }
73
    this.selected = false;
74
    this.popup = $('<div class="dropdown"></div>')[0];
75
    this.popup.owner = this;
76
    $input.parent().after(this.popup);
77

    
78
    // Do search.
79
    this.db.owner = this;
80
    this.db.search(this.input.value);
81
  };
82

    
83
  /**
84
   * Fills the suggestion popup with any matches received.
85
   */
86
  Drupal.jsAC.prototype.found = function (matches) {
87
    // If no value in the textfield, do not show the popup.
88
    if (!this.input.value.length) {
89
      return false;
90
    }
91

    
92
    // Prepare matches.
93
    var ul = $('<ul class="dropdown-menu"></ul>');
94
    var ac = this;
95
    ul.css({
96
      display: 'block',
97
      right: 0
98
    });
99
    for (var key in matches) {
100
      $('<li></li>')
101
        .html($('<a href="#"></a>').html(matches[key]).on('click', function (e) {
102
          e.preventDefault();
103
        }))
104
        .on('mousedown', function () {
105
          ac.hidePopup(this);
106
        })
107
        .on('mouseover', function () {
108
          ac.highlight(this);
109
        })
110
        .on('mouseout', function () {
111
          ac.unhighlight(this);
112
        })
113
        .data('autocompleteValue', key)
114
        .appendTo(ul);
115
    }
116

    
117
    // Show popup with matches, if any.
118
    if (this.popup) {
119
      if (ul.children().length) {
120
        $(this.popup).empty().append(ul).show();
121
        $(this.ariaLive).html(Drupal.t('Autocomplete popup'));
122
      }
123
      else {
124
        $(this.popup).css({visibility: 'hidden'});
125
        this.hidePopup();
126
      }
127
    }
128
  };
129

    
130
  /**
131
   * Finds the next sibling item.
132
   */
133
  Drupal.jsAC.prototype.findNextSibling = function (element) {
134
    var sibling = element && element.nextSibling;
135
    if (sibling && !this.validItem(sibling)) {
136
      return this.findNextSibling(sibling.nextSibling);
137
    }
138
    return sibling;
139
  };
140

    
141
  /**
142
   * Finds the previous sibling item.
143
   */
144
  Drupal.jsAC.prototype.findPreviousSibling = function (element) {
145
    var sibling = element && element.previousSibling;
146
    if (sibling && !this.validItem(sibling)) {
147
      return this.findPreviousSibling(sibling.previousSibling);
148
    }
149
    return sibling;
150
  };
151

    
152
  /**
153
   * Highlights the next suggestion.
154
   */
155
  Drupal.jsAC.prototype.selectDown = function () {
156
    var sibling = this.findNextSibling(this.selected);
157
    if (sibling) {
158
      this.highlight(sibling);
159
    }
160
    else if (this.popup) {
161
      var lis = $('li', this.popup);
162
      if (lis.length > 0) {
163
        if (this.validItem(lis[0])) {
164
          this.highlight(lis[0]);
165
        }
166
        else {
167
          this.highlight(this.findNextSibling(lis[0]));
168
        }
169
      }
170
    }
171
  };
172

    
173
  /**
174
   * Highlights the previous suggestion.
175
   */
176
  Drupal.jsAC.prototype.selectUp = function () {
177
    var sibling = this.findPreviousSibling(this.selected);
178
    if (sibling) {
179
      this.highlight(sibling);
180
    }
181
    else if (this.popup) {
182
      var lis = $('li', this.popup);
183
      if (lis.length > 0) {
184
        if (this.validItem(lis[lis.length - 1])) {
185
          this.highlight(lis[lis.length - 1]);
186
        }
187
        else {
188
          this.highlight(this.findPreviousSibling(lis[lis.length - 1]));
189
        }
190
      }
191
    }
192
  };
193

    
194
  /**
195
   * Ensures the item is valid.
196
   */
197
  Drupal.jsAC.prototype.validItem = function (element) {
198
    return !$(element).is('.dropdown-header, .divider, .disabled');
199
  };
200

    
201
  Drupal.jsAC.prototype.setStatus = function (status) {
202
    var $throbber = $(this.input).parent().find('.glyphicon-refresh, .autocomplete-throbber').first();
203
    var throbbingClass = $throbber.is('.autocomplete-throbber') ? 'throbbing' : 'glyphicon-spin';
204
    switch (status) {
205
      case 'begin':
206
        $throbber.addClass(throbbingClass);
207
        $(this.ariaLive).html(Drupal.t('Searching for matches...'));
208
        break;
209
      case 'cancel':
210
      case 'error':
211
      case 'found':
212
        $throbber.removeClass(throbbingClass);
213
        break;
214
    }
215
  };
216

    
217
  // Save the previous autocomplete prototype.
218
  var oldPrototype = Drupal.jsAC.prototype;
219

    
220
  /**
221
   * Override the autocomplete constructor.
222
   */
223
  Drupal.jsAC = function ($input, db, context) {
224
    var ac = this;
225

    
226
    // Context is normally passed by Drupal.behaviors.autocomplete above. However,
227
    // if a module has manually invoked this method they will likely not know
228
    // about this feature and a global fallback context to document must be used.
229
    // @see https://www.drupal.org/node/2594243
230
    // @see https://www.drupal.org/node/2315295
231
    this.$context = context && $(context) || $(document);
232

    
233
    this.input = $input[0];
234
    this.ariaLive = this.$context.find('#' + this.input.id + '-autocomplete-aria-live');
235
    this.db = db;
236
    $input
237
      .keydown(function (event) {
238
        return ac.onkeydown(this, event);
239
      })
240
      .keyup(function (event) {
241
        ac.onkeyup(this, event);
242
      })
243
      .blur(function () {
244
        ac.hidePopup();
245
        ac.db.cancel();
246
      });
247
  };
248

    
249
  // Restore the previous prototype.
250
  Drupal.jsAC.prototype = oldPrototype;
251

    
252
})(jQuery);