jekyll-navigation 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. data/.gitignore +17 -0
  2. data/.rspec +3 -0
  3. data/Gemfile +4 -0
  4. data/Guardfile +24 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +102 -0
  7. data/Rakefile +1 -0
  8. data/example-jekyll-site/_config.yml +2 -0
  9. data/example-jekyll-site/_layouts/default.html +35 -0
  10. data/example-jekyll-site/_plugins/navigation.rb +3 -0
  11. data/example-jekyll-site/_site/assets/css/bootstrap.css +6307 -0
  12. data/example-jekyll-site/_site/assets/css/bootstrap.min.css +873 -0
  13. data/example-jekyll-site/_site/assets/img/glyphicons-halflings-white.png +0 -0
  14. data/example-jekyll-site/_site/assets/img/glyphicons-halflings.png +0 -0
  15. data/example-jekyll-site/_site/assets/js/bootstrap.js +2287 -0
  16. data/example-jekyll-site/_site/assets/js/bootstrap.min.js +7 -0
  17. data/example-jekyll-site/_site/contact.html +45 -0
  18. data/example-jekyll-site/_site/digital_art.html +52 -0
  19. data/example-jekyll-site/_site/imprint.html +45 -0
  20. data/example-jekyll-site/_site/index.html +45 -0
  21. data/example-jekyll-site/_site/portfolio.html +52 -0
  22. data/example-jekyll-site/_site/traditional_art.html +52 -0
  23. data/example-jekyll-site/assets/css/bootstrap.css +6307 -0
  24. data/example-jekyll-site/assets/css/bootstrap.min.css +873 -0
  25. data/example-jekyll-site/assets/img/glyphicons-halflings-white.png +0 -0
  26. data/example-jekyll-site/assets/img/glyphicons-halflings.png +0 -0
  27. data/example-jekyll-site/assets/js/bootstrap.js +2287 -0
  28. data/example-jekyll-site/assets/js/bootstrap.min.js +7 -0
  29. data/example-jekyll-site/contact.md +22 -0
  30. data/example-jekyll-site/digital_art.md +24 -0
  31. data/example-jekyll-site/imprint.md +22 -0
  32. data/example-jekyll-site/index.md +22 -0
  33. data/example-jekyll-site/portfolio.md +22 -0
  34. data/example-jekyll-site/traditional_art.md +24 -0
  35. data/jekyll-navigation.gemspec +26 -0
  36. data/lib/jekyll-navigation.rb +38 -0
  37. data/lib/jekyll-navigation/navigation.rb +44 -0
  38. data/lib/jekyll-navigation/navigation_item.rb +49 -0
  39. data/lib/jekyll-navigation/version.rb +3 -0
  40. data/resources/example.png +0 -0
  41. data/spec/examples/pages.yml +14 -0
  42. data/spec/examples/pages_spec.rb +10 -0
  43. data/spec/jekyll-navigation_spec.rb +193 -0
  44. data/spec/spec_helper.rb +25 -0
  45. data/spec/support/pages.rb +35 -0
  46. metadata +177 -0
