PageSourceSearch

https://portail.gim-idf.fr/jcms10/js/lib/bootstrap-typeahead/bootstrap-typeahead.js

js gim-idf.fr collected 2026-10-04 20:23:40 UTC 7,839 bytes, 311 lines download raw bytes

vendor: 7,604 bytes, lines 1-303
1/* =============================================================
2 * bootstrap-typeahead.js v2.2.1
3 * http://twitter.github.com/bootstrap/javascript.html#typeahead
4 * =============================================================
5 * Copyright 2012 Twitter, Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============================================================ */
19
20
21!function($){
22
23  "use strict"; // jshint ;_;
24
25
26 /* TYPEAHEAD PUBLIC CLASS DEFINITION
27  * ================================= */
28
29  window.Typeahead = function (element, options) {
30    this.$element = $(element)
31    this.options = $.extend({}, $.fn.typeahead.defaults, options)
32    this.matcher = this.options.matcher || this.matcher
33    this.sorter = this.options.sorter || this.sorter
34    this.highlighter = this.options.highlighter || this.highlighter
35    this.updater = this.options.updater || this.updater
36    this.$menu = $(this.options.menu).appendTo('body')
37    this.source = this.options.source
38    this.shown = false
39    this.listen()
40  }
41
42  // FIX:JCMS Hook to expose Typeahead prototype
43  Typeahead.prototype = { 
44
45    constructor: Typeahead
46
47  , select: function () {
48      var val = this.$menu.find('.active').attr('data-value')
49      this.$element
50        .val(this.updater(val))
51        .change()
52      return this.hide()
53    }
54
55  , updater: function (item) {
56      return item
57    }
58
59  , show: function () {
60      var pos = $.extend({}, this.$element.offset(), {
61        height: this.$element[0].offsetHeight
62      })
63
64      this.$menu.css({
65        top: pos.top + pos.height
66      , left: pos.left
67      })
68
69      this.$menu.show()
70      this.shown = true
71      return this
72    }
73
74  , hide: function () {
75      this.$menu.hide()
76      this.shown = false
77      return this
78    }
79
80  , lookup: function (event) {
81      var items
82
83      this.query = this.$element.val()
84
85      if (!this.query || this.query.length < this.options.minLength) {
86        return this.shown ? this.hide() : this
87      }
88
89      items = $.isFunction(this.source) ? this.source(this.query, $.proxy(this.process, this)) : this.source
90
91      return items ? this.process(items) : this
92    }
93
94  , process: function (items) {
95      var that = this
96
97      items = $.grep(items, function (item) {
98        return that.matcher(item)
99      })
100
101      items = this.sorter(items)
102
103      if (!items.length) {
104        return this.shown ? this.hide() : this
105      }
106
107      return this.render(items.slice(0, this.options.items)).show()
108    }
109
110  , matcher: function (item) {
111      return ~item.toLowerCase().indexOf(this.query.toLowerCase())
112    }
113
114  , sorter: function (items) {
115      var beginswith = []
116        , caseSensitive = []
117        , caseInsensitive = []
118        , item
119
120      while (item = items.shift()) {
121        if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item)
122        else if (~item.indexOf(this.query)) caseSensitive.push(item)
123        else caseInsensitive.push(item)
124      }
125
126      return beginswith.concat(caseSensitive, caseInsensitive)
127    }
128
129  , highlighter: function (item) {
130      var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
131      return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
132        return '<strong>' + match + '</strong>'
133      })
134    }
135
136  , render: function (items) {
137      var that = this
138
139      items = $(items).map(function (i, item) {
140        i = $(that.options.item).attr('data-value', item)
141        i.find('a').html(that.highlighter(item))
142        return i[0]
143      })
144
145      items.first().addClass('active')
146      this.$menu.html(items)
147      return this
148    }
149
150  , next: function (event) {
151      var active = this.$menu.find('.active').removeClass('active')
152        , next = active.next()
153
154      if (!next.length) {
155        next = $(this.$menu.find('li')[0])
156      }
157
158      next.addClass('active')
159    }
160
161  , prev: function (event) {
162      var active = this.$menu.find('.active').removeClass('active')
163        , prev = active.prev()
164
165      if (!prev.length) {
166        prev = this.$menu.find('li').last()
167      }
168
169      prev.addClass('active')
170    }
171
172  , listen: function () {
173      this.$element
174        .on('blur',     $.proxy(this.blur, this))
175        .on('keypress', $.proxy(this.keypress, this))
176        .on('keyup',    $.proxy(this.keyup, this))
177
178      if (this.eventSupported('keydown')) {
179        this.$element.on('keydown', $.proxy(this.keydown, this))
180      }
181
182      this.$menu
183        .on('click', $.proxy(this.click, this))
184        .on('mouseenter', 'li', $.proxy(this.mouseenter, this))
185    }
186
187  , eventSupported: function(eventName) {
188      var isSupported = eventName in this.$element
189      if (!isSupported) {
190        this.$element.setAttribute(eventName, 'return;')
191        isSupported = typeof this.$element[eventName] === 'function'
192      }
193      return isSupported
194    }
195
196  , move: function (e) {
197      if (!this.shown) return
198
199      switch(e.keyCode) {
200        case 9: // tab
201        case 13: // enter
202        case 27: // escape
203          e.preventDefault()
204          break
205
206        case 38: // up arrow
207          e.preventDefault()
208          this.prev()
209          break
210
211        case 40: // down arrow
212          e.preventDefault()
213          this.next()
214          break
215      }
216
217      e.stopPropagation()
218    }
219
220  , keydown: function (e) {
221      this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40,38,9,13,27])
222      this.move(e)
223    }
224
225  , keypress: function (e) {
226      if (this.suppressKeyPressRepeat) return
227      this.move(e)
228    }
229
230  , keyup: function (e) {
231      switch(e.keyCode) {
232        case 40: // down arrow
233        case 38: // up arrow
234        case 16: // shift
235        case 17: // ctrl
236        case 18: // alt
237          break
238
239        case 9: // tab
240        case 13: // enter
241          if (!this.shown) return
242          this.select()
243          break
244
245        case 27: // escape
246          if (!this.shown) return
247          this.hide()
248          break
249
250        default:
251          this.lookup()
252      }
253
254      e.stopPropagation()
255      e.preventDefault()
256  }
257
258  , blur: function (e) {
259      var that = this
260      setTimeout(function () { that.hide() }, 150)
261    }
262
263  , click: function (e) {
264      e.stopPropagation()
265      e.preventDefault()
266      this.select()
267    }
268
269  , mouseenter: function (e) {
270      this.$menu.find('.active').removeClass('active')
271      $(e.currentTarget).addClass('active')
272    }
273
274  }
275
276
277  /* TYPEAHEAD PLUGIN DEFINITION
278   * =========================== */
279
280  $.fn.typeahead = function (option) {
281    return this.each(function () {
282      var $this = $(this)
283        , data = $this.data('typeahead')
284        , options = typeof option == 'object' && option
285      if (!data) $this.data('typeahead', (data = new Typeahead(this, options)))
286      if (typeof option == 'string') data[option]()
287    })
288  }
289
290  $.fn.typeahead.defaults = {
291    source: []
292  , items: 8
293  , menu: '<ul class="typeahead dropdown-menu"></ul>'
294  , item: '<li><a href="#"></a></li>'
295  , minLength: 1
296  }
297
298  $.fn.typeahead.Constructor = Typeahead
299
300
301 /*   TYPEAHEAD DATA-API
302  * ================== */
303
304  $(document).on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) {
305    var $this = $(this)
306    if ($this.data('typeahead')) return
307    e.preventDefault()
308    $this.typeahead($this.data())
309  })
310
311}(window.jQuery);

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.