jabe 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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);