@@ -0,0 +1,2287 @@
1
+ /* ===================================================
2
+ * bootstrap-transition.js v2.3.1
3
+ * http://twitter.github.com/bootstrap/javascript.html#transitions
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
+ /* CSS TRANSITION SUPPORT (http://www.modernizr.com/)
27
+ * ======================================================= */
28
+
29
+ $(function () {
30
+
31
+ $.support.transition = (function () {
32
+
33
+ var transitionEnd = (function () {
34
+
35
+ var el = document.createElement('bootstrap')
36
+ , transEndEventNames = {
37
+ 'WebkitTransition' : 'webkitTransitionEnd'
38
+ , 'MozTransition' : 'transitionend'
39
+ , 'OTransition' : 'oTransitionEnd otransitionend'
40
+ , 'transition' : 'transitionend'
41
+ }
42
+ , name
43
+
44
+ for (name in transEndEventNames){
45
+ if (el.style[name] !== undefined) {
46
+ return transEndEventNames[name]
47
+ }
48
+ }
49
+
50
+ }())
51
+
52
+ return transitionEnd && {
53
+ end: transitionEnd
54
+ }
55
+
56
+ })()
57
+
58
+ })
59
+
60
+ }(window.jQuery);
61
+ /* =========================================================
62
+ * bootstrap-modal.js v2.3.1
63
+ * http://twitter.github.com/bootstrap/javascript.html#modals
64
+ * =========================================================
65
+ * Copyright 2012 Twitter, Inc.
66
+ *
67
+ * Licensed under the Apache License, Version 2.0 (the "License");
68
+ * you may not use this file except in compliance with the License.
69
+ * You may obtain a copy of the License at
70
+ *
71
+ * http://www.apache.org/licenses/LICENSE-2.0
72
+ *
73
+ * Unless required by applicable law or agreed to in writing, software
74
+ * distributed under the License is distributed on an "AS IS" BASIS,
75
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
76
+ * See the License for the specific language governing permissions and
77
+ * limitations under the License.
78
+ * ========================================================= */
79
+
80
+
81
+ !function ($) {
82
+
83
+ "use strict"; // jshint ;_;
84
+
85
+
86
+ /* MODAL CLASS DEFINITION
87
+ * ====================== */
88
+
89
+ var Modal = function (element, options) {
90
+ this.options = options
91
+ this.$element = $(element)
92
+ .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
93
+ this.options.remote && this.$element.find('.modal-body').load(this.options.remote)
94
+ }
95
+
96
+ Modal.prototype = {
97
+
98
+ constructor: Modal
99
+
100
+ , toggle: function () {
101
+ return this[!this.isShown ? 'show' : 'hide']()
102
+ }
103
+
104
+ , show: function () {
105
+ var that = this
106
+ , e = $.Event('show')
107
+
108
+ this.$element.trigger(e)
109
+
110
+ if (this.isShown || e.isDefaultPrevented()) return
111
+
112
+ this.isShown = true
113
+
114
+ this.escape()
115
+
116
+ this.backdrop(function () {
117
+ var transition = $.support.transition && that.$element.hasClass('fade')
118
+
119
+ if (!that.$element.parent().length) {
120
+ that.$element.appendTo(document.body) //don't move modals dom position
121
+ }
122
+
123
+ that.$element.show()
124
+
125
+ if (transition) {
126
+ that.$element[0].offsetWidth // force reflow
127
+ }
128
+
129
+ that.$element
130
+ .addClass('in')
131
+ .attr('aria-hidden', false)
132
+
133
+ that.enforceFocus()
134
+
135
+ transition ?
136
+ that.$element.one($.support.transition.end, function () { that.$element.focus().trigger('shown') }) :
137
+ that.$element.focus().trigger('shown')
138
+
139
+ })
140
+ }
141
+
142
+ , hide: function (e) {
143
+ e && e.preventDefault()
144
+
145
+ var that = this
146
+
147
+ e = $.Event('hide')
148
+
149
+ this.$element.trigger(e)
150
+
151
+ if (!this.isShown || e.isDefaultPrevented()) return
152
+
153
+ this.isShown = false
154
+
155
+ this.escape()
156
+
157
+ $(document).off('focusin.modal')
158
+
159
+ this.$element
160
+ .removeClass('in')
161
+ .attr('aria-hidden', true)
162
+
163
+ $.support.transition && this.$element.hasClass('fade') ?
164
+ this.hideWithTransition() :
165
+ this.hideModal()
166
+ }
167
+
168
+ , enforceFocus: function () {
169
+ var that = this
170
+ $(document).on('focusin.modal', function (e) {
171
+ if (that.$element[0] !== e.target && !that.$element.has(e.target).length) {
172
+ that.$element.focus()
173
+ }
174
+ })
175
+ }
176
+
177
+ , escape: function () {
178
+ var that = this
179
+ if (this.isShown && this.options.keyboard) {
180
+ this.$element.on('keyup.dismiss.modal', function ( e ) {
181
+ e.which == 27 && that.hide()
182
+ })
183
+ } else if (!this.isShown) {
184
+ this.$element.off('keyup.dismiss.modal')
185
+ }
186
+ }
187
+
188
+ , hideWithTransition: function () {
189
+ var that = this
190
+ , timeout = setTimeout(function () {
191
+ that.$element.off($.support.transition.end)
192
+ that.hideModal()
193
+ }, 500)
194
+
195
+ this.$element.one($.support.transition.end, function () {
196
+ clearTimeout(timeout)
197
+ that.hideModal()
198
+ })
199
+ }
200
+
201
+ , hideModal: function () {
202
+ var that = this
203
+ this.$element.hide()
204
+ this.backdrop(function () {
205
+ that.removeBackdrop()
206
+ that.$element.trigger('hidden')
207
+ })
208
+ }
209
+
210
+ , removeBackdrop: function () {
211
+ this.$backdrop && this.$backdrop.remove()
212
+ this.$backdrop = null
213
+ }
214
+
215
+ , backdrop: function (callback) {
216
+ var that = this
217
+ , animate = this.$element.hasClass('fade') ? 'fade' : ''
218
+
219
+ if (this.isShown && this.options.backdrop) {
220
+ var doAnimate = $.support.transition && animate
221
+
222
+ this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
223
+ .appendTo(document.body)
224
+
225
+ this.$backdrop.click(
226
+ this.options.backdrop == 'static' ?
227
+ $.proxy(this.$element[0].focus, this.$element[0])
228
+ : $.proxy(this.hide, this)
229
+ )
230
+
231
+ if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
232
+
233
+ this.$backdrop.addClass('in')
234
+
235
+ if (!callback) return
236
+
237
+ doAnimate ?
238
+ this.$backdrop.one($.support.transition.end, callback) :
239
+ callback()
240
+
241
+ } else if (!this.isShown && this.$backdrop) {
242
+ this.$backdrop.removeClass('in')
243
+
244
+ $.support.transition && this.$element.hasClass('fade')?
245
+ this.$backdrop.one($.support.transition.end, callback) :
246
+ callback()
247
+
248
+ } else if (callback) {
249
+ callback()
250
+ }
251
+ }
252
+ }
253
+
254
+
255
+ /* MODAL PLUGIN DEFINITION
256
+ * ======================= */
257
+
258
+ var old = $.fn.modal
259
+
260
+ $.fn.modal = function (option) {
261
+ return this.each(function () {
262
+ var $this = $(this)
263
+ , data = $this.data('modal')
264
+ , options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option)
265
+ if (!data) $this.data('modal', (data = new Modal(this, options)))
266
+ if (typeof option == 'string') data[option]()
267
+ else if (options.show) data.show()
268
+ })
269
+ }
270
+
271
+ $.fn.modal.defaults = {
272
+ backdrop: true
273
+ , keyboard: true
274
+ , show: true
275
+ }
276
+
277
+ $.fn.modal.Constructor = Modal
278
+
279
+
280
+ /* MODAL NO CONFLICT
281
+ * ================= */
282
+
283
+ $.fn.modal.noConflict = function () {
284
+ $.fn.modal = old
285
+ return this
286
+ }
287
+
288
+
289
+ /* MODAL DATA-API
290
+ * ============== */
291
+
292
+ $(document).on('click.modal.data-api', '[data-toggle="modal"]', function (e) {
293
+ var $this = $(this)
294
+ , href = $this.attr('href')
295
+ , $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
296
+ , option = $target.data('modal') ? 'toggle' : $.extend({ remote:!/#/.test(href) && href }, $target.data(), $this.data())
297
+
298
+ e.preventDefault()
299
+
300
+ $target
301
+ .modal(option)
302
+ .one('hide', function () {
303
+ $this.focus()
304
+ })
305
+ })
306
+
307
+ }(window.jQuery);
308
+
309
+ /* ============================================================
310
+ * bootstrap-dropdown.js v2.3.1
311
+ * http://twitter.github.com/bootstrap/javascript.html#dropdowns
312
+ * ============================================================
313
+ * Copyright 2012 Twitter, Inc.
314
+ *
315
+ * Licensed under the Apache License, Version 2.0 (the "License");
316
+ * you may not use this file except in compliance with the License.
317
+ * You may obtain a copy of the License at
318
+ *
319
+ * http://www.apache.org/licenses/LICENSE-2.0
320
+ *
321
+ * Unless required by applicable law or agreed to in writing, software
322
+ * distributed under the License is distributed on an "AS IS" BASIS,
323
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
324
+ * See the License for the specific language governing permissions and
325
+ * limitations under the License.
326
+ * ============================================================ */
327
+
328
+
329
+ !function ($) {
330
+
331
+ "use strict"; // jshint ;_;
332
+
333
+
334
+ /* DROPDOWN CLASS DEFINITION
335
+ * ========================= */
336
+
337
+ var toggle = '[data-toggle=dropdown]'
338
+ , Dropdown = function (element) {
339
+ var $el = $(element).on('click.dropdown.data-api', this.toggle)
340
+ $('html').on('click.dropdown.data-api', function () {
341
+ $el.parent().removeClass('open')
342
+ })
343
+ }
344
+
345
+ Dropdown.prototype = {
346
+
347
+ constructor: Dropdown
348
+
349
+ , toggle: function (e) {
350
+ var $this = $(this)
351
+ , $parent
352
+ , isActive
353
+
354
+ if ($this.is('.disabled, :disabled')) return
355
+
356
+ $parent = getParent($this)
357
+
358
+ isActive = $parent.hasClass('open')
359
+
360
+ clearMenus()
361
+
362
+ if (!isActive) {
363
+ $parent.toggleClass('open')
364
+ }
365
+
366
+ $this.focus()
367
+
368
+ return false
369
+ }
370
+
371
+ , keydown: function (e) {
372
+ var $this
373
+ , $items
374
+ , $active
375
+ , $parent
376
+ , isActive
377
+ , index
378
+
379
+ if (!/(38|40|27)/.test(e.keyCode)) return
380
+
381
+ $this = $(this)
382
+
383
+ e.preventDefault()
384
+ e.stopPropagation()
385
+
386
+ if ($this.is('.disabled, :disabled')) return
387
+
388
+ $parent = getParent($this)
389
+
390
+ isActive = $parent.hasClass('open')
391
+
392
+ if (!isActive || (isActive && e.keyCode == 27)) {
393
+ if (e.which == 27) $parent.find(toggle).focus()
394
+ return $this.click()
395
+ }
396
+
397
+ $items = $('[role=menu] li:not(.divider):visible a', $parent)
398
+
399
+ if (!$items.length) return
400
+
401
+ index = $items.index($items.filter(':focus'))
402
+
403
+ if (e.keyCode == 38 && index > 0) index-- // up
404
+ if (e.keyCode == 40 && index < $items.length - 1) index++ // down
405
+ if (!~index) index = 0
406
+
407
+ $items
408
+ .eq(index)
409
+ .focus()
410
+ }
411
+
412
+ }
413
+
414
+ function clearMenus() {
415
+ $(toggle).each(function () {
416
+ getParent($(this)).removeClass('open')
417
+ })
418
+ }
419
+
420
+ function getParent($this) {
421
+ var selector = $this.attr('data-target')
422
+ , $parent
423
+
424
+ if (!selector) {
425
+ selector = $this.attr('href')
426
+ selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
427
+ }
428
+
429
+ $parent = selector && $(selector)
430
+
431
+ if (!$parent || !$parent.length) $parent = $this.parent()
432
+
433
+ return $parent
434
+ }
435
+
436
+
437
+ /* DROPDOWN PLUGIN DEFINITION
438
+ * ========================== */
439
+
440
+ var old = $.fn.dropdown
441
+
442
+ $.fn.dropdown = function (option) {
443
+ return this.each(function () {
444
+ var $this = $(this)
445
+ , data = $this.data('dropdown')
446
+ if (!data) $this.data('dropdown', (data = new Dropdown(this)))
447
+ if (typeof option == 'string') data[option].call($this)
448
+ })
449
+ }
450
+
451
+ $.fn.dropdown.Constructor = Dropdown
452
+
453
+
454
+ /* DROPDOWN NO CONFLICT
455
+ * ==================== */
456
+
457
+ $.fn.dropdown.noConflict = function () {
458
+ $.fn.dropdown = old
459
+ return this
460
+ }
461
+
462
+
463
+ /* APPLY TO STANDARD DROPDOWN ELEMENTS
464
+ * =================================== */
465
+
466
+ $(document)
467
+ .on('click.dropdown.data-api', clearMenus)
468
+ .on('click.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
469
+ .on('click.dropdown-menu', function (e) { e.stopPropagation() })
470
+ .on('click.dropdown.data-api' , toggle, Dropdown.prototype.toggle)
471
+ .on('keydown.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
472
+
473
+ }(window.jQuery);
474
+
475
+ /* =============================================================
476
+ * bootstrap-scrollspy.js v2.3.1
477
+ * http://twitter.github.com/bootstrap/javascript.html#scrollspy
478
+ * =============================================================
479
+ * Copyright 2012 Twitter, Inc.
480
+ *
481
+ * Licensed under the Apache License, Version 2.0 (the "License");
482
+ * you may not use this file except in compliance with the License.
483
+ * You may obtain a copy of the License at
484
+ *
485
+ * http://www.apache.org/licenses/LICENSE-2.0
486
+ *
487
+ * Unless required by applicable law or agreed to in writing, software
488
+ * distributed under the License is distributed on an "AS IS" BASIS,
489
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
490
+ * See the License for the specific language governing permissions and
491
+ * limitations under the License.
492
+ * ============================================================== */
493
+
494
+
495
+ !function ($) {
496
+
497
+ "use strict"; // jshint ;_;
498
+
499
+
500
+ /* SCROLLSPY CLASS DEFINITION
501
+ * ========================== */
502
+
503
+ function ScrollSpy(element, options) {
504
+ var process = $.proxy(this.process, this)
505
+ , $element = $(element).is('body') ? $(window) : $(element)
506
+ , href
507
+ this.options = $.extend({}, $.fn.scrollspy.defaults, options)
508
+ this.$scrollElement = $element.on('scroll.scroll-spy.data-api', process)
509
+ this.selector = (this.options.target
510
+ || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
511
+ || '') + ' .nav li > a'
512
+ this.$body = $('body')
513
+ this.refresh()
514
+ this.process()
515
+ }
516
+
517
+ ScrollSpy.prototype = {
518
+
519
+ constructor: ScrollSpy
520
+
521
+ , refresh: function () {
522
+ var self = this
523
+ , $targets
524
+
525
+ this.offsets = $([])
526
+ this.targets = $([])
527
+
528
+ $targets = this.$body
529
+ .find(this.selector)
530
+ .map(function () {
531
+ var $el = $(this)
532
+ , href = $el.data('target') || $el.attr('href')
533
+ , $href = /^#\w/.test(href) && $(href)
534
+ return ( $href
535
+ && $href.length
536
+ && [[ $href.position().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]] ) || null
537
+ })
538
+ .sort(function (a, b) { return a[0] - b[0] })
539
+ .each(function () {
540
+ self.offsets.push(this[0])
541
+ self.targets.push(this[1])
542
+ })
543
+ }
544
+
545
+ , process: function () {
546
+ var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
547
+ , scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight
548
+ , maxScroll = scrollHeight - this.$scrollElement.height()
549
+ , offsets = this.offsets
550
+ , targets = this.targets
551
+ , activeTarget = this.activeTarget
552
+ , i
553
+
554
+ if (scrollTop >= maxScroll) {
555
+ return activeTarget != (i = targets.last()[0])
556
+ && this.activate ( i )
557
+ }
558
+
559
+ for (i = offsets.length; i--;) {
560
+ activeTarget != targets[i]
561
+ && scrollTop >= offsets[i]
562
+ && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
563
+ && this.activate( targets[i] )
564
+ }
565
+ }
566
+
567
+ , activate: function (target) {
568
+ var active
569
+ , selector
570
+
571
+ this.activeTarget = target
572
+
573
+ $(this.selector)
574
+ .parent('.active')
575
+ .removeClass('active')
576
+
577
+ selector = this.selector
578
+ + '[data-target="' + target + '"],'
579
+ + this.selector + '[href="' + target + '"]'
580
+
581
+ active = $(selector)
582
+ .parent('li')
583
+ .addClass('active')
584
+
585
+ if (active.parent('.dropdown-menu').length) {
586
+ active = active.closest('li.dropdown').addClass('active')
587
+ }
588
+
589
+ active.trigger('activate')
590
+ }
591
+
592
+ }
593
+
594
+
595
+ /* SCROLLSPY PLUGIN DEFINITION
596
+ * =========================== */
597
+
598
+ var old = $.fn.scrollspy
599
+
600
+ $.fn.scrollspy = function (option) {
601
+ return this.each(function () {
602
+ var $this = $(this)
603
+ , data = $this.data('scrollspy')
604
+ , options = typeof option == 'object' && option
605
+ if (!data) $this.data('scrollspy', (data = new ScrollSpy(this, options)))
606
+ if (typeof option == 'string') data[option]()
607
+ })
608
+ }
609
+
610
+ $.fn.scrollspy.Constructor = ScrollSpy
611
+
612
+ $.fn.scrollspy.defaults = {
613
+ offset: 10
614
+ }
615
+
616
+
617
+ /* SCROLLSPY NO CONFLICT
618
+ * ===================== */
619
+
620
+ $.fn.scrollspy.noConflict = function () {
621
+ $.fn.scrollspy = old
622
+ return this
623
+ }
624
+
625
+
626
+ /* SCROLLSPY DATA-API
627
+ * ================== */
628
+
629
+ $(window).on('load', function () {
630
+ $('[data-spy="scroll"]').each(function () {
631
+ var $spy = $(this)
632
+ $spy.scrollspy($spy.data())
633
+ })
634
+ })
635
+
636
+ }(window.jQuery);
637
+ /* ========================================================
638
+ * bootstrap-tab.js v2.3.1
639
+ * http://twitter.github.com/bootstrap/javascript.html#tabs
640
+ * ========================================================
641
+ * Copyright 2012 Twitter, Inc.
642
+ *
643
+ * Licensed under the Apache License, Version 2.0 (the "License");
644
+ * you may not use this file except in compliance with the License.
645
+ * You may obtain a copy of the License at
646
+ *
647
+ * http://www.apache.org/licenses/LICENSE-2.0
648
+ *
649
+ * Unless required by applicable law or agreed to in writing, software
650
+ * distributed under the License is distributed on an "AS IS" BASIS,
651
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
652
+ * See the License for the specific language governing permissions and
653
+ * limitations under the License.
654
+ * ======================================================== */
655
+
656
+
657
+ !function ($) {
658
+
659
+ "use strict"; // jshint ;_;
660
+
661
+
662
+ /* TAB CLASS DEFINITION
663
+ * ==================== */
664
+
665
+ var Tab = function (element) {
666
+ this.element = $(element)
667
+ }
668
+
669
+ Tab.prototype = {
670
+
671
+ constructor: Tab
672
+
673
+ , show: function () {
674
+ var $this = this.element
675
+ , $ul = $this.closest('ul:not(.dropdown-menu)')
676
+ , selector = $this.attr('data-target')
677
+ , previous
678
+ , $target
679
+ , e
680
+
681
+ if (!selector) {
682
+ selector = $this.attr('href')
683
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
684
+ }
685
+
686
+ if ( $this.parent('li').hasClass('active') ) return
687
+
688
+ previous = $ul.find('.active:last a')[0]
689
+
690
+ e = $.Event('show', {
691
+ relatedTarget: previous
692
+ })
693
+
694
+ $this.trigger(e)
695
+
696
+ if (e.isDefaultPrevented()) return
697
+
698
+ $target = $(selector)
699
+
700
+ this.activate($this.parent('li'), $ul)
701
+ this.activate($target, $target.parent(), function () {
702
+ $this.trigger({
703
+ type: 'shown'
704
+ , relatedTarget: previous
705
+ })
706
+ })
707
+ }
708
+
709
+ , activate: function ( element, container, callback) {
710
+ var $active = container.find('> .active')
711
+ , transition = callback
712
+ && $.support.transition
713
+ && $active.hasClass('fade')
714
+
715
+ function next() {
716
+ $active
717
+ .removeClass('active')
718
+ .find('> .dropdown-menu > .active')
719
+ .removeClass('active')
720
+
721
+ element.addClass('active')
722
+
723
+ if (transition) {
724
+ element[0].offsetWidth // reflow for transition
725
+ element.addClass('in')
726
+ } else {
727
+ element.removeClass('fade')
728
+ }
729
+
730
+ if ( element.parent('.dropdown-menu') ) {
731
+ element.closest('li.dropdown').addClass('active')
732
+ }
733
+
734
+ callback && callback()
735
+ }
736
+
737
+ transition ?
738
+ $active.one($.support.transition.end, next) :
739
+ next()
740
+
741
+ $active.removeClass('in')
742
+ }
743
+ }
744
+
745
+
746
+ /* TAB PLUGIN DEFINITION
747
+ * ===================== */
748
+
749
+ var old = $.fn.tab
750
+
751
+ $.fn.tab = function ( option ) {
752
+ return this.each(function () {
753
+ var $this = $(this)
754
+ , data = $this.data('tab')
755
+ if (!data) $this.data('tab', (data = new Tab(this)))
756
+ if (typeof option == 'string') data[option]()
757
+ })
758
+ }
759
+
760
+ $.fn.tab.Constructor = Tab
761
+
762
+
763
+ /* TAB NO CONFLICT
764
+ * =============== */
765
+
766
+ $.fn.tab.noConflict = function () {
767
+ $.fn.tab = old
768
+ return this
769
+ }
770
+
771
+
772
+ /* TAB DATA-API
773
+ * ============ */
774
+
775
+ $(document).on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
776
+ e.preventDefault()
777
+ $(this).tab('show')
778
+ })
779
+
780
+ }(window.jQuery);
781
+ /* ===========================================================
782
+ * bootstrap-tooltip.js v2.3.1
783
+ * http://twitter.github.com/bootstrap/javascript.html#tooltips
784
+ * Inspired by the original jQuery.tipsy by Jason Frame
785
+ * ===========================================================
786
+ * Copyright 2012 Twitter, Inc.
787
+ *
788
+ * Licensed under the Apache License, Version 2.0 (the "License");
789
+ * you may not use this file except in compliance with the License.
790
+ * You may obtain a copy of the License at
791
+ *
792
+ * http://www.apache.org/licenses/LICENSE-2.0
793
+ *
794
+ * Unless required by applicable law or agreed to in writing, software
795
+ * distributed under the License is distributed on an "AS IS" BASIS,
796
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
797
+ * See the License for the specific language governing permissions and
798
+ * limitations under the License.
799
+ * ========================================================== */
800
+
801
+
802
+ !function ($) {
803
+
804
+ "use strict"; // jshint ;_;
805
+
806
+
807
+ /* TOOLTIP PUBLIC CLASS DEFINITION
808
+ * =============================== */
809
+
810
+ var Tooltip = function (element, options) {
811
+ this.init('tooltip', element, options)
812
+ }
813
+
814
+ Tooltip.prototype = {
815
+
816
+ constructor: Tooltip
817
+
818
+ , init: function (type, element, options) {
819
+ var eventIn
820
+ , eventOut
821
+ , triggers
822
+ , trigger
823
+ , i
824
+
825
+ this.type = type
826
+ this.$element = $(element)
827
+ this.options = this.getOptions(options)
828
+ this.enabled = true
829
+
830
+ triggers = this.options.trigger.split(' ')
831
+
832
+ for (i = triggers.length; i--;) {
833
+ trigger = triggers[i]
834
+ if (trigger == 'click') {
835
+ this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
836
+ } else if (trigger != 'manual') {
837
+ eventIn = trigger == 'hover' ? 'mouseenter' : 'focus'
838
+ eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'
839
+ this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
840
+ this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
841
+ }
842
+ }
843
+
844
+ this.options.selector ?
845
+ (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
846
+ this.fixTitle()
847
+ }
848
+
849
+ , getOptions: function (options) {
850
+ options = $.extend({}, $.fn[this.type].defaults, this.$element.data(), options)
851
+
852
+ if (options.delay && typeof options.delay == 'number') {
853
+ options.delay = {
854
+ show: options.delay
855
+ , hide: options.delay
856
+ }
857
+ }
858
+
859
+ return options
860
+ }
861
+
862
+ , enter: function (e) {
863
+ var defaults = $.fn[this.type].defaults
864
+ , options = {}
865
+ , self
866
+
867
+ this._options && $.each(this._options, function (key, value) {
868
+ if (defaults[key] != value) options[key] = value
869
+ }, this)
870
+
871
+ self = $(e.currentTarget)[this.type](options).data(this.type)
872
+
873
+ if (!self.options.delay || !self.options.delay.show) return self.show()
874
+
875
+ clearTimeout(this.timeout)
876
+ self.hoverState = 'in'
877
+ this.timeout = setTimeout(function() {
878
+ if (self.hoverState == 'in') self.show()
879
+ }, self.options.delay.show)
880
+ }
881
+
882
+ , leave: function (e) {
883
+ var self = $(e.currentTarget)[this.type](this._options).data(this.type)
884
+
885
+ if (this.timeout) clearTimeout(this.timeout)
886
+ if (!self.options.delay || !self.options.delay.hide) return self.hide()
887
+
888
+ self.hoverState = 'out'
889
+ this.timeout = setTimeout(function() {
890
+ if (self.hoverState == 'out') self.hide()
891
+ }, self.options.delay.hide)
892
+ }
893
+
894
+ , show: function () {
895
+ var $tip
896
+ , pos
897
+ , actualWidth
898
+ , actualHeight
899
+ , placement
900
+ , tp
901
+ , e = $.Event('show')
902
+
903
+ if (this.hasContent() && this.enabled) {
904
+ this.$element.trigger(e)
905
+ if (e.isDefaultPrevented()) return
906
+ $tip = this.tip()
907
+ this.setContent()
908
+
909
+ if (this.options.animation) {
910
+ $tip.addClass('fade')
911
+ }
912
+
913
+ placement = typeof this.options.placement == 'function' ?
914
+ this.options.placement.call(this, $tip[0], this.$element[0]) :
915
+ this.options.placement
916
+
917
+ $tip
918
+ .detach()
919
+ .css({ top: 0, left: 0, display: 'block' })
920
+
921
+ this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
922
+
923
+ pos = this.getPosition()
924
+
925
+ actualWidth = $tip[0].offsetWidth
926
+ actualHeight = $tip[0].offsetHeight
927
+
928
+ switch (placement) {
929
+ case 'bottom':
930
+ tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
931
+ break
932
+ case 'top':
933
+ tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
934
+ break
935
+ case 'left':
936
+ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
937
+ break
938
+ case 'right':
939
+ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
940
+ break
941
+ }
942
+
943
+ this.applyPlacement(tp, placement)
944
+ this.$element.trigger('shown')
945
+ }
946
+ }
947
+
948
+ , applyPlacement: function(offset, placement){
949
+ var $tip = this.tip()
950
+ , width = $tip[0].offsetWidth
951
+ , height = $tip[0].offsetHeight
952
+ , actualWidth
953
+ , actualHeight
954
+ , delta
955
+ , replace
956
+
957
+ $tip
958
+ .offset(offset)
959
+ .addClass(placement)
960
+ .addClass('in')
961
+
962
+ actualWidth = $tip[0].offsetWidth
963
+ actualHeight = $tip[0].offsetHeight
964
+
965
+ if (placement == 'top' && actualHeight != height) {
966
+ offset.top = offset.top + height - actualHeight
967
+ replace = true
968
+ }
969
+
970
+ if (placement == 'bottom' || placement == 'top') {
971
+ delta = 0
972
+
973
+ if (offset.left < 0){
974
+ delta = offset.left * -2
975
+ offset.left = 0
976
+ $tip.offset(offset)
977
+ actualWidth = $tip[0].offsetWidth
978
+ actualHeight = $tip[0].offsetHeight
979
+ }
980
+
981
+ this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
982
+ } else {
983
+ this.replaceArrow(actualHeight - height, actualHeight, 'top')
984
+ }
985
+
986
+ if (replace) $tip.offset(offset)
987
+ }
988
+
989
+ , replaceArrow: function(delta, dimension, position){
990
+ this
991
+ .arrow()
992
+ .css(position, delta ? (50 * (1 - delta / dimension) + "%") : '')
993
+ }
994
+
995
+ , setContent: function () {
996
+ var $tip = this.tip()
997
+ , title = this.getTitle()
998
+
999
+ $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
1000
+ $tip.removeClass('fade in top bottom left right')
1001
+ }
1002
+
1003
+ , hide: function () {
1004
+ var that = this
1005
+ , $tip = this.tip()
1006
+ , e = $.Event('hide')
1007
+
1008
+ this.$element.trigger(e)
1009
+ if (e.isDefaultPrevented()) return
1010
+
1011
+ $tip.removeClass('in')
1012
+
1013
+ function removeWithAnimation() {
1014
+ var timeout = setTimeout(function () {
1015
+ $tip.off($.support.transition.end).detach()
1016
+ }, 500)
1017
+
1018
+ $tip.one($.support.transition.end, function () {
1019
+ clearTimeout(timeout)
1020
+ $tip.detach()
1021
+ })
1022
+ }
1023
+
1024
+ $.support.transition && this.$tip.hasClass('fade') ?
1025
+ removeWithAnimation() :
1026
+ $tip.detach()
1027
+
1028
+ this.$element.trigger('hidden')
1029
+
1030
+ return this
1031
+ }
1032
+
1033
+ , fixTitle: function () {
1034
+ var $e = this.$element
1035
+ if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
1036
+ $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
1037
+ }
1038
+ }
1039
+
1040
+ , hasContent: function () {
1041
+ return this.getTitle()
1042
+ }
1043
+
1044
+ , getPosition: function () {
1045
+ var el = this.$element[0]
1046
+ return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
1047
+ width: el.offsetWidth
1048
+ , height: el.offsetHeight
1049
+ }, this.$element.offset())
1050
+ }
1051
+
1052
+ , getTitle: function () {
1053
+ var title
1054
+ , $e = this.$element
1055
+ , o = this.options
1056
+
1057
+ title = $e.attr('data-original-title')
1058
+ || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
1059
+
1060
+ return title
1061
+ }
1062
+
1063
+ , tip: function () {
1064
+ return this.$tip = this.$tip || $(this.options.template)
1065
+ }
1066
+
1067
+ , arrow: function(){
1068
+ return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow")
1069
+ }
1070
+
1071
+ , validate: function () {
1072
+ if (!this.$element[0].parentNode) {
1073
+ this.hide()
1074
+ this.$element = null
1075
+ this.options = null
1076
+ }
1077
+ }
1078
+
1079
+ , enable: function () {
1080
+ this.enabled = true
1081
+ }
1082
+
1083
+ , disable: function () {
1084
+ this.enabled = false
1085
+ }
1086
+
1087
+ , toggleEnabled: function () {
1088
+ this.enabled = !this.enabled
1089
+ }
1090
+
1091
+ , toggle: function (e) {
1092
+ var self = e ? $(e.currentTarget)[this.type](this._options).data(this.type) : this
1093
+ self.tip().hasClass('in') ? self.hide() : self.show()
1094
+ }
1095
+
1096
+ , destroy: function () {
1097
+ this.hide().$element.off('.' + this.type).removeData(this.type)
1098
+ }
1099
+
1100
+ }
1101
+
1102
+
1103
+ /* TOOLTIP PLUGIN DEFINITION
1104
+ * ========================= */
1105
+
1106
+ var old = $.fn.tooltip
1107
+
1108
+ $.fn.tooltip = function ( option ) {
1109
+ return this.each(function () {
1110
+ var $this = $(this)
1111
+ , data = $this.data('tooltip')
1112
+ , options = typeof option == 'object' && option
1113
+ if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
1114
+ if (typeof option == 'string') data[option]()
1115
+ })
1116
+ }
1117
+
1118
+ $.fn.tooltip.Constructor = Tooltip
1119
+
1120
+ $.fn.tooltip.defaults = {
1121
+ animation: true
1122
+ , placement: 'top'
1123
+ , selector: false
1124
+ , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
1125
+ , trigger: 'hover focus'
1126
+ , title: ''
1127
+ , delay: 0
1128
+ , html: false
1129
+ , container: false
1130
+ }
1131
+
1132
+
1133
+ /* TOOLTIP NO CONFLICT
1134
+ * =================== */
1135
+
1136
+ $.fn.tooltip.noConflict = function () {
1137
+ $.fn.tooltip = old
1138
+ return this
1139
+ }
1140
+
1141
+ }(window.jQuery);
1142
+
1143
+ /* ===========================================================
1144
+ * bootstrap-popover.js v2.3.1
1145
+ * http://twitter.github.com/bootstrap/javascript.html#popovers
1146
+ * ===========================================================
1147
+ * Copyright 2012 Twitter, Inc.
1148
+ *
1149
+ * Licensed under the Apache License, Version 2.0 (the "License");
1150
+ * you may not use this file except in compliance with the License.
1151
+ * You may obtain a copy of the License at
1152
+ *
1153
+ * http://www.apache.org/licenses/LICENSE-2.0
1154
+ *
1155
+ * Unless required by applicable law or agreed to in writing, software
1156
+ * distributed under the License is distributed on an "AS IS" BASIS,
1157
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1158
+ * See the License for the specific language governing permissions and
1159
+ * limitations under the License.
1160
+ * =========================================================== */
1161
+
1162
+
1163
+ !function ($) {
1164
+
1165
+ "use strict"; // jshint ;_;
1166
+
1167
+
1168
+ /* POPOVER PUBLIC CLASS DEFINITION
1169
+ * =============================== */
1170
+
1171
+ var Popover = function (element, options) {
1172
+ this.init('popover', element, options)
1173
+ }
1174
+
1175
+
1176
+ /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js
1177
+ ========================================== */
1178
+
1179
+ Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {
1180
+
1181
+ constructor: Popover
1182
+
1183
+ , setContent: function () {
1184
+ var $tip = this.tip()
1185
+ , title = this.getTitle()
1186
+ , content = this.getContent()
1187
+
1188
+ $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
1189
+ $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)
1190
+
1191
+ $tip.removeClass('fade top bottom left right in')
1192
+ }
1193
+
1194
+ , hasContent: function () {
1195
+ return this.getTitle() || this.getContent()
1196
+ }
1197
+
1198
+ , getContent: function () {
1199
+ var content
1200
+ , $e = this.$element
1201
+ , o = this.options
1202
+
1203
+ content = (typeof o.content == 'function' ? o.content.call($e[0]) : o.content)
1204
+ || $e.attr('data-content')
1205
+
1206
+ return content
1207
+ }
1208
+
1209
+ , tip: function () {
1210
+ if (!this.$tip) {
1211
+ this.$tip = $(this.options.template)
1212
+ }
1213
+ return this.$tip
1214
+ }
1215
+
1216
+ , destroy: function () {
1217
+ this.hide().$element.off('.' + this.type).removeData(this.type)
1218
+ }
1219
+
1220
+ })
1221
+
1222
+
1223
+ /* POPOVER PLUGIN DEFINITION
1224
+ * ======================= */
1225
+
1226
+ var old = $.fn.popover
1227
+
1228
+ $.fn.popover = function (option) {
1229
+ return this.each(function () {
1230
+ var $this = $(this)
1231
+ , data = $this.data('popover')
1232
+ , options = typeof option == 'object' && option
1233
+ if (!data) $this.data('popover', (data = new Popover(this, options)))
1234
+ if (typeof option == 'string') data[option]()
1235
+ })
1236
+ }
1237
+
1238
+ $.fn.popover.Constructor = Popover
1239
+
1240
+ $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
1241
+ placement: 'right'
1242
+ , trigger: 'click'
1243
+ , content: ''
1244
+ , template: '<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
1245
+ })
1246
+
1247
+
1248
+ /* POPOVER NO CONFLICT
1249
+ * =================== */
1250
+
1251
+ $.fn.popover.noConflict = function () {
1252
+ $.fn.popover = old
1253
+ return this
1254
+ }
1255
+
1256
+ }(window.jQuery);
1257
+
1258
+ /* ==========================================================
1259
+ * bootstrap-affix.js v2.3.1
1260
+ * http://twitter.github.com/bootstrap/javascript.html#affix
1261
+ * ==========================================================
1262
+ * Copyright 2012 Twitter, Inc.
1263
+ *
1264
+ * Licensed under the Apache License, Version 2.0 (the "License");
1265
+ * you may not use this file except in compliance with the License.
1266
+ * You may obtain a copy of the License at
1267
+ *
1268
+ * http://www.apache.org/licenses/LICENSE-2.0
1269
+ *
1270
+ * Unless required by applicable law or agreed to in writing, software
1271
+ * distributed under the License is distributed on an "AS IS" BASIS,
1272
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1273
+ * See the License for the specific language governing permissions and
1274
+ * limitations under the License.
1275
+ * ========================================================== */
1276
+
1277
+
1278
+ !function ($) {
1279
+
1280
+ "use strict"; // jshint ;_;
1281
+
1282
+
1283
+ /* AFFIX CLASS DEFINITION
1284
+ * ====================== */
1285
+
1286
+ var Affix = function (element, options) {
1287
+ this.options = $.extend({}, $.fn.affix.defaults, options)
1288
+ this.$window = $(window)
1289
+ .on('scroll.affix.data-api', $.proxy(this.checkPosition, this))
1290
+ .on('click.affix.data-api', $.proxy(function () { setTimeout($.proxy(this.checkPosition, this), 1) }, this))
1291
+ this.$element = $(element)
1292
+ this.checkPosition()
1293
+ }
1294
+
1295
+ Affix.prototype.checkPosition = function () {
1296
+ if (!this.$element.is(':visible')) return
1297
+
1298
+ var scrollHeight = $(document).height()
1299
+ , scrollTop = this.$window.scrollTop()
1300
+ , position = this.$element.offset()
1301
+ , offset = this.options.offset
1302
+ , offsetBottom = offset.bottom
1303
+ , offsetTop = offset.top
1304
+ , reset = 'affix affix-top affix-bottom'
1305
+ , affix
1306
+
1307
+ if (typeof offset != 'object') offsetBottom = offsetTop = offset
1308
+ if (typeof offsetTop == 'function') offsetTop = offset.top()
1309
+ if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()
1310
+
1311
+ affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ?
1312
+ false : offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ?
1313
+ 'bottom' : offsetTop != null && scrollTop <= offsetTop ?
1314
+ 'top' : false
1315
+
1316
+ if (this.affixed === affix) return
1317
+
1318
+ this.affixed = affix
1319
+ this.unpin = affix == 'bottom' ? position.top - scrollTop : null
1320
+
1321
+ this.$element.removeClass(reset).addClass('affix' + (affix ? '-' + affix : ''))
1322
+ }
1323
+
1324
+
1325
+ /* AFFIX PLUGIN DEFINITION
1326
+ * ======================= */
1327
+
1328
+ var old = $.fn.affix
1329
+
1330
+ $.fn.affix = function (option) {
1331
+ return this.each(function () {
1332
+ var $this = $(this)
1333
+ , data = $this.data('affix')
1334
+ , options = typeof option == 'object' && option
1335
+ if (!data) $this.data('affix', (data = new Affix(this, options)))
1336
+ if (typeof option == 'string') data[option]()
1337
+ })
1338
+ }
1339
+
1340
+ $.fn.affix.Constructor = Affix
1341
+
1342
+ $.fn.affix.defaults = {
1343
+ offset: 0
1344
+ }
1345
+
1346
+
1347
+ /* AFFIX NO CONFLICT
1348
+ * ================= */
1349
+
1350
+ $.fn.affix.noConflict = function () {
1351
+ $.fn.affix = old
1352
+ return this
1353
+ }
1354
+
1355
+
1356
+ /* AFFIX DATA-API
1357
+ * ============== */
1358
+
1359
+ $(window).on('load', function () {
1360
+ $('[data-spy="affix"]').each(function () {
1361
+ var $spy = $(this)
1362
+ , data = $spy.data()
1363
+
1364
+ data.offset = data.offset || {}
1365
+
1366
+ data.offsetBottom && (data.offset.bottom = data.offsetBottom)
1367
+ data.offsetTop && (data.offset.top = data.offsetTop)
1368
+
1369
+ $spy.affix(data)
1370
+ })
1371
+ })
1372
+
1373
+
1374
+ }(window.jQuery);
1375
+ /* ==========================================================
1376
+ * bootstrap-alert.js v2.3.1
1377
+ * http://twitter.github.com/bootstrap/javascript.html#alerts
1378
+ * ==========================================================
1379
+ * Copyright 2012 Twitter, Inc.
1380
+ *
1381
+ * Licensed under the Apache License, Version 2.0 (the "License");
1382
+ * you may not use this file except in compliance with the License.
1383
+ * You may obtain a copy of the License at
1384
+ *
1385
+ * http://www.apache.org/licenses/LICENSE-2.0
1386
+ *
1387
+ * Unless required by applicable law or agreed to in writing, software
1388
+ * distributed under the License is distributed on an "AS IS" BASIS,
1389
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1390
+ * See the License for the specific language governing permissions and
1391
+ * limitations under the License.
1392
+ * ========================================================== */
1393
+
1394
+
1395
+ !function ($) {
1396
+
1397
+ "use strict"; // jshint ;_;
1398
+
1399
+
1400
+ /* ALERT CLASS DEFINITION
1401
+ * ====================== */
1402
+
1403
+ var dismiss = '[data-dismiss="alert"]'
1404
+ , Alert = function (el) {
1405
+ $(el).on('click', dismiss, this.close)
1406
+ }
1407
+
1408
+ Alert.prototype.close = function (e) {
1409
+ var $this = $(this)
1410
+ , selector = $this.attr('data-target')
1411
+ , $parent
1412
+
1413
+ if (!selector) {
1414
+ selector = $this.attr('href')
1415
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
1416
+ }
1417
+
1418
+ $parent = $(selector)
1419
+
1420
+ e && e.preventDefault()
1421
+
1422
+ $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent())
1423
+
1424
+ $parent.trigger(e = $.Event('close'))
1425
+
1426
+ if (e.isDefaultPrevented()) return
1427
+
1428
+ $parent.removeClass('in')
1429
+
1430
+ function removeElement() {
1431
+ $parent
1432
+ .trigger('closed')
1433
+ .remove()
1434
+ }
1435
+
1436
+ $.support.transition && $parent.hasClass('fade') ?
1437
+ $parent.on($.support.transition.end, removeElement) :
1438
+ removeElement()
1439
+ }
1440
+
1441
+
1442
+ /* ALERT PLUGIN DEFINITION
1443
+ * ======================= */
1444
+
1445
+ var old = $.fn.alert
1446
+
1447
+ $.fn.alert = function (option) {
1448
+ return this.each(function () {
1449
+ var $this = $(this)
1450
+ , data = $this.data('alert')
1451
+ if (!data) $this.data('alert', (data = new Alert(this)))
1452
+ if (typeof option == 'string') data[option].call($this)
1453
+ })
1454
+ }
1455
+
1456
+ $.fn.alert.Constructor = Alert
1457
+
1458
+
1459
+ /* ALERT NO CONFLICT
1460
+ * ================= */
1461
+
1462
+ $.fn.alert.noConflict = function () {
1463
+ $.fn.alert = old
1464
+ return this
1465
+ }
1466
+
1467
+
1468
+ /* ALERT DATA-API
1469
+ * ============== */
1470
+
1471
+ $(document).on('click.alert.data-api', dismiss, Alert.prototype.close)
1472
+
1473
+ }(window.jQuery);
1474
+ /* ============================================================
1475
+ * bootstrap-button.js v2.3.1
1476
+ * http://twitter.github.com/bootstrap/javascript.html#buttons
1477
+ * ============================================================
1478
+ * Copyright 2012 Twitter, Inc.
1479
+ *
1480
+ * Licensed under the Apache License, Version 2.0 (the "License");
1481
+ * you may not use this file except in compliance with the License.
1482
+ * You may obtain a copy of the License at
1483
+ *
1484
+ * http://www.apache.org/licenses/LICENSE-2.0
1485
+ *
1486
+ * Unless required by applicable law or agreed to in writing, software
1487
+ * distributed under the License is distributed on an "AS IS" BASIS,
1488
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1489
+ * See the License for the specific language governing permissions and
1490
+ * limitations under the License.
1491
+ * ============================================================ */
1492
+
1493
+
1494
+ !function ($) {
1495
+
1496
+ "use strict"; // jshint ;_;
1497
+
1498
+
1499
+ /* BUTTON PUBLIC CLASS DEFINITION
1500
+ * ============================== */
1501
+
1502
+ var Button = function (element, options) {
1503
+ this.$element = $(element)
1504
+ this.options = $.extend({}, $.fn.button.defaults, options)
1505
+ }
1506
+
1507
+ Button.prototype.setState = function (state) {
1508
+ var d = 'disabled'
1509
+ , $el = this.$element
1510
+ , data = $el.data()
1511
+ , val = $el.is('input') ? 'val' : 'html'
1512
+
1513
+ state = state + 'Text'
1514
+ data.resetText || $el.data('resetText', $el[val]())
1515
+
1516
+ $el[val](data[state] || this.options[state])
1517
+
1518
+ // push to event loop to allow forms to submit
1519
+ setTimeout(function () {
1520
+ state == 'loadingText' ?
1521
+ $el.addClass(d).attr(d, d) :
1522
+ $el.removeClass(d).removeAttr(d)
1523
+ }, 0)
1524
+ }
1525
+
1526
+ Button.prototype.toggle = function () {
1527
+ var $parent = this.$element.closest('[data-toggle="buttons-radio"]')
1528
+
1529
+ $parent && $parent
1530
+ .find('.active')
1531
+ .removeClass('active')
1532
+
1533
+ this.$element.toggleClass('active')
1534
+ }
1535
+
1536
+
1537
+ /* BUTTON PLUGIN DEFINITION
1538
+ * ======================== */
1539
+
1540
+ var old = $.fn.button
1541
+
1542
+ $.fn.button = function (option) {
1543
+ return this.each(function () {
1544
+ var $this = $(this)
1545
+ , data = $this.data('button')
1546
+ , options = typeof option == 'object' && option
1547
+ if (!data) $this.data('button', (data = new Button(this, options)))
1548
+ if (option == 'toggle') data.toggle()
1549
+ else if (option) data.setState(option)
1550
+ })
1551
+ }
1552
+
1553
+ $.fn.button.defaults = {
1554
+ loadingText: 'loading...'
1555
+ }
1556
+
1557
+ $.fn.button.Constructor = Button
1558
+
1559
+
1560
+ /* BUTTON NO CONFLICT
1561
+ * ================== */
1562
+
1563
+ $.fn.button.noConflict = function () {
1564
+ $.fn.button = old
1565
+ return this
1566
+ }
1567
+
1568
+
1569
+ /* BUTTON DATA-API
1570
+ * =============== */
1571
+
1572
+ $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) {
1573
+ var $btn = $(e.target)
1574
+ if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
1575
+ $btn.button('toggle')
1576
+ })
1577
+
1578
+ }(window.jQuery);
1579
+ /* =============================================================
1580
+ * bootstrap-collapse.js v2.3.1
1581
+ * http://twitter.github.com/bootstrap/javascript.html#collapse
1582
+ * =============================================================
1583
+ * Copyright 2012 Twitter, Inc.
1584
+ *
1585
+ * Licensed under the Apache License, Version 2.0 (the "License");
1586
+ * you may not use this file except in compliance with the License.
1587
+ * You may obtain a copy of the License at
1588
+ *
1589
+ * http://www.apache.org/licenses/LICENSE-2.0
1590
+ *
1591
+ * Unless required by applicable law or agreed to in writing, software
1592
+ * distributed under the License is distributed on an "AS IS" BASIS,
1593
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1594
+ * See the License for the specific language governing permissions and
1595
+ * limitations under the License.
1596
+ * ============================================================ */
1597
+
1598
+
1599
+ !function ($) {
1600
+
1601
+ "use strict"; // jshint ;_;
1602
+
1603
+
1604
+ /* COLLAPSE PUBLIC CLASS DEFINITION
1605
+ * ================================ */
1606
+
1607
+ var Collapse = function (element, options) {
1608
+ this.$element = $(element)
1609
+ this.options = $.extend({}, $.fn.collapse.defaults, options)
1610
+
1611
+ if (this.options.parent) {
1612
+ this.$parent = $(this.options.parent)
1613
+ }
1614
+
1615
+ this.options.toggle && this.toggle()
1616
+ }
1617
+
1618
+ Collapse.prototype = {
1619
+
1620
+ constructor: Collapse
1621
+
1622
+ , dimension: function () {
1623
+ var hasWidth = this.$element.hasClass('width')
1624
+ return hasWidth ? 'width' : 'height'
1625
+ }
1626
+
1627
+ , show: function () {
1628
+ var dimension
1629
+ , scroll
1630
+ , actives
1631
+ , hasData
1632
+
1633
+ if (this.transitioning || this.$element.hasClass('in')) return
1634
+
1635
+ dimension = this.dimension()
1636
+ scroll = $.camelCase(['scroll', dimension].join('-'))
1637
+ actives = this.$parent && this.$parent.find('> .accordion-group > .in')
1638
+
1639
+ if (actives && actives.length) {
1640
+ hasData = actives.data('collapse')
1641
+ if (hasData && hasData.transitioning) return
1642
+ actives.collapse('hide')
1643
+ hasData || actives.data('collapse', null)
1644
+ }
1645
+
1646
+ this.$element[dimension](0)
1647
+ this.transition('addClass', $.Event('show'), 'shown')
1648
+ $.support.transition && this.$element[dimension](this.$element[0][scroll])
1649
+ }
1650
+
1651
+ , hide: function () {
1652
+ var dimension
1653
+ if (this.transitioning || !this.$element.hasClass('in')) return
1654
+ dimension = this.dimension()
1655
+ this.reset(this.$element[dimension]())
1656
+ this.transition('removeClass', $.Event('hide'), 'hidden')
1657
+ this.$element[dimension](0)
1658
+ }
1659
+
1660
+ , reset: function (size) {
1661
+ var dimension = this.dimension()
1662
+
1663
+ this.$element
1664
+ .removeClass('collapse')
1665
+ [dimension](size || 'auto')
1666
+ [0].offsetWidth
1667
+
1668
+ this.$element[size !== null ? 'addClass' : 'removeClass']('collapse')
1669
+
1670
+ return this
1671
+ }
1672
+
1673
+ , transition: function (method, startEvent, completeEvent) {
1674
+ var that = this
1675
+ , complete = function () {
1676
+ if (startEvent.type == 'show') that.reset()
1677
+ that.transitioning = 0
1678
+ that.$element.trigger(completeEvent)
1679
+ }
1680
+
1681
+ this.$element.trigger(startEvent)
1682
+
1683
+ if (startEvent.isDefaultPrevented()) return
1684
+
1685
+ this.transitioning = 1
1686
+
1687
+ this.$element[method]('in')
1688
+
1689
+ $.support.transition && this.$element.hasClass('collapse') ?
1690
+ this.$element.one($.support.transition.end, complete) :
1691
+ complete()
1692
+ }
1693
+
1694
+ , toggle: function () {
1695
+ this[this.$element.hasClass('in') ? 'hide' : 'show']()
1696
+ }
1697
+
1698
+ }
1699
+
1700
+
1701
+ /* COLLAPSE PLUGIN DEFINITION
1702
+ * ========================== */
1703
+
1704
+ var old = $.fn.collapse
1705
+
1706
+ $.fn.collapse = function (option) {
1707
+ return this.each(function () {
1708
+ var $this = $(this)
1709
+ , data = $this.data('collapse')
1710
+ , options = $.extend({}, $.fn.collapse.defaults, $this.data(), typeof option == 'object' && option)
1711
+ if (!data) $this.data('collapse', (data = new Collapse(this, options)))
1712
+ if (typeof option == 'string') data[option]()
1713
+ })
1714
+ }
1715
+
1716
+ $.fn.collapse.defaults = {
1717
+ toggle: true
1718
+ }
1719
+
1720
+ $.fn.collapse.Constructor = Collapse
1721
+
1722
+
1723
+ /* COLLAPSE NO CONFLICT
1724
+ * ==================== */
1725
+
1726
+ $.fn.collapse.noConflict = function () {
1727
+ $.fn.collapse = old
1728
+ return this
1729
+ }
1730
+
1731
+
1732
+ /* COLLAPSE DATA-API
1733
+ * ================= */
1734
+
1735
+ $(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) {
1736
+ var $this = $(this), href
1737
+ , target = $this.attr('data-target')
1738
+ || e.preventDefault()
1739
+ || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
1740
+ , option = $(target).data('collapse') ? 'toggle' : $this.data()
1741
+ $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
1742
+ $(target).collapse(option)
1743
+ })
1744
+
1745
+ }(window.jQuery);
1746
+ /* ==========================================================
1747
+ * bootstrap-carousel.js v2.3.1
1748
+ * http://twitter.github.com/bootstrap/javascript.html#carousel
1749
+ * ==========================================================
1750
+ * Copyright 2012 Twitter, Inc.
1751
+ *
1752
+ * Licensed under the Apache License, Version 2.0 (the "License");
1753
+ * you may not use this file except in compliance with the License.
1754
+ * You may obtain a copy of the License at
1755
+ *
1756
+ * http://www.apache.org/licenses/LICENSE-2.0
1757
+ *
1758
+ * Unless required by applicable law or agreed to in writing, software
1759
+ * distributed under the License is distributed on an "AS IS" BASIS,
1760
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1761
+ * See the License for the specific language governing permissions and
1762
+ * limitations under the License.
1763
+ * ========================================================== */
1764
+
1765
+
1766
+ !function ($) {
1767
+
1768
+ "use strict"; // jshint ;_;
1769
+
1770
+
1771
+ /* CAROUSEL CLASS DEFINITION
1772
+ * ========================= */
1773
+
1774
+ var Carousel = function (element, options) {
1775
+ this.$element = $(element)
1776
+ this.$indicators = this.$element.find('.carousel-indicators')
1777
+ this.options = options
1778
+ this.options.pause == 'hover' && this.$element
1779
+ .on('mouseenter', $.proxy(this.pause, this))
1780
+ .on('mouseleave', $.proxy(this.cycle, this))
1781
+ }
1782
+
1783
+ Carousel.prototype = {
1784
+
1785
+ cycle: function (e) {
1786
+ if (!e) this.paused = false
1787
+ if (this.interval) clearInterval(this.interval);
1788
+ this.options.interval
1789
+ && !this.paused
1790
+ && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
1791
+ return this
1792
+ }
1793
+
1794
+ , getActiveIndex: function () {
1795
+ this.$active = this.$element.find('.item.active')
1796
+ this.$items = this.$active.parent().children()
1797
+ return this.$items.index(this.$active)
1798
+ }
1799
+
1800
+ , to: function (pos) {
1801
+ var activeIndex = this.getActiveIndex()
1802
+ , that = this
1803
+
1804
+ if (pos > (this.$items.length - 1) || pos < 0) return
1805
+
1806
+ if (this.sliding) {
1807
+ return this.$element.one('slid', function () {
1808
+ that.to(pos)
1809
+ })
1810
+ }
1811
+
1812
+ if (activeIndex == pos) {
1813
+ return this.pause().cycle()
1814
+ }
1815
+
1816
+ return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))
1817
+ }
1818
+
1819
+ , pause: function (e) {
1820
+ if (!e) this.paused = true
1821
+ if (this.$element.find('.next, .prev').length && $.support.transition.end) {
1822
+ this.$element.trigger($.support.transition.end)
1823
+ this.cycle(true)
1824
+ }
1825
+ clearInterval(this.interval)
1826
+ this.interval = null
1827
+ return this
1828
+ }
1829
+
1830
+ , next: function () {
1831
+ if (this.sliding) return
1832
+ return this.slide('next')
1833
+ }
1834
+
1835
+ , prev: function () {
1836
+ if (this.sliding) return
1837
+ return this.slide('prev')
1838
+ }
1839
+
1840
+ , slide: function (type, next) {
1841
+ var $active = this.$element.find('.item.active')
1842
+ , $next = next || $active[type]()
1843
+ , isCycling = this.interval
1844
+ , direction = type == 'next' ? 'left' : 'right'
1845
+ , fallback = type == 'next' ? 'first' : 'last'
1846
+ , that = this
1847
+ , e
1848
+
1849
+ this.sliding = true
1850
+
1851
+ isCycling && this.pause()
1852
+
1853
+ $next = $next.length ? $next : this.$element.find('.item')[fallback]()
1854
+
1855
+ e = $.Event('slide', {
1856
+ relatedTarget: $next[0]
1857
+ , direction: direction
1858
+ })
1859
+
1860
+ if ($next.hasClass('active')) return
1861
+
1862
+ if (this.$indicators.length) {
1863
+ this.$indicators.find('.active').removeClass('active')
1864
+ this.$element.one('slid', function () {
1865
+ var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()])
1866
+ $nextIndicator && $nextIndicator.addClass('active')
1867
+ })
1868
+ }
1869
+
1870
+ if ($.support.transition && this.$element.hasClass('slide')) {
1871
+ this.$element.trigger(e)
1872
+ if (e.isDefaultPrevented()) return
1873
+ $next.addClass(type)
1874
+ $next[0].offsetWidth // force reflow
1875
+ $active.addClass(direction)
1876
+ $next.addClass(direction)
1877
+ this.$element.one($.support.transition.end, function () {
1878
+ $next.removeClass([type, direction].join(' ')).addClass('active')
1879
+ $active.removeClass(['active', direction].join(' '))
1880
+ that.sliding = false
1881
+ setTimeout(function () { that.$element.trigger('slid') }, 0)
1882
+ })
1883
+ } else {
1884
+ this.$element.trigger(e)
1885
+ if (e.isDefaultPrevented()) return
1886
+ $active.removeClass('active')
1887
+ $next.addClass('active')
1888
+ this.sliding = false
1889
+ this.$element.trigger('slid')
1890
+ }
1891
+
1892
+ isCycling && this.cycle()
1893
+
1894
+ return this
1895
+ }
1896
+
1897
+ }
1898
+
1899
+
1900
+ /* CAROUSEL PLUGIN DEFINITION
1901
+ * ========================== */
1902
+
1903
+ var old = $.fn.carousel
1904
+
1905
+ $.fn.carousel = function (option) {
1906
+ return this.each(function () {
1907
+ var $this = $(this)
1908
+ , data = $this.data('carousel')
1909
+ , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option)
1910
+ , action = typeof option == 'string' ? option : options.slide
1911
+ if (!data) $this.data('carousel', (data = new Carousel(this, options)))
1912
+ if (typeof option == 'number') data.to(option)
1913
+ else if (action) data[action]()
1914
+ else if (options.interval) data.pause().cycle()
1915
+ })
1916
+ }
1917
+
1918
+ $.fn.carousel.defaults = {
1919
+ interval: 5000
1920
+ , pause: 'hover'
1921
+ }
1922
+
1923
+ $.fn.carousel.Constructor = Carousel
1924
+
1925
+
1926
+ /* CAROUSEL NO CONFLICT
1927
+ * ==================== */
1928
+
1929
+ $.fn.carousel.noConflict = function () {
1930
+ $.fn.carousel = old
1931
+ return this
1932
+ }
1933
+
1934
+ /* CAROUSEL DATA-API
1935
+ * ================= */
1936
+
1937
+ $(document).on('click.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {
1938
+ var $this = $(this), href
1939
+ , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
1940
+ , options = $.extend({}, $target.data(), $this.data())
1941
+ , slideIndex
1942
+
1943
+ $target.carousel(options)
1944
+
1945
+ if (slideIndex = $this.attr('data-slide-to')) {
1946
+ $target.data('carousel').pause().to(slideIndex).cycle()
1947
+ }
1948
+
1949
+ e.preventDefault()
1950
+ })
1951
+
1952
+ }(window.jQuery);
1953
+ /* =============================================================
1954
+ * bootstrap-typeahead.js v2.3.1
1955
+ * http://twitter.github.com/bootstrap/javascript.html#typeahead
1956
+ * =============================================================
1957
+ * Copyright 2012 Twitter, Inc.
1958
+ *
1959
+ * Licensed under the Apache License, Version 2.0 (the "License");
1960
+ * you may not use this file except in compliance with the License.
1961
+ * You may obtain a copy of the License at
1962
+ *
1963
+ * http://www.apache.org/licenses/LICENSE-2.0
1964
+ *
1965
+ * Unless required by applicable law or agreed to in writing, software
1966
+ * distributed under the License is distributed on an "AS IS" BASIS,
1967
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1968
+ * See the License for the specific language governing permissions and
1969
+ * limitations under the License.
1970
+ * ============================================================ */
1971
+
1972
+
1973
+ !function($){
1974
+
1975
+ "use strict"; // jshint ;_;
1976
+
1977
+
1978
+ /* TYPEAHEAD PUBLIC CLASS DEFINITION
1979
+ * ================================= */
1980
+
1981
+ var Typeahead = function (element, options) {
1982
+ this.$element = $(element)
1983
+ this.options = $.extend({}, $.fn.typeahead.defaults, options)
1984
+ this.matcher = this.options.matcher || this.matcher
1985
+ this.sorter = this.options.sorter || this.sorter
1986
+ this.highlighter = this.options.highlighter || this.highlighter
1987
+ this.updater = this.options.updater || this.updater
1988
+ this.source = this.options.source
1989
+ this.$menu = $(this.options.menu)
1990
+ this.shown = false
1991
+ this.listen()
1992
+ }
1993
+
1994
+ Typeahead.prototype = {
1995
+
1996
+ constructor: Typeahead
1997
+
1998
+ , select: function () {
1999
+ var val = this.$menu.find('.active').attr('data-value')
2000
+ this.$element
2001
+ .val(this.updater(val))
2002
+ .change()
2003
+ return this.hide()
2004
+ }
2005
+
2006
+ , updater: function (item) {
2007
+ return item
2008
+ }
2009
+
2010
+ , show: function () {
2011
+ var pos = $.extend({}, this.$element.position(), {
2012
+ height: this.$element[0].offsetHeight
2013
+ })
2014
+
2015
+ this.$menu
2016
+ .insertAfter(this.$element)
2017
+ .css({
2018
+ top: pos.top + pos.height
2019
+ , left: pos.left
2020
+ })
2021
+ .show()
2022
+
2023
+ this.shown = true
2024
+ return this
2025
+ }
2026
+
2027
+ , hide: function () {
2028
+ this.$menu.hide()
2029
+ this.shown = false
2030
+ return this
2031
+ }
2032
+
2033
+ , lookup: function (event) {
2034
+ var items
2035
+
2036
+ this.query = this.$element.val()
2037
+
2038
+ if (!this.query || this.query.length < this.options.minLength) {
2039
+ return this.shown ? this.hide() : this
2040
+ }
2041
+
2042
+ items = $.isFunction(this.source) ? this.source(this.query, $.proxy(this.process, this)) : this.source
2043
+
2044
+ return items ? this.process(items) : this
2045
+ }
2046
+
2047
+ , process: function (items) {
2048
+ var that = this
2049
+
2050
+ items = $.grep(items, function (item) {
2051
+ return that.matcher(item)
2052
+ })
2053
+
2054
+ items = this.sorter(items)
2055
+
2056
+ if (!items.length) {
2057
+ return this.shown ? this.hide() : this
2058
+ }
2059
+
2060
+ return this.render(items.slice(0, this.options.items)).show()
2061
+ }
2062
+
2063
+ , matcher: function (item) {
2064
+ return ~item.toLowerCase().indexOf(this.query.toLowerCase())
2065
+ }
2066
+
2067
+ , sorter: function (items) {
2068
+ var beginswith = []
2069
+ , caseSensitive = []
2070
+ , caseInsensitive = []
2071
+ , item
2072
+
2073
+ while (item = items.shift()) {
2074
+ if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item)
2075
+ else if (~item.indexOf(this.query)) caseSensitive.push(item)
2076
+ else caseInsensitive.push(item)
2077
+ }
2078
+
2079
+ return beginswith.concat(caseSensitive, caseInsensitive)
2080
+ }
2081
+
2082
+ , highlighter: function (item) {
2083
+ var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
2084
+ return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
2085
+ return '<strong>' + match + '</strong>'
2086
+ })
2087
+ }
2088
+
2089
+ , render: function (items) {
2090
+ var that = this
2091
+
2092
+ items = $(items).map(function (i, item) {
2093
+ i = $(that.options.item).attr('data-value', item)
2094
+ i.find('a').html(that.highlighter(item))
2095
+ return i[0]
2096
+ })
2097
+
2098
+ items.first().addClass('active')
2099
+ this.$menu.html(items)
2100
+ return this
2101
+ }
2102
+
2103
+ , next: function (event) {
2104
+ var active = this.$menu.find('.active').removeClass('active')
2105
+ , next = active.next()
2106
+
2107
+ if (!next.length) {
2108
+ next = $(this.$menu.find('li')[0])
2109
+ }
2110
+
2111
+ next.addClass('active')
2112
+ }
2113
+
2114
+ , prev: function (event) {
2115
+ var active = this.$menu.find('.active').removeClass('active')
2116
+ , prev = active.prev()
2117
+
2118
+ if (!prev.length) {
2119
+ prev = this.$menu.find('li').last()
2120
+ }
2121
+
2122
+ prev.addClass('active')
2123
+ }
2124
+
2125
+ , listen: function () {
2126
+ this.$element
2127
+ .on('focus', $.proxy(this.focus, this))
2128
+ .on('blur', $.proxy(this.blur, this))
2129
+ .on('keypress', $.proxy(this.keypress, this))
2130
+ .on('keyup', $.proxy(this.keyup, this))
2131
+
2132
+ if (this.eventSupported('keydown')) {
2133
+ this.$element.on('keydown', $.proxy(this.keydown, this))
2134
+ }
2135
+
2136
+ this.$menu
2137
+ .on('click', $.proxy(this.click, this))
2138
+ .on('mouseenter', 'li', $.proxy(this.mouseenter, this))
2139
+ .on('mouseleave', 'li', $.proxy(this.mouseleave, this))
2140
+ }
2141
+
2142
+ , eventSupported: function(eventName) {
2143
+ var isSupported = eventName in this.$element
2144
+ if (!isSupported) {
2145
+ this.$element.setAttribute(eventName, 'return;')
2146
+ isSupported = typeof this.$element[eventName] === 'function'
2147
+ }
2148
+ return isSupported
2149
+ }
2150
+
2151
+ , move: function (e) {
2152
+ if (!this.shown) return
2153
+
2154
+ switch(e.keyCode) {
2155
+ case 9: // tab
2156
+ case 13: // enter
2157
+ case 27: // escape
2158
+ e.preventDefault()
2159
+ break
2160
+
2161
+ case 38: // up arrow
2162
+ e.preventDefault()
2163
+ this.prev()
2164
+ break
2165
+
2166
+ case 40: // down arrow
2167
+ e.preventDefault()
2168
+ this.next()
2169
+ break
2170
+ }
2171
+
2172
+ e.stopPropagation()
2173
+ }
2174
+
2175
+ , keydown: function (e) {
2176
+ this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40,38,9,13,27])
2177
+ this.move(e)
2178
+ }
2179
+
2180
+ , keypress: function (e) {
2181
+ if (this.suppressKeyPressRepeat) return
2182
+ this.move(e)
2183
+ }
2184
+
2185
+ , keyup: function (e) {
2186
+ switch(e.keyCode) {
2187
+ case 40: // down arrow
2188
+ case 38: // up arrow
2189
+ case 16: // shift
2190
+ case 17: // ctrl
2191
+ case 18: // alt
2192
+ break
2193
+
2194
+ case 9: // tab
2195
+ case 13: // enter
2196
+ if (!this.shown) return
2197
+ this.select()
2198
+ break
2199
+
2200
+ case 27: // escape
2201
+ if (!this.shown) return
2202
+ this.hide()
2203
+ break
2204
+
2205
+ default:
2206
+ this.lookup()
2207
+ }
2208
+
2209
+ e.stopPropagation()
2210
+ e.preventDefault()
2211
+ }
2212
+
2213
+ , focus: function (e) {
2214
+ this.focused = true
2215
+ }
2216
+
2217
+ , blur: function (e) {
2218
+ this.focused = false
2219
+ if (!this.mousedover && this.shown) this.hide()
2220
+ }
2221
+
2222
+ , click: function (e) {
2223
+ e.stopPropagation()
2224
+ e.preventDefault()
2225
+ this.select()
2226
+ this.$element.focus()
2227
+ }
2228
+
2229
+ , mouseenter: function (e) {
2230
+ this.mousedover = true
2231
+ this.$menu.find('.active').removeClass('active')
2232
+ $(e.currentTarget).addClass('active')
2233
+ }
2234
+
2235
+ , mouseleave: function (e) {
2236
+ this.mousedover = false
2237
+ if (!this.focused && this.shown) this.hide()
2238
+ }
2239
+
2240
+ }
2241
+
2242
+
2243
+ /* TYPEAHEAD PLUGIN DEFINITION
2244
+ * =========================== */
2245
+
2246
+ var old = $.fn.typeahead
2247
+
2248
+ $.fn.typeahead = function (option) {
2249
+ return this.each(function () {
2250
+ var $this = $(this)
2251
+ , data = $this.data('typeahead')
2252
+ , options = typeof option == 'object' && option
2253
+ if (!data) $this.data('typeahead', (data = new Typeahead(this, options)))
2254
+ if (typeof option == 'string') data[option]()
2255
+ })
2256
+ }
2257
+
2258
+ $.fn.typeahead.defaults = {
2259
+ source: []
2260
+ , items: 8
2261
+ , menu: '<ul class="typeahead dropdown-menu"></ul>'
2262
+ , item: '<li><a href="#"></a></li>'
2263
+ , minLength: 1
2264
+ }
2265
+
2266
+ $.fn.typeahead.Constructor = Typeahead
2267
+
2268
+
2269
+ /* TYPEAHEAD NO CONFLICT
2270
+ * =================== */
2271
+
2272
+ $.fn.typeahead.noConflict = function () {
2273
+ $.fn.typeahead = old
2274
+ return this
2275
+ }
2276
+
2277
+
2278
+ /* TYPEAHEAD DATA-API
2279
+ * ================== */
2280
+
2281
+ $(document).on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) {
2282
+ var $this = $(this)
2283
+ if ($this.data('typeahead')) return
2284
+ $this.typeahead($this.data())
2285
+ })
2286
+
2287
+ }(window.jQuery);