jabe 0.7.0 → 0.8.0

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