bladerunner 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. checksums.yaml +15 -0
  2. data/LICENSE +20 -0
  3. data/README.md +56 -0
  4. data/Rakefile +38 -0
  5. data/app/assets/javascripts/bladerunner/application.js +6 -0
  6. data/app/assets/javascripts/bladerunner/bladerunner.coffee +31 -0
  7. data/app/assets/javascripts/bladerunner/vendor/bootstrap.js +1999 -0
  8. data/app/assets/javascripts/bladerunner/vendor/jquery.js +8829 -0
  9. data/app/assets/javascripts/bladerunner/vendor/prettify-lang-sql.js +2 -0
  10. data/app/assets/javascripts/bladerunner/vendor/prettify.js +30 -0
  11. data/app/assets/javascripts/bladerunner/vendor/pubnub.js +1436 -0
  12. data/app/assets/stylesheets/bladerunner/application.css +7 -0
  13. data/app/assets/stylesheets/bladerunner/bladerunner.css.scss +17 -0
  14. data/app/assets/stylesheets/bladerunner/bootstrap-theme.css +384 -0
  15. data/app/assets/stylesheets/bladerunner/bootstrap.css +6805 -0
  16. data/app/assets/stylesheets/bladerunner/prettify-desert.css +34 -0
  17. data/app/assets/stylesheets/bladerunner/prettify.css +1 -0
  18. data/app/controllers/bladerunner/application_controller.rb +50 -0
  19. data/app/helpers/bladerunner/application_helper.rb +4 -0
  20. data/app/views/bladerunner/application/_query_info.html.erb +8 -0
  21. data/app/views/bladerunner/application/index.html.erb +14 -0
  22. data/app/views/bladerunner/application/run.html.erb +41 -0
  23. data/app/views/layouts/bladerunner/application.html.erb +34 -0
  24. data/config/routes.rb +5 -0
  25. data/lib/bladerunner.rb +4 -0
  26. data/lib/bladerunner/engine.rb +5 -0
  27. data/lib/bladerunner/version.rb +3 -0
  28. data/lib/tasks/bladerunner_tasks.rake +4 -0
  29. data/test/bladerunner_test.rb +7 -0
  30. data/test/dummy/README.rdoc +261 -0
  31. data/test/dummy/Rakefile +7 -0
  32. data/test/dummy/app/assets/javascripts/application.js +15 -0
  33. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  34. data/test/dummy/app/controllers/application_controller.rb +3 -0
  35. data/test/dummy/app/helpers/application_helper.rb +2 -0
  36. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  37. data/test/dummy/config.ru +4 -0
  38. data/test/dummy/config/application.rb +65 -0
  39. data/test/dummy/config/boot.rb +10 -0
  40. data/test/dummy/config/environment.rb +5 -0
  41. data/test/dummy/config/environments/development.rb +31 -0
  42. data/test/dummy/config/environments/production.rb +64 -0
  43. data/test/dummy/config/environments/test.rb +35 -0
  44. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  45. data/test/dummy/config/initializers/inflections.rb +15 -0
  46. data/test/dummy/config/initializers/mime_types.rb +5 -0
  47. data/test/dummy/config/initializers/secret_token.rb +7 -0
  48. data/test/dummy/config/initializers/session_store.rb +8 -0
  49. data/test/dummy/config/initializers/wrap_parameters.rb +10 -0
  50. data/test/dummy/config/locales/en.yml +5 -0
  51. data/test/dummy/config/routes.rb +4 -0
  52. data/test/dummy/log/development.log +202 -0
  53. data/test/dummy/public/404.html +26 -0
  54. data/test/dummy/public/422.html +26 -0
  55. data/test/dummy/public/500.html +25 -0
  56. data/test/dummy/public/favicon.ico +0 -0
  57. data/test/dummy/script/rails +6 -0
  58. data/test/integration/navigation_test.rb +9 -0
  59. data/test/test_helper.rb +15 -0
  60. metadata +162 -0
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ N2ZhMTFlNzYyMTJhNWRjYTAwYmM2ZDdlZWVjNDMyYzFiOGZlNDg4Ng==
5
+ data.tar.gz: !binary |-
6
+ YzU5ZDJkMjZkM2ZmNzU0ZGJjMzgxNGYzYTE4MGVhOGYzNDY5ZjQ5Zg==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ MjkyNjU4NGEzODVjN2QyNGFmMTI2NGI2MDUwMmFiODIxOGI1NzA1MjA1NDMx
10
+ YTc0YzcxMTkxNjI3YTdmNzRhZWEwZDMxZGE1NDliZTg1ODA3MTYxZjdmNGZk
11
+ ZWY5M2FmZWZhNjQxY2Y3YzZlOTYyMzQ3N2RlZjMzMzMzMDAyNmM=
12
+ data.tar.gz: !binary |-
13
+ OTNmY2JhMjdjNzlkMmEzZWNiNTc4NDE5ZDY2NTcwZmUwYWMwM2YzMTk5MTMw
14
+ NjhkZGQ4ZGQwY2E1M2RlZTI4ZDM0YzI3Zjc5ZjdjNzllMjE3YzQxMDQwODdm
15
+ ZTM3Yjg4OGY2OGQyN2MyOTY2ZDQ1MTQzMzdjYTRiNjE0MjZkMzk=
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2013 Vincent Roy
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # Bladerunner
2
+
3
+ Edit SQL files in your Rails project with your favourite editor; View results in your browser in realtime as your files are saved.
4
+
5
+ I've never found an SQL editor/runner that I liked for PostgreSQL, so why not profit from Rails and an active connection to your database to solve this problem? Write SQL files in `bladerunner/*.sql` and open your browser to the mounted path to see your queries and run them.
6
+
7
+ Quick little screencast demo of the functionality: http://www.youtube.com/watch?v=r1858nYdQQk
8
+
9
+ **WARNING:** Bladerunner does NOT prevent anything nasty from happening, operate at your own risk.
10
+
11
+ ## Installation & Getting Started
12
+
13
+ Add bladerunner to your Gemfile:
14
+
15
+ ```ruby
16
+ gem "bladerunner"
17
+ ```
18
+
19
+ Add this to your `config/routes.rb` file to mount Bladerunner in your Rails app in development:
20
+
21
+ ```ruby
22
+ if Rails.env.development?
23
+ mount Bladerunner::Engine => "/bladerunner"
24
+ end
25
+ ```
26
+
27
+ Create your first query:
28
+
29
+ ```sh
30
+ mkdir bladerunner/
31
+ echo "select * from schema_migrations" >> bladerunner/schema-migrations.sql
32
+ open http://localhost:3000/bladerunner/run?filename=schema-migrations.sql
33
+ ```
34
+
35
+ Don't forget to add `bladerunner/` to your `.gitignore` file if you don't want to share these queries.
36
+
37
+ ```sh
38
+ echo "bladerunner/" >> .gitignore
39
+ ```
40
+
41
+ ## Notes
42
+
43
+ Tested on:
44
+
45
+ * Ruby 2.0.0p247 (MRI)
46
+ * Rails 3.2.13
47
+
48
+
49
+ ## Feature ideas
50
+
51
+ * Refactor & move logic out of controller.
52
+ * Improved realtime support (vs. the current polling).
53
+ * Ability to run ruby code the same way.
54
+ * Some tests.
55
+ * Scrolling table support for results (sticky header).
56
+ * Log every query ran in `log/bladerunner.log` for future reference.
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'Bladerunner'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+
24
+
25
+
26
+ Bundler::GemHelper.install_tasks
27
+
28
+ require 'rake/testtask'
29
+
30
+ Rake::TestTask.new(:test) do |t|
31
+ t.libs << 'lib'
32
+ t.libs << 'test'
33
+ t.pattern = 'test/**/*_test.rb'
34
+ t.verbose = false
35
+ end
36
+
37
+
38
+ task :default => :test
@@ -0,0 +1,6 @@
1
+ //= require ./vendor/jquery
2
+ //= require ./vendor/bootstrap
3
+ //= require ./vendor/prettify
4
+ //= require ./vendor/prettify-lang-sql
5
+ //= require ./vendor/pubnub
6
+ //= require_tree .
@@ -0,0 +1,31 @@
1
+ $ ->
2
+ $("[rel=popover]").popover(trigger: "hover", placement: "bottom")
3
+
4
+ $("[data-action=open-results-modal]").on "click", (e) ->
5
+ target = $(e.currentTarget)
6
+ alert("@todo modal of this row.")
7
+
8
+ prettyPrint()
9
+
10
+ window.refreshContent = ->
11
+ $.get window.location.href, (data) ->
12
+ $("#container").html(data)
13
+ prettyPrint()
14
+
15
+ testToReload = ->
16
+ filename = $("[data-run-filename]").attr("data-run-filename")
17
+ timestamp = $("[data-run-timestamp]").attr("data-run-timestamp")
18
+
19
+ return unless filename? and timestamp?
20
+
21
+ $.ajax
22
+ type: "GET"
23
+ dataType: "json"
24
+ url: "/bladerunner/test"
25
+ data: { filename: filename }
26
+ success: (data) ->
27
+ if ( parseInt(data.timestamp) != parseInt(timestamp) )
28
+ refreshContent()
29
+
30
+ testToReload()
31
+ setInterval( testToReload, 2000)
@@ -0,0 +1,1999 @@
1
+ /**
2
+ * bootstrap.js v3.0.0 by @fat and @mdo
3
+ * Copyright 2013 Twitter Inc.
4
+ * http://www.apache.org/licenses/LICENSE-2.0
5
+ */
6
+ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
7
+
8
+ /* ========================================================================
9
+ * Bootstrap: transition.js v3.0.0
10
+ * http://twbs.github.com/bootstrap/javascript.html#transitions
11
+ * ========================================================================
12
+ * Copyright 2013 Twitter, Inc.
13
+ *
14
+ * Licensed under the Apache License, Version 2.0 (the "License");
15
+ * you may not use this file except in compliance with the License.
16
+ * You may obtain a copy of the License at
17
+ *
18
+ * http://www.apache.org/licenses/LICENSE-2.0
19
+ *
20
+ * Unless required by applicable law or agreed to in writing, software
21
+ * distributed under the License is distributed on an "AS IS" BASIS,
22
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23
+ * See the License for the specific language governing permissions and
24
+ * limitations under the License.
25
+ * ======================================================================== */
26
+
27
+
28
+ +function ($) { "use strict";
29
+
30
+ // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
31
+ // ============================================================
32
+
33
+ function transitionEnd() {
34
+ var el = document.createElement('bootstrap')
35
+
36
+ var transEndEventNames = {
37
+ 'WebkitTransition' : 'webkitTransitionEnd'
38
+ , 'MozTransition' : 'transitionend'
39
+ , 'OTransition' : 'oTransitionEnd otransitionend'
40
+ , 'transition' : 'transitionend'
41
+ }
42
+
43
+ for (var name in transEndEventNames) {
44
+ if (el.style[name] !== undefined) {
45
+ return { end: transEndEventNames[name] }
46
+ }
47
+ }
48
+ }
49
+
50
+ // http://blog.alexmaccaw.com/css-transitions
51
+ $.fn.emulateTransitionEnd = function (duration) {
52
+ var called = false, $el = this
53
+ $(this).one($.support.transition.end, function () { called = true })
54
+ var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
55
+ setTimeout(callback, duration)
56
+ return this
57
+ }
58
+
59
+ $(function () {
60
+ $.support.transition = transitionEnd()
61
+ })
62
+
63
+ }(window.jQuery);
64
+
65
+ /* ========================================================================
66
+ * Bootstrap: alert.js v3.0.0
67
+ * http://twbs.github.com/bootstrap/javascript.html#alerts
68
+ * ========================================================================
69
+ * Copyright 2013 Twitter, Inc.
70
+ *
71
+ * Licensed under the Apache License, Version 2.0 (the "License");
72
+ * you may not use this file except in compliance with the License.
73
+ * You may obtain a copy of the License at
74
+ *
75
+ * http://www.apache.org/licenses/LICENSE-2.0
76
+ *
77
+ * Unless required by applicable law or agreed to in writing, software
78
+ * distributed under the License is distributed on an "AS IS" BASIS,
79
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
80
+ * See the License for the specific language governing permissions and
81
+ * limitations under the License.
82
+ * ======================================================================== */
83
+
84
+
85
+ +function ($) { "use strict";
86
+
87
+ // ALERT CLASS DEFINITION
88
+ // ======================
89
+
90
+ var dismiss = '[data-dismiss="alert"]'
91
+ var Alert = function (el) {
92
+ $(el).on('click', dismiss, this.close)
93
+ }
94
+
95
+ Alert.prototype.close = function (e) {
96
+ var $this = $(this)
97
+ var selector = $this.attr('data-target')
98
+
99
+ if (!selector) {
100
+ selector = $this.attr('href')
101
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
102
+ }
103
+
104
+ var $parent = $(selector)
105
+
106
+ if (e) e.preventDefault()
107
+
108
+ if (!$parent.length) {
109
+ $parent = $this.hasClass('alert') ? $this : $this.parent()
110
+ }
111
+
112
+ $parent.trigger(e = $.Event('close.bs.alert'))
113
+
114
+ if (e.isDefaultPrevented()) return
115
+
116
+ $parent.removeClass('in')
117
+
118
+ function removeElement() {
119
+ $parent.trigger('closed.bs.alert').remove()
120
+ }
121
+
122
+ $.support.transition && $parent.hasClass('fade') ?
123
+ $parent
124
+ .one($.support.transition.end, removeElement)
125
+ .emulateTransitionEnd(150) :
126
+ removeElement()
127
+ }
128
+
129
+
130
+ // ALERT PLUGIN DEFINITION
131
+ // =======================
132
+
133
+ var old = $.fn.alert
134
+
135
+ $.fn.alert = function (option) {
136
+ return this.each(function () {
137
+ var $this = $(this)
138
+ var data = $this.data('bs.alert')
139
+
140
+ if (!data) $this.data('bs.alert', (data = new Alert(this)))
141
+ if (typeof option == 'string') data[option].call($this)
142
+ })
143
+ }
144
+
145
+ $.fn.alert.Constructor = Alert
146
+
147
+
148
+ // ALERT NO CONFLICT
149
+ // =================
150
+
151
+ $.fn.alert.noConflict = function () {
152
+ $.fn.alert = old
153
+ return this
154
+ }
155
+
156
+
157
+ // ALERT DATA-API
158
+ // ==============
159
+
160
+ $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
161
+
162
+ }(window.jQuery);
163
+
164
+ /* ========================================================================
165
+ * Bootstrap: button.js v3.0.0
166
+ * http://twbs.github.com/bootstrap/javascript.html#buttons
167
+ * ========================================================================
168
+ * Copyright 2013 Twitter, Inc.
169
+ *
170
+ * Licensed under the Apache License, Version 2.0 (the "License");
171
+ * you may not use this file except in compliance with the License.
172
+ * You may obtain a copy of the License at
173
+ *
174
+ * http://www.apache.org/licenses/LICENSE-2.0
175
+ *
176
+ * Unless required by applicable law or agreed to in writing, software
177
+ * distributed under the License is distributed on an "AS IS" BASIS,
178
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
179
+ * See the License for the specific language governing permissions and
180
+ * limitations under the License.
181
+ * ======================================================================== */
182
+
183
+
184
+ +function ($) { "use strict";
185
+
186
+ // BUTTON PUBLIC CLASS DEFINITION
187
+ // ==============================
188
+
189
+ var Button = function (element, options) {
190
+ this.$element = $(element)
191
+ this.options = $.extend({}, Button.DEFAULTS, options)
192
+ }
193
+
194
+ Button.DEFAULTS = {
195
+ loadingText: 'loading...'
196
+ }
197
+
198
+ Button.prototype.setState = function (state) {
199
+ var d = 'disabled'
200
+ var $el = this.$element
201
+ var val = $el.is('input') ? 'val' : 'html'
202
+ var data = $el.data()
203
+
204
+ state = state + 'Text'
205
+
206
+ if (!data.resetText) $el.data('resetText', $el[val]())
207
+
208
+ $el[val](data[state] || this.options[state])
209
+
210
+ // push to event loop to allow forms to submit
211
+ setTimeout(function () {
212
+ state == 'loadingText' ?
213
+ $el.addClass(d).attr(d, d) :
214
+ $el.removeClass(d).removeAttr(d);
215
+ }, 0)
216
+ }
217
+
218
+ Button.prototype.toggle = function () {
219
+ var $parent = this.$element.closest('[data-toggle="buttons"]')
220
+
221
+ if ($parent.length) {
222
+ var $input = this.$element.find('input')
223
+ .prop('checked', !this.$element.hasClass('active'))
224
+ .trigger('change')
225
+ if ($input.prop('type') === 'radio') $parent.find('.active').removeClass('active')
226
+ }
227
+
228
+ this.$element.toggleClass('active')
229
+ }
230
+
231
+
232
+ // BUTTON PLUGIN DEFINITION
233
+ // ========================
234
+
235
+ var old = $.fn.button
236
+
237
+ $.fn.button = function (option) {
238
+ return this.each(function () {
239
+ var $this = $(this)
240
+ var data = $this.data('bs.button')
241
+ var options = typeof option == 'object' && option
242
+
243
+ if (!data) $this.data('bs.button', (data = new Button(this, options)))
244
+
245
+ if (option == 'toggle') data.toggle()
246
+ else if (option) data.setState(option)
247
+ })
248
+ }
249
+
250
+ $.fn.button.Constructor = Button
251
+
252
+
253
+ // BUTTON NO CONFLICT
254
+ // ==================
255
+
256
+ $.fn.button.noConflict = function () {
257
+ $.fn.button = old
258
+ return this
259
+ }
260
+
261
+
262
+ // BUTTON DATA-API
263
+ // ===============
264
+
265
+ $(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) {
266
+ var $btn = $(e.target)
267
+ if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
268
+ $btn.button('toggle')
269
+ e.preventDefault()
270
+ })
271
+
272
+ }(window.jQuery);
273
+
274
+ /* ========================================================================
275
+ * Bootstrap: carousel.js v3.0.0
276
+ * http://twbs.github.com/bootstrap/javascript.html#carousel
277
+ * ========================================================================
278
+ * Copyright 2012 Twitter, Inc.
279
+ *
280
+ * Licensed under the Apache License, Version 2.0 (the "License");
281
+ * you may not use this file except in compliance with the License.
282
+ * You may obtain a copy of the License at
283
+ *
284
+ * http://www.apache.org/licenses/LICENSE-2.0
285
+ *
286
+ * Unless required by applicable law or agreed to in writing, software
287
+ * distributed under the License is distributed on an "AS IS" BASIS,
288
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
289
+ * See the License for the specific language governing permissions and
290
+ * limitations under the License.
291
+ * ======================================================================== */
292
+
293
+
294
+ +function ($) { "use strict";
295
+
296
+ // CAROUSEL CLASS DEFINITION
297
+ // =========================
298
+
299
+ var Carousel = function (element, options) {
300
+ this.$element = $(element)
301
+ this.$indicators = this.$element.find('.carousel-indicators')
302
+ this.options = options
303
+ this.paused =
304
+ this.sliding =
305
+ this.interval =
306
+ this.$active =
307
+ this.$items = null
308
+
309
+ this.options.pause == 'hover' && this.$element
310
+ .on('mouseenter', $.proxy(this.pause, this))
311
+ .on('mouseleave', $.proxy(this.cycle, this))
312
+ }
313
+
314
+ Carousel.DEFAULTS = {
315
+ interval: 5000
316
+ , pause: 'hover'
317
+ , wrap: true
318
+ }
319
+
320
+ Carousel.prototype.cycle = function (e) {
321
+ e || (this.paused = false)
322
+
323
+ this.interval && clearInterval(this.interval)
324
+
325
+ this.options.interval
326
+ && !this.paused
327
+ && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
328
+
329
+ return this
330
+ }
331
+
332
+ Carousel.prototype.getActiveIndex = function () {
333
+ this.$active = this.$element.find('.item.active')
334
+ this.$items = this.$active.parent().children()
335
+
336
+ return this.$items.index(this.$active)
337
+ }
338
+
339
+ Carousel.prototype.to = function (pos) {
340
+ var that = this
341
+ var activeIndex = this.getActiveIndex()
342
+
343
+ if (pos > (this.$items.length - 1) || pos < 0) return
344
+
345
+ if (this.sliding) return this.$element.one('slid', function () { that.to(pos) })
346
+ if (activeIndex == pos) return this.pause().cycle()
347
+
348
+ return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))
349
+ }
350
+
351
+ Carousel.prototype.pause = function (e) {
352
+ e || (this.paused = true)
353
+
354
+ if (this.$element.find('.next, .prev').length && $.support.transition.end) {
355
+ this.$element.trigger($.support.transition.end)
356
+ this.cycle(true)
357
+ }
358
+
359
+ this.interval = clearInterval(this.interval)
360
+
361
+ return this
362
+ }
363
+
364
+ Carousel.prototype.next = function () {
365
+ if (this.sliding) return
366
+ return this.slide('next')
367
+ }
368
+
369
+ Carousel.prototype.prev = function () {
370
+ if (this.sliding) return
371
+ return this.slide('prev')
372
+ }
373
+
374
+ Carousel.prototype.slide = function (type, next) {
375
+ var $active = this.$element.find('.item.active')
376
+ var $next = next || $active[type]()
377
+ var isCycling = this.interval
378
+ var direction = type == 'next' ? 'left' : 'right'
379
+ var fallback = type == 'next' ? 'first' : 'last'
380
+ var that = this
381
+
382
+ if (!$next.length) {
383
+ if (!this.options.wrap) return
384
+ $next = this.$element.find('.item')[fallback]()
385
+ }
386
+
387
+ this.sliding = true
388
+
389
+ isCycling && this.pause()
390
+
391
+ var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction })
392
+
393
+ if ($next.hasClass('active')) return
394
+
395
+ if (this.$indicators.length) {
396
+ this.$indicators.find('.active').removeClass('active')
397
+ this.$element.one('slid', function () {
398
+ var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()])
399
+ $nextIndicator && $nextIndicator.addClass('active')
400
+ })
401
+ }
402
+
403
+ if ($.support.transition && this.$element.hasClass('slide')) {
404
+ this.$element.trigger(e)
405
+ if (e.isDefaultPrevented()) return
406
+ $next.addClass(type)
407
+ $next[0].offsetWidth // force reflow
408
+ $active.addClass(direction)
409
+ $next.addClass(direction)
410
+ $active
411
+ .one($.support.transition.end, function () {
412
+ $next.removeClass([type, direction].join(' ')).addClass('active')
413
+ $active.removeClass(['active', direction].join(' '))
414
+ that.sliding = false
415
+ setTimeout(function () { that.$element.trigger('slid') }, 0)
416
+ })
417
+ .emulateTransitionEnd(600)
418
+ } else {
419
+ this.$element.trigger(e)
420
+ if (e.isDefaultPrevented()) return
421
+ $active.removeClass('active')
422
+ $next.addClass('active')
423
+ this.sliding = false
424
+ this.$element.trigger('slid')
425
+ }
426
+
427
+ isCycling && this.cycle()
428
+
429
+ return this
430
+ }
431
+
432
+
433
+ // CAROUSEL PLUGIN DEFINITION
434
+ // ==========================
435
+
436
+ var old = $.fn.carousel
437
+
438
+ $.fn.carousel = function (option) {
439
+ return this.each(function () {
440
+ var $this = $(this)
441
+ var data = $this.data('bs.carousel')
442
+ var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
443
+ var action = typeof option == 'string' ? option : options.slide
444
+
445
+ if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
446
+ if (typeof option == 'number') data.to(option)
447
+ else if (action) data[action]()
448
+ else if (options.interval) data.pause().cycle()
449
+ })
450
+ }
451
+
452
+ $.fn.carousel.Constructor = Carousel
453
+
454
+
455
+ // CAROUSEL NO CONFLICT
456
+ // ====================
457
+
458
+ $.fn.carousel.noConflict = function () {
459
+ $.fn.carousel = old
460
+ return this
461
+ }
462
+
463
+
464
+ // CAROUSEL DATA-API
465
+ // =================
466
+
467
+ $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {
468
+ var $this = $(this), href
469
+ var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
470
+ var options = $.extend({}, $target.data(), $this.data())
471
+ var slideIndex = $this.attr('data-slide-to')
472
+ if (slideIndex) options.interval = false
473
+
474
+ $target.carousel(options)
475
+
476
+ if (slideIndex = $this.attr('data-slide-to')) {
477
+ $target.data('bs.carousel').to(slideIndex)
478
+ }
479
+
480
+ e.preventDefault()
481
+ })
482
+
483
+ $(window).on('load', function () {
484
+ $('[data-ride="carousel"]').each(function () {
485
+ var $carousel = $(this)
486
+ $carousel.carousel($carousel.data())
487
+ })
488
+ })
489
+
490
+ }(window.jQuery);
491
+
492
+ /* ========================================================================
493
+ * Bootstrap: collapse.js v3.0.0
494
+ * http://twbs.github.com/bootstrap/javascript.html#collapse
495
+ * ========================================================================
496
+ * Copyright 2012 Twitter, Inc.
497
+ *
498
+ * Licensed under the Apache License, Version 2.0 (the "License");
499
+ * you may not use this file except in compliance with the License.
500
+ * You may obtain a copy of the License at
501
+ *
502
+ * http://www.apache.org/licenses/LICENSE-2.0
503
+ *
504
+ * Unless required by applicable law or agreed to in writing, software
505
+ * distributed under the License is distributed on an "AS IS" BASIS,
506
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
507
+ * See the License for the specific language governing permissions and
508
+ * limitations under the License.
509
+ * ======================================================================== */
510
+
511
+
512
+ +function ($) { "use strict";
513
+
514
+ // COLLAPSE PUBLIC CLASS DEFINITION
515
+ // ================================
516
+
517
+ var Collapse = function (element, options) {
518
+ this.$element = $(element)
519
+ this.options = $.extend({}, Collapse.DEFAULTS, options)
520
+ this.transitioning = null
521
+
522
+ if (this.options.parent) this.$parent = $(this.options.parent)
523
+ if (this.options.toggle) this.toggle()
524
+ }
525
+
526
+ Collapse.DEFAULTS = {
527
+ toggle: true
528
+ }
529
+
530
+ Collapse.prototype.dimension = function () {
531
+ var hasWidth = this.$element.hasClass('width')
532
+ return hasWidth ? 'width' : 'height'
533
+ }
534
+
535
+ Collapse.prototype.show = function () {
536
+ if (this.transitioning || this.$element.hasClass('in')) return
537
+
538
+ var startEvent = $.Event('show.bs.collapse')
539
+ this.$element.trigger(startEvent)
540
+ if (startEvent.isDefaultPrevented()) return
541
+
542
+ var actives = this.$parent && this.$parent.find('> .panel > .in')
543
+
544
+ if (actives && actives.length) {
545
+ var hasData = actives.data('bs.collapse')
546
+ if (hasData && hasData.transitioning) return
547
+ actives.collapse('hide')
548
+ hasData || actives.data('bs.collapse', null)
549
+ }
550
+
551
+ var dimension = this.dimension()
552
+
553
+ this.$element
554
+ .removeClass('collapse')
555
+ .addClass('collapsing')
556
+ [dimension](0)
557
+
558
+ this.transitioning = 1
559
+
560
+ var complete = function () {
561
+ this.$element
562
+ .removeClass('collapsing')
563
+ .addClass('in')
564
+ [dimension]('auto')
565
+ this.transitioning = 0
566
+ this.$element.trigger('shown.bs.collapse')
567
+ }
568
+
569
+ if (!$.support.transition) return complete.call(this)
570
+
571
+ var scrollSize = $.camelCase(['scroll', dimension].join('-'))
572
+
573
+ this.$element
574
+ .one($.support.transition.end, $.proxy(complete, this))
575
+ .emulateTransitionEnd(350)
576
+ [dimension](this.$element[0][scrollSize])
577
+ }
578
+
579
+ Collapse.prototype.hide = function () {
580
+ if (this.transitioning || !this.$element.hasClass('in')) return
581
+
582
+ var startEvent = $.Event('hide.bs.collapse')
583
+ this.$element.trigger(startEvent)
584
+ if (startEvent.isDefaultPrevented()) return
585
+
586
+ var dimension = this.dimension()
587
+
588
+ this.$element
589
+ [dimension](this.$element[dimension]())
590
+ [0].offsetHeight
591
+
592
+ this.$element
593
+ .addClass('collapsing')
594
+ .removeClass('collapse')
595
+ .removeClass('in')
596
+
597
+ this.transitioning = 1
598
+
599
+ var complete = function () {
600
+ this.transitioning = 0
601
+ this.$element
602
+ .trigger('hidden.bs.collapse')
603
+ .removeClass('collapsing')
604
+ .addClass('collapse')
605
+ }
606
+
607
+ if (!$.support.transition) return complete.call(this)
608
+
609
+ this.$element
610
+ [dimension](0)
611
+ .one($.support.transition.end, $.proxy(complete, this))
612
+ .emulateTransitionEnd(350)
613
+ }
614
+
615
+ Collapse.prototype.toggle = function () {
616
+ this[this.$element.hasClass('in') ? 'hide' : 'show']()
617
+ }
618
+
619
+
620
+ // COLLAPSE PLUGIN DEFINITION
621
+ // ==========================
622
+
623
+ var old = $.fn.collapse
624
+
625
+ $.fn.collapse = function (option) {
626
+ return this.each(function () {
627
+ var $this = $(this)
628
+ var data = $this.data('bs.collapse')
629
+ var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
630
+
631
+ if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
632
+ if (typeof option == 'string') data[option]()
633
+ })
634
+ }
635
+
636
+ $.fn.collapse.Constructor = Collapse
637
+
638
+
639
+ // COLLAPSE NO CONFLICT
640
+ // ====================
641
+
642
+ $.fn.collapse.noConflict = function () {
643
+ $.fn.collapse = old
644
+ return this
645
+ }
646
+
647
+
648
+ // COLLAPSE DATA-API
649
+ // =================
650
+
651
+ $(document).on('click.bs.collapse.data-api', '[data-toggle=collapse]', function (e) {
652
+ var $this = $(this), href
653
+ var target = $this.attr('data-target')
654
+ || e.preventDefault()
655
+ || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
656
+ var $target = $(target)
657
+ var data = $target.data('bs.collapse')
658
+ var option = data ? 'toggle' : $this.data()
659
+ var parent = $this.attr('data-parent')
660
+ var $parent = parent && $(parent)
661
+
662
+ if (!data || !data.transitioning) {
663
+ if ($parent) $parent.find('[data-toggle=collapse][data-parent="' + parent + '"]').not($this).addClass('collapsed')
664
+ $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
665
+ }
666
+
667
+ $target.collapse(option)
668
+ })
669
+
670
+ }(window.jQuery);
671
+
672
+ /* ========================================================================
673
+ * Bootstrap: dropdown.js v3.0.0
674
+ * http://twbs.github.com/bootstrap/javascript.html#dropdowns
675
+ * ========================================================================
676
+ * Copyright 2012 Twitter, Inc.
677
+ *
678
+ * Licensed under the Apache License, Version 2.0 (the "License");
679
+ * you may not use this file except in compliance with the License.
680
+ * You may obtain a copy of the License at
681
+ *
682
+ * http://www.apache.org/licenses/LICENSE-2.0
683
+ *
684
+ * Unless required by applicable law or agreed to in writing, software
685
+ * distributed under the License is distributed on an "AS IS" BASIS,
686
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
687
+ * See the License for the specific language governing permissions and
688
+ * limitations under the License.
689
+ * ======================================================================== */
690
+
691
+
692
+ +function ($) { "use strict";
693
+
694
+ // DROPDOWN CLASS DEFINITION
695
+ // =========================
696
+
697
+ var backdrop = '.dropdown-backdrop'
698
+ var toggle = '[data-toggle=dropdown]'
699
+ var Dropdown = function (element) {
700
+ var $el = $(element).on('click.bs.dropdown', this.toggle)
701
+ }
702
+
703
+ Dropdown.prototype.toggle = function (e) {
704
+ var $this = $(this)
705
+
706
+ if ($this.is('.disabled, :disabled')) return
707
+
708
+ var $parent = getParent($this)
709
+ var isActive = $parent.hasClass('open')
710
+
711
+ clearMenus()
712
+
713
+ if (!isActive) {
714
+ if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
715
+ // if mobile we we use a backdrop because click events don't delegate
716
+ $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
717
+ }
718
+
719
+ $parent.trigger(e = $.Event('show.bs.dropdown'))
720
+
721
+ if (e.isDefaultPrevented()) return
722
+
723
+ $parent
724
+ .toggleClass('open')
725
+ .trigger('shown.bs.dropdown')
726
+
727
+ $this.focus()
728
+ }
729
+
730
+ return false
731
+ }
732
+
733
+ Dropdown.prototype.keydown = function (e) {
734
+ if (!/(38|40|27)/.test(e.keyCode)) return
735
+
736
+ var $this = $(this)
737
+
738
+ e.preventDefault()
739
+ e.stopPropagation()
740
+
741
+ if ($this.is('.disabled, :disabled')) return
742
+
743
+ var $parent = getParent($this)
744
+ var isActive = $parent.hasClass('open')
745
+
746
+ if (!isActive || (isActive && e.keyCode == 27)) {
747
+ if (e.which == 27) $parent.find(toggle).focus()
748
+ return $this.click()
749
+ }
750
+
751
+ var $items = $('[role=menu] li:not(.divider):visible a', $parent)
752
+
753
+ if (!$items.length) return
754
+
755
+ var index = $items.index($items.filter(':focus'))
756
+
757
+ if (e.keyCode == 38 && index > 0) index-- // up
758
+ if (e.keyCode == 40 && index < $items.length - 1) index++ // down
759
+ if (!~index) index=0
760
+
761
+ $items.eq(index).focus()
762
+ }
763
+
764
+ function clearMenus() {
765
+ $(backdrop).remove()
766
+ $(toggle).each(function (e) {
767
+ var $parent = getParent($(this))
768
+ if (!$parent.hasClass('open')) return
769
+ $parent.trigger(e = $.Event('hide.bs.dropdown'))
770
+ if (e.isDefaultPrevented()) return
771
+ $parent.removeClass('open').trigger('hidden.bs.dropdown')
772
+ })
773
+ }
774
+
775
+ function getParent($this) {
776
+ var selector = $this.attr('data-target')
777
+
778
+ if (!selector) {
779
+ selector = $this.attr('href')
780
+ selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
781
+ }
782
+
783
+ var $parent = selector && $(selector)
784
+
785
+ return $parent && $parent.length ? $parent : $this.parent()
786
+ }
787
+
788
+
789
+ // DROPDOWN PLUGIN DEFINITION
790
+ // ==========================
791
+
792
+ var old = $.fn.dropdown
793
+
794
+ $.fn.dropdown = function (option) {
795
+ return this.each(function () {
796
+ var $this = $(this)
797
+ var data = $this.data('dropdown')
798
+
799
+ if (!data) $this.data('dropdown', (data = new Dropdown(this)))
800
+ if (typeof option == 'string') data[option].call($this)
801
+ })
802
+ }
803
+
804
+ $.fn.dropdown.Constructor = Dropdown
805
+
806
+
807
+ // DROPDOWN NO CONFLICT
808
+ // ====================
809
+
810
+ $.fn.dropdown.noConflict = function () {
811
+ $.fn.dropdown = old
812
+ return this
813
+ }
814
+
815
+
816
+ // APPLY TO STANDARD DROPDOWN ELEMENTS
817
+ // ===================================
818
+
819
+ $(document)
820
+ .on('click.bs.dropdown.data-api', clearMenus)
821
+ .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
822
+ .on('click.bs.dropdown.data-api' , toggle, Dropdown.prototype.toggle)
823
+ .on('keydown.bs.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
824
+
825
+ }(window.jQuery);
826
+
827
+ /* ========================================================================
828
+ * Bootstrap: modal.js v3.0.0
829
+ * http://twbs.github.com/bootstrap/javascript.html#modals
830
+ * ========================================================================
831
+ * Copyright 2012 Twitter, Inc.
832
+ *
833
+ * Licensed under the Apache License, Version 2.0 (the "License");
834
+ * you may not use this file except in compliance with the License.
835
+ * You may obtain a copy of the License at
836
+ *
837
+ * http://www.apache.org/licenses/LICENSE-2.0
838
+ *
839
+ * Unless required by applicable law or agreed to in writing, software
840
+ * distributed under the License is distributed on an "AS IS" BASIS,
841
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
842
+ * See the License for the specific language governing permissions and
843
+ * limitations under the License.
844
+ * ======================================================================== */
845
+
846
+
847
+ +function ($) { "use strict";
848
+
849
+ // MODAL CLASS DEFINITION
850
+ // ======================
851
+
852
+ var Modal = function (element, options) {
853
+ this.options = options
854
+ this.$element = $(element)
855
+ this.$backdrop =
856
+ this.isShown = null
857
+
858
+ if (this.options.remote) this.$element.load(this.options.remote)
859
+ }
860
+
861
+ Modal.DEFAULTS = {
862
+ backdrop: true
863
+ , keyboard: true
864
+ , show: true
865
+ }
866
+
867
+ Modal.prototype.toggle = function (_relatedTarget) {
868
+ return this[!this.isShown ? 'show' : 'hide'](_relatedTarget)
869
+ }
870
+
871
+ Modal.prototype.show = function (_relatedTarget) {
872
+ var that = this
873
+ var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
874
+
875
+ this.$element.trigger(e)
876
+
877
+ if (this.isShown || e.isDefaultPrevented()) return
878
+
879
+ this.isShown = true
880
+
881
+ this.escape()
882
+
883
+ this.$element.on('click.dismiss.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
884
+
885
+ this.backdrop(function () {
886
+ var transition = $.support.transition && that.$element.hasClass('fade')
887
+
888
+ if (!that.$element.parent().length) {
889
+ that.$element.appendTo(document.body) // don't move modals dom position
890
+ }
891
+
892
+ that.$element.show()
893
+
894
+ if (transition) {
895
+ that.$element[0].offsetWidth // force reflow
896
+ }
897
+
898
+ that.$element
899
+ .addClass('in')
900
+ .attr('aria-hidden', false)
901
+
902
+ that.enforceFocus()
903
+
904
+ var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
905
+
906
+ transition ?
907
+ that.$element.find('.modal-dialog') // wait for modal to slide in
908
+ .one($.support.transition.end, function () {
909
+ that.$element.focus().trigger(e)
910
+ })
911
+ .emulateTransitionEnd(300) :
912
+ that.$element.focus().trigger(e)
913
+ })
914
+ }
915
+
916
+ Modal.prototype.hide = function (e) {
917
+ if (e) e.preventDefault()
918
+
919
+ e = $.Event('hide.bs.modal')
920
+
921
+ this.$element.trigger(e)
922
+
923
+ if (!this.isShown || e.isDefaultPrevented()) return
924
+
925
+ this.isShown = false
926
+
927
+ this.escape()
928
+
929
+ $(document).off('focusin.bs.modal')
930
+
931
+ this.$element
932
+ .removeClass('in')
933
+ .attr('aria-hidden', true)
934
+ .off('click.dismiss.modal')
935
+
936
+ $.support.transition && this.$element.hasClass('fade') ?
937
+ this.$element
938
+ .one($.support.transition.end, $.proxy(this.hideModal, this))
939
+ .emulateTransitionEnd(300) :
940
+ this.hideModal()
941
+ }
942
+
943
+ Modal.prototype.enforceFocus = function () {
944
+ $(document)
945
+ .off('focusin.bs.modal') // guard against infinite focus loop
946
+ .on('focusin.bs.modal', $.proxy(function (e) {
947
+ if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
948
+ this.$element.focus()
949
+ }
950
+ }, this))
951
+ }
952
+
953
+ Modal.prototype.escape = function () {
954
+ if (this.isShown && this.options.keyboard) {
955
+ this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) {
956
+ e.which == 27 && this.hide()
957
+ }, this))
958
+ } else if (!this.isShown) {
959
+ this.$element.off('keyup.dismiss.bs.modal')
960
+ }
961
+ }
962
+
963
+ Modal.prototype.hideModal = function () {
964
+ var that = this
965
+ this.$element.hide()
966
+ this.backdrop(function () {
967
+ that.removeBackdrop()
968
+ that.$element.trigger('hidden.bs.modal')
969
+ })
970
+ }
971
+
972
+ Modal.prototype.removeBackdrop = function () {
973
+ this.$backdrop && this.$backdrop.remove()
974
+ this.$backdrop = null
975
+ }
976
+
977
+ Modal.prototype.backdrop = function (callback) {
978
+ var that = this
979
+ var animate = this.$element.hasClass('fade') ? 'fade' : ''
980
+
981
+ if (this.isShown && this.options.backdrop) {
982
+ var doAnimate = $.support.transition && animate
983
+
984
+ this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
985
+ .appendTo(document.body)
986
+
987
+ this.$element.on('click.dismiss.modal', $.proxy(function (e) {
988
+ if (e.target !== e.currentTarget) return
989
+ this.options.backdrop == 'static'
990
+ ? this.$element[0].focus.call(this.$element[0])
991
+ : this.hide.call(this)
992
+ }, this))
993
+
994
+ if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
995
+
996
+ this.$backdrop.addClass('in')
997
+
998
+ if (!callback) return
999
+
1000
+ doAnimate ?
1001
+ this.$backdrop
1002
+ .one($.support.transition.end, callback)
1003
+ .emulateTransitionEnd(150) :
1004
+ callback()
1005
+
1006
+ } else if (!this.isShown && this.$backdrop) {
1007
+ this.$backdrop.removeClass('in')
1008
+
1009
+ $.support.transition && this.$element.hasClass('fade')?
1010
+ this.$backdrop
1011
+ .one($.support.transition.end, callback)
1012
+ .emulateTransitionEnd(150) :
1013
+ callback()
1014
+
1015
+ } else if (callback) {
1016
+ callback()
1017
+ }
1018
+ }
1019
+
1020
+
1021
+ // MODAL PLUGIN DEFINITION
1022
+ // =======================
1023
+
1024
+ var old = $.fn.modal
1025
+
1026
+ $.fn.modal = function (option, _relatedTarget) {
1027
+ return this.each(function () {
1028
+ var $this = $(this)
1029
+ var data = $this.data('bs.modal')
1030
+ var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
1031
+
1032
+ if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
1033
+ if (typeof option == 'string') data[option](_relatedTarget)
1034
+ else if (options.show) data.show(_relatedTarget)
1035
+ })
1036
+ }
1037
+
1038
+ $.fn.modal.Constructor = Modal
1039
+
1040
+
1041
+ // MODAL NO CONFLICT
1042
+ // =================
1043
+
1044
+ $.fn.modal.noConflict = function () {
1045
+ $.fn.modal = old
1046
+ return this
1047
+ }
1048
+
1049
+
1050
+ // MODAL DATA-API
1051
+ // ==============
1052
+
1053
+ $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
1054
+ var $this = $(this)
1055
+ var href = $this.attr('href')
1056
+ var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
1057
+ var option = $target.data('modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
1058
+
1059
+ e.preventDefault()
1060
+
1061
+ $target
1062
+ .modal(option, this)
1063
+ .one('hide', function () {
1064
+ $this.is(':visible') && $this.focus()
1065
+ })
1066
+ })
1067
+
1068
+ $(document)
1069
+ .on('show.bs.modal', '.modal', function () { $(document.body).addClass('modal-open') })
1070
+ .on('hidden.bs.modal', '.modal', function () { $(document.body).removeClass('modal-open') })
1071
+
1072
+ }(window.jQuery);
1073
+
1074
+ /* ========================================================================
1075
+ * Bootstrap: tooltip.js v3.0.0
1076
+ * http://twbs.github.com/bootstrap/javascript.html#tooltip
1077
+ * Inspired by the original jQuery.tipsy by Jason Frame
1078
+ * ========================================================================
1079
+ * Copyright 2012 Twitter, Inc.
1080
+ *
1081
+ * Licensed under the Apache License, Version 2.0 (the "License");
1082
+ * you may not use this file except in compliance with the License.
1083
+ * You may obtain a copy of the License at
1084
+ *
1085
+ * http://www.apache.org/licenses/LICENSE-2.0
1086
+ *
1087
+ * Unless required by applicable law or agreed to in writing, software
1088
+ * distributed under the License is distributed on an "AS IS" BASIS,
1089
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1090
+ * See the License for the specific language governing permissions and
1091
+ * limitations under the License.
1092
+ * ======================================================================== */
1093
+
1094
+
1095
+ +function ($) { "use strict";
1096
+
1097
+ // TOOLTIP PUBLIC CLASS DEFINITION
1098
+ // ===============================
1099
+
1100
+ var Tooltip = function (element, options) {
1101
+ this.type =
1102
+ this.options =
1103
+ this.enabled =
1104
+ this.timeout =
1105
+ this.hoverState =
1106
+ this.$element = null
1107
+
1108
+ this.init('tooltip', element, options)
1109
+ }
1110
+
1111
+ Tooltip.DEFAULTS = {
1112
+ animation: true
1113
+ , placement: 'top'
1114
+ , selector: false
1115
+ , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
1116
+ , trigger: 'hover focus'
1117
+ , title: ''
1118
+ , delay: 0
1119
+ , html: false
1120
+ , container: false
1121
+ }
1122
+
1123
+ Tooltip.prototype.init = function (type, element, options) {
1124
+ this.enabled = true
1125
+ this.type = type
1126
+ this.$element = $(element)
1127
+ this.options = this.getOptions(options)
1128
+
1129
+ var triggers = this.options.trigger.split(' ')
1130
+
1131
+ for (var i = triggers.length; i--;) {
1132
+ var trigger = triggers[i]
1133
+
1134
+ if (trigger == 'click') {
1135
+ this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
1136
+ } else if (trigger != 'manual') {
1137
+ var eventIn = trigger == 'hover' ? 'mouseenter' : 'focus'
1138
+ var eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'
1139
+
1140
+ this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
1141
+ this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
1142
+ }
1143
+ }
1144
+
1145
+ this.options.selector ?
1146
+ (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
1147
+ this.fixTitle()
1148
+ }
1149
+
1150
+ Tooltip.prototype.getDefaults = function () {
1151
+ return Tooltip.DEFAULTS
1152
+ }
1153
+
1154
+ Tooltip.prototype.getOptions = function (options) {
1155
+ options = $.extend({}, this.getDefaults(), this.$element.data(), options)
1156
+
1157
+ if (options.delay && typeof options.delay == 'number') {
1158
+ options.delay = {
1159
+ show: options.delay
1160
+ , hide: options.delay
1161
+ }
1162
+ }
1163
+
1164
+ return options
1165
+ }
1166
+
1167
+ Tooltip.prototype.getDelegateOptions = function () {
1168
+ var options = {}
1169
+ var defaults = this.getDefaults()
1170
+
1171
+ this._options && $.each(this._options, function (key, value) {
1172
+ if (defaults[key] != value) options[key] = value
1173
+ })
1174
+
1175
+ return options
1176
+ }
1177
+
1178
+ Tooltip.prototype.enter = function (obj) {
1179
+ var self = obj instanceof this.constructor ?
1180
+ obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
1181
+
1182
+ clearTimeout(self.timeout)
1183
+
1184
+ self.hoverState = 'in'
1185
+
1186
+ if (!self.options.delay || !self.options.delay.show) return self.show()
1187
+
1188
+ self.timeout = setTimeout(function () {
1189
+ if (self.hoverState == 'in') self.show()
1190
+ }, self.options.delay.show)
1191
+ }
1192
+
1193
+ Tooltip.prototype.leave = function (obj) {
1194
+ var self = obj instanceof this.constructor ?
1195
+ obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
1196
+
1197
+ clearTimeout(self.timeout)
1198
+
1199
+ self.hoverState = 'out'
1200
+
1201
+ if (!self.options.delay || !self.options.delay.hide) return self.hide()
1202
+
1203
+ self.timeout = setTimeout(function () {
1204
+ if (self.hoverState == 'out') self.hide()
1205
+ }, self.options.delay.hide)
1206
+ }
1207
+
1208
+ Tooltip.prototype.show = function () {
1209
+ var e = $.Event('show.bs.'+ this.type)
1210
+
1211
+ if (this.hasContent() && this.enabled) {
1212
+ this.$element.trigger(e)
1213
+
1214
+ if (e.isDefaultPrevented()) return
1215
+
1216
+ var $tip = this.tip()
1217
+
1218
+ this.setContent()
1219
+
1220
+ if (this.options.animation) $tip.addClass('fade')
1221
+
1222
+ var placement = typeof this.options.placement == 'function' ?
1223
+ this.options.placement.call(this, $tip[0], this.$element[0]) :
1224
+ this.options.placement
1225
+
1226
+ var autoToken = /\s?auto?\s?/i
1227
+ var autoPlace = autoToken.test(placement)
1228
+ if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
1229
+
1230
+ $tip
1231
+ .detach()
1232
+ .css({ top: 0, left: 0, display: 'block' })
1233
+ .addClass(placement)
1234
+
1235
+ this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
1236
+
1237
+ var pos = this.getPosition()
1238
+ var actualWidth = $tip[0].offsetWidth
1239
+ var actualHeight = $tip[0].offsetHeight
1240
+
1241
+ if (autoPlace) {
1242
+ var $parent = this.$element.parent()
1243
+
1244
+ var orgPlacement = placement
1245
+ var docScroll = document.documentElement.scrollTop || document.body.scrollTop
1246
+ var parentWidth = this.options.container == 'body' ? window.innerWidth : $parent.outerWidth()
1247
+ var parentHeight = this.options.container == 'body' ? window.innerHeight : $parent.outerHeight()
1248
+ var parentLeft = this.options.container == 'body' ? 0 : $parent.offset().left
1249
+
1250
+ placement = placement == 'bottom' && pos.top + pos.height + actualHeight - docScroll > parentHeight ? 'top' :
1251
+ placement == 'top' && pos.top - docScroll - actualHeight < 0 ? 'bottom' :
1252
+ placement == 'right' && pos.right + actualWidth > parentWidth ? 'left' :
1253
+ placement == 'left' && pos.left - actualWidth < parentLeft ? 'right' :
1254
+ placement
1255
+
1256
+ $tip
1257
+ .removeClass(orgPlacement)
1258
+ .addClass(placement)
1259
+ }
1260
+
1261
+ var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
1262
+
1263
+ this.applyPlacement(calculatedOffset, placement)
1264
+ this.$element.trigger('shown.bs.' + this.type)
1265
+ }
1266
+ }
1267
+
1268
+ Tooltip.prototype.applyPlacement = function(offset, placement) {
1269
+ var replace
1270
+ var $tip = this.tip()
1271
+ var width = $tip[0].offsetWidth
1272
+ var height = $tip[0].offsetHeight
1273
+
1274
+ // manually read margins because getBoundingClientRect includes difference
1275
+ var marginTop = parseInt($tip.css('margin-top'), 10)
1276
+ var marginLeft = parseInt($tip.css('margin-left'), 10)
1277
+
1278
+ // we must check for NaN for ie 8/9
1279
+ if (isNaN(marginTop)) marginTop = 0
1280
+ if (isNaN(marginLeft)) marginLeft = 0
1281
+
1282
+ offset.top = offset.top + marginTop
1283
+ offset.left = offset.left + marginLeft
1284
+
1285
+ $tip
1286
+ .offset(offset)
1287
+ .addClass('in')
1288
+
1289
+ // check to see if placing tip in new offset caused the tip to resize itself
1290
+ var actualWidth = $tip[0].offsetWidth
1291
+ var actualHeight = $tip[0].offsetHeight
1292
+
1293
+ if (placement == 'top' && actualHeight != height) {
1294
+ replace = true
1295
+ offset.top = offset.top + height - actualHeight
1296
+ }
1297
+
1298
+ if (/bottom|top/.test(placement)) {
1299
+ var delta = 0
1300
+
1301
+ if (offset.left < 0) {
1302
+ delta = offset.left * -2
1303
+ offset.left = 0
1304
+
1305
+ $tip.offset(offset)
1306
+
1307
+ actualWidth = $tip[0].offsetWidth
1308
+ actualHeight = $tip[0].offsetHeight
1309
+ }
1310
+
1311
+ this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
1312
+ } else {
1313
+ this.replaceArrow(actualHeight - height, actualHeight, 'top')
1314
+ }
1315
+
1316
+ if (replace) $tip.offset(offset)
1317
+ }
1318
+
1319
+ Tooltip.prototype.replaceArrow = function(delta, dimension, position) {
1320
+ this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + "%") : '')
1321
+ }
1322
+
1323
+ Tooltip.prototype.setContent = function () {
1324
+ var $tip = this.tip()
1325
+ var title = this.getTitle()
1326
+
1327
+ $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
1328
+ $tip.removeClass('fade in top bottom left right')
1329
+ }
1330
+
1331
+ Tooltip.prototype.hide = function () {
1332
+ var that = this
1333
+ var $tip = this.tip()
1334
+ var e = $.Event('hide.bs.' + this.type)
1335
+
1336
+ function complete() {
1337
+ if (that.hoverState != 'in') $tip.detach()
1338
+ }
1339
+
1340
+ this.$element.trigger(e)
1341
+
1342
+ if (e.isDefaultPrevented()) return
1343
+
1344
+ $tip.removeClass('in')
1345
+
1346
+ $.support.transition && this.$tip.hasClass('fade') ?
1347
+ $tip
1348
+ .one($.support.transition.end, complete)
1349
+ .emulateTransitionEnd(150) :
1350
+ complete()
1351
+
1352
+ this.$element.trigger('hidden.bs.' + this.type)
1353
+
1354
+ return this
1355
+ }
1356
+
1357
+ Tooltip.prototype.fixTitle = function () {
1358
+ var $e = this.$element
1359
+ if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
1360
+ $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
1361
+ }
1362
+ }
1363
+
1364
+ Tooltip.prototype.hasContent = function () {
1365
+ return this.getTitle()
1366
+ }
1367
+
1368
+ Tooltip.prototype.getPosition = function () {
1369
+ var el = this.$element[0]
1370
+ return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
1371
+ width: el.offsetWidth
1372
+ , height: el.offsetHeight
1373
+ }, this.$element.offset())
1374
+ }
1375
+
1376
+ Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
1377
+ return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
1378
+ placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
1379
+ placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
1380
+ /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
1381
+ }
1382
+
1383
+ Tooltip.prototype.getTitle = function () {
1384
+ var title
1385
+ var $e = this.$element
1386
+ var o = this.options
1387
+
1388
+ title = $e.attr('data-original-title')
1389
+ || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
1390
+
1391
+ return title
1392
+ }
1393
+
1394
+ Tooltip.prototype.tip = function () {
1395
+ return this.$tip = this.$tip || $(this.options.template)
1396
+ }
1397
+
1398
+ Tooltip.prototype.arrow = function () {
1399
+ return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
1400
+ }
1401
+
1402
+ Tooltip.prototype.validate = function () {
1403
+ if (!this.$element[0].parentNode) {
1404
+ this.hide()
1405
+ this.$element = null
1406
+ this.options = null
1407
+ }
1408
+ }
1409
+
1410
+ Tooltip.prototype.enable = function () {
1411
+ this.enabled = true
1412
+ }
1413
+
1414
+ Tooltip.prototype.disable = function () {
1415
+ this.enabled = false
1416
+ }
1417
+
1418
+ Tooltip.prototype.toggleEnabled = function () {
1419
+ this.enabled = !this.enabled
1420
+ }
1421
+
1422
+ Tooltip.prototype.toggle = function (e) {
1423
+ var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this
1424
+ self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
1425
+ }
1426
+
1427
+ Tooltip.prototype.destroy = function () {
1428
+ this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
1429
+ }
1430
+
1431
+
1432
+ // TOOLTIP PLUGIN DEFINITION
1433
+ // =========================
1434
+
1435
+ var old = $.fn.tooltip
1436
+
1437
+ $.fn.tooltip = function (option) {
1438
+ return this.each(function () {
1439
+ var $this = $(this)
1440
+ var data = $this.data('bs.tooltip')
1441
+ var options = typeof option == 'object' && option
1442
+
1443
+ if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
1444
+ if (typeof option == 'string') data[option]()
1445
+ })
1446
+ }
1447
+
1448
+ $.fn.tooltip.Constructor = Tooltip
1449
+
1450
+
1451
+ // TOOLTIP NO CONFLICT
1452
+ // ===================
1453
+
1454
+ $.fn.tooltip.noConflict = function () {
1455
+ $.fn.tooltip = old
1456
+ return this
1457
+ }
1458
+
1459
+ }(window.jQuery);
1460
+
1461
+ /* ========================================================================
1462
+ * Bootstrap: popover.js v3.0.0
1463
+ * http://twbs.github.com/bootstrap/javascript.html#popovers
1464
+ * ========================================================================
1465
+ * Copyright 2012 Twitter, Inc.
1466
+ *
1467
+ * Licensed under the Apache License, Version 2.0 (the "License");
1468
+ * you may not use this file except in compliance with the License.
1469
+ * You may obtain a copy of the License at
1470
+ *
1471
+ * http://www.apache.org/licenses/LICENSE-2.0
1472
+ *
1473
+ * Unless required by applicable law or agreed to in writing, software
1474
+ * distributed under the License is distributed on an "AS IS" BASIS,
1475
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1476
+ * See the License for the specific language governing permissions and
1477
+ * limitations under the License.
1478
+ * ======================================================================== */
1479
+
1480
+
1481
+ +function ($) { "use strict";
1482
+
1483
+ // POPOVER PUBLIC CLASS DEFINITION
1484
+ // ===============================
1485
+
1486
+ var Popover = function (element, options) {
1487
+ this.init('popover', element, options)
1488
+ }
1489
+
1490
+ if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
1491
+
1492
+ Popover.DEFAULTS = $.extend({} , $.fn.tooltip.Constructor.DEFAULTS, {
1493
+ placement: 'right'
1494
+ , trigger: 'click'
1495
+ , content: ''
1496
+ , template: '<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
1497
+ })
1498
+
1499
+
1500
+ // NOTE: POPOVER EXTENDS tooltip.js
1501
+ // ================================
1502
+
1503
+ Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
1504
+
1505
+ Popover.prototype.constructor = Popover
1506
+
1507
+ Popover.prototype.getDefaults = function () {
1508
+ return Popover.DEFAULTS
1509
+ }
1510
+
1511
+ Popover.prototype.setContent = function () {
1512
+ var $tip = this.tip()
1513
+ var title = this.getTitle()
1514
+ var content = this.getContent()
1515
+
1516
+ $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
1517
+ $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)
1518
+
1519
+ $tip.removeClass('fade top bottom left right in')
1520
+
1521
+ // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
1522
+ // this manually by checking the contents.
1523
+ if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
1524
+ }
1525
+
1526
+ Popover.prototype.hasContent = function () {
1527
+ return this.getTitle() || this.getContent()
1528
+ }
1529
+
1530
+ Popover.prototype.getContent = function () {
1531
+ var $e = this.$element
1532
+ var o = this.options
1533
+
1534
+ return $e.attr('data-content')
1535
+ || (typeof o.content == 'function' ?
1536
+ o.content.call($e[0]) :
1537
+ o.content)
1538
+ }
1539
+
1540
+ Popover.prototype.arrow = function () {
1541
+ return this.$arrow = this.$arrow || this.tip().find('.arrow')
1542
+ }
1543
+
1544
+ Popover.prototype.tip = function () {
1545
+ if (!this.$tip) this.$tip = $(this.options.template)
1546
+ return this.$tip
1547
+ }
1548
+
1549
+
1550
+ // POPOVER PLUGIN DEFINITION
1551
+ // =========================
1552
+
1553
+ var old = $.fn.popover
1554
+
1555
+ $.fn.popover = function (option) {
1556
+ return this.each(function () {
1557
+ var $this = $(this)
1558
+ var data = $this.data('bs.popover')
1559
+ var options = typeof option == 'object' && option
1560
+
1561
+ if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
1562
+ if (typeof option == 'string') data[option]()
1563
+ })
1564
+ }
1565
+
1566
+ $.fn.popover.Constructor = Popover
1567
+
1568
+
1569
+ // POPOVER NO CONFLICT
1570
+ // ===================
1571
+
1572
+ $.fn.popover.noConflict = function () {
1573
+ $.fn.popover = old
1574
+ return this
1575
+ }
1576
+
1577
+ }(window.jQuery);
1578
+
1579
+ /* ========================================================================
1580
+ * Bootstrap: scrollspy.js v3.0.0
1581
+ * http://twbs.github.com/bootstrap/javascript.html#scrollspy
1582
+ * ========================================================================
1583
+ * Copyright 2012 Twitter, Inc.
1584
+ *
1585
+ * Licensed under the Apache License, Version 2.0 (the "License");
1586
+ * you may not use this file except in compliance with the License.
1587
+ * You may obtain a copy of the License at
1588
+ *
1589
+ * http://www.apache.org/licenses/LICENSE-2.0
1590
+ *
1591
+ * Unless required by applicable law or agreed to in writing, software
1592
+ * distributed under the License is distributed on an "AS IS" BASIS,
1593
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1594
+ * See the License for the specific language governing permissions and
1595
+ * limitations under the License.
1596
+ * ======================================================================== */
1597
+
1598
+
1599
+ +function ($) { "use strict";
1600
+
1601
+ // SCROLLSPY CLASS DEFINITION
1602
+ // ==========================
1603
+
1604
+ function ScrollSpy(element, options) {
1605
+ var href
1606
+ var process = $.proxy(this.process, this)
1607
+
1608
+ this.$element = $(element).is('body') ? $(window) : $(element)
1609
+ this.$body = $('body')
1610
+ this.$scrollElement = this.$element.on('scroll.bs.scroll-spy.data-api', process)
1611
+ this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
1612
+ this.selector = (this.options.target
1613
+ || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
1614
+ || '') + ' .nav li > a'
1615
+ this.offsets = $([])
1616
+ this.targets = $([])
1617
+ this.activeTarget = null
1618
+
1619
+ this.refresh()
1620
+ this.process()
1621
+ }
1622
+
1623
+ ScrollSpy.DEFAULTS = {
1624
+ offset: 10
1625
+ }
1626
+
1627
+ ScrollSpy.prototype.refresh = function () {
1628
+ var offsetMethod = this.$element[0] == window ? 'offset' : 'position'
1629
+
1630
+ this.offsets = $([])
1631
+ this.targets = $([])
1632
+
1633
+ var self = this
1634
+ var $targets = this.$body
1635
+ .find(this.selector)
1636
+ .map(function () {
1637
+ var $el = $(this)
1638
+ var href = $el.data('target') || $el.attr('href')
1639
+ var $href = /^#\w/.test(href) && $(href)
1640
+
1641
+ return ($href
1642
+ && $href.length
1643
+ && [[ $href[offsetMethod]().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]]) || null
1644
+ })
1645
+ .sort(function (a, b) { return a[0] - b[0] })
1646
+ .each(function () {
1647
+ self.offsets.push(this[0])
1648
+ self.targets.push(this[1])
1649
+ })
1650
+ }
1651
+
1652
+ ScrollSpy.prototype.process = function () {
1653
+ var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
1654
+ var scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight
1655
+ var maxScroll = scrollHeight - this.$scrollElement.height()
1656
+ var offsets = this.offsets
1657
+ var targets = this.targets
1658
+ var activeTarget = this.activeTarget
1659
+ var i
1660
+
1661
+ if (scrollTop >= maxScroll) {
1662
+ return activeTarget != (i = targets.last()[0]) && this.activate(i)
1663
+ }
1664
+
1665
+ for (i = offsets.length; i--;) {
1666
+ activeTarget != targets[i]
1667
+ && scrollTop >= offsets[i]
1668
+ && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
1669
+ && this.activate( targets[i] )
1670
+ }
1671
+ }
1672
+
1673
+ ScrollSpy.prototype.activate = function (target) {
1674
+ this.activeTarget = target
1675
+
1676
+ $(this.selector)
1677
+ .parents('.active')
1678
+ .removeClass('active')
1679
+
1680
+ var selector = this.selector
1681
+ + '[data-target="' + target + '"],'
1682
+ + this.selector + '[href="' + target + '"]'
1683
+
1684
+ var active = $(selector)
1685
+ .parents('li')
1686
+ .addClass('active')
1687
+
1688
+ if (active.parent('.dropdown-menu').length) {
1689
+ active = active
1690
+ .closest('li.dropdown')
1691
+ .addClass('active')
1692
+ }
1693
+
1694
+ active.trigger('activate')
1695
+ }
1696
+
1697
+
1698
+ // SCROLLSPY PLUGIN DEFINITION
1699
+ // ===========================
1700
+
1701
+ var old = $.fn.scrollspy
1702
+
1703
+ $.fn.scrollspy = function (option) {
1704
+ return this.each(function () {
1705
+ var $this = $(this)
1706
+ var data = $this.data('bs.scrollspy')
1707
+ var options = typeof option == 'object' && option
1708
+
1709
+ if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
1710
+ if (typeof option == 'string') data[option]()
1711
+ })
1712
+ }
1713
+
1714
+ $.fn.scrollspy.Constructor = ScrollSpy
1715
+
1716
+
1717
+ // SCROLLSPY NO CONFLICT
1718
+ // =====================
1719
+
1720
+ $.fn.scrollspy.noConflict = function () {
1721
+ $.fn.scrollspy = old
1722
+ return this
1723
+ }
1724
+
1725
+
1726
+ // SCROLLSPY DATA-API
1727
+ // ==================
1728
+
1729
+ $(window).on('load', function () {
1730
+ $('[data-spy="scroll"]').each(function () {
1731
+ var $spy = $(this)
1732
+ $spy.scrollspy($spy.data())
1733
+ })
1734
+ })
1735
+
1736
+ }(window.jQuery);
1737
+
1738
+ /* ========================================================================
1739
+ * Bootstrap: tab.js v3.0.0
1740
+ * http://twbs.github.com/bootstrap/javascript.html#tabs
1741
+ * ========================================================================
1742
+ * Copyright 2012 Twitter, Inc.
1743
+ *
1744
+ * Licensed under the Apache License, Version 2.0 (the "License");
1745
+ * you may not use this file except in compliance with the License.
1746
+ * You may obtain a copy of the License at
1747
+ *
1748
+ * http://www.apache.org/licenses/LICENSE-2.0
1749
+ *
1750
+ * Unless required by applicable law or agreed to in writing, software
1751
+ * distributed under the License is distributed on an "AS IS" BASIS,
1752
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1753
+ * See the License for the specific language governing permissions and
1754
+ * limitations under the License.
1755
+ * ======================================================================== */
1756
+
1757
+
1758
+ +function ($) { "use strict";
1759
+
1760
+ // TAB CLASS DEFINITION
1761
+ // ====================
1762
+
1763
+ var Tab = function (element) {
1764
+ this.element = $(element)
1765
+ }
1766
+
1767
+ Tab.prototype.show = function () {
1768
+ var $this = this.element
1769
+ var $ul = $this.closest('ul:not(.dropdown-menu)')
1770
+ var selector = $this.attr('data-target')
1771
+
1772
+ if (!selector) {
1773
+ selector = $this.attr('href')
1774
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
1775
+ }
1776
+
1777
+ if ($this.parent('li').hasClass('active')) return
1778
+
1779
+ var previous = $ul.find('.active:last a')[0]
1780
+ var e = $.Event('show.bs.tab', {
1781
+ relatedTarget: previous
1782
+ })
1783
+
1784
+ $this.trigger(e)
1785
+
1786
+ if (e.isDefaultPrevented()) return
1787
+
1788
+ var $target = $(selector)
1789
+
1790
+ this.activate($this.parent('li'), $ul)
1791
+ this.activate($target, $target.parent(), function () {
1792
+ $this.trigger({
1793
+ type: 'shown.bs.tab'
1794
+ , relatedTarget: previous
1795
+ })
1796
+ })
1797
+ }
1798
+
1799
+ Tab.prototype.activate = function (element, container, callback) {
1800
+ var $active = container.find('> .active')
1801
+ var transition = callback
1802
+ && $.support.transition
1803
+ && $active.hasClass('fade')
1804
+
1805
+ function next() {
1806
+ $active
1807
+ .removeClass('active')
1808
+ .find('> .dropdown-menu > .active')
1809
+ .removeClass('active')
1810
+
1811
+ element.addClass('active')
1812
+
1813
+ if (transition) {
1814
+ element[0].offsetWidth // reflow for transition
1815
+ element.addClass('in')
1816
+ } else {
1817
+ element.removeClass('fade')
1818
+ }
1819
+
1820
+ if (element.parent('.dropdown-menu')) {
1821
+ element.closest('li.dropdown').addClass('active')
1822
+ }
1823
+
1824
+ callback && callback()
1825
+ }
1826
+
1827
+ transition ?
1828
+ $active
1829
+ .one($.support.transition.end, next)
1830
+ .emulateTransitionEnd(150) :
1831
+ next()
1832
+
1833
+ $active.removeClass('in')
1834
+ }
1835
+
1836
+
1837
+ // TAB PLUGIN DEFINITION
1838
+ // =====================
1839
+
1840
+ var old = $.fn.tab
1841
+
1842
+ $.fn.tab = function ( option ) {
1843
+ return this.each(function () {
1844
+ var $this = $(this)
1845
+ var data = $this.data('bs.tab')
1846
+
1847
+ if (!data) $this.data('bs.tab', (data = new Tab(this)))
1848
+ if (typeof option == 'string') data[option]()
1849
+ })
1850
+ }
1851
+
1852
+ $.fn.tab.Constructor = Tab
1853
+
1854
+
1855
+ // TAB NO CONFLICT
1856
+ // ===============
1857
+
1858
+ $.fn.tab.noConflict = function () {
1859
+ $.fn.tab = old
1860
+ return this
1861
+ }
1862
+
1863
+
1864
+ // TAB DATA-API
1865
+ // ============
1866
+
1867
+ $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
1868
+ e.preventDefault()
1869
+ $(this).tab('show')
1870
+ })
1871
+
1872
+ }(window.jQuery);
1873
+
1874
+ /* ========================================================================
1875
+ * Bootstrap: affix.js v3.0.0
1876
+ * http://twbs.github.com/bootstrap/javascript.html#affix
1877
+ * ========================================================================
1878
+ * Copyright 2012 Twitter, Inc.
1879
+ *
1880
+ * Licensed under the Apache License, Version 2.0 (the "License");
1881
+ * you may not use this file except in compliance with the License.
1882
+ * You may obtain a copy of the License at
1883
+ *
1884
+ * http://www.apache.org/licenses/LICENSE-2.0
1885
+ *
1886
+ * Unless required by applicable law or agreed to in writing, software
1887
+ * distributed under the License is distributed on an "AS IS" BASIS,
1888
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1889
+ * See the License for the specific language governing permissions and
1890
+ * limitations under the License.
1891
+ * ======================================================================== */
1892
+
1893
+
1894
+ +function ($) { "use strict";
1895
+
1896
+ // AFFIX CLASS DEFINITION
1897
+ // ======================
1898
+
1899
+ var Affix = function (element, options) {
1900
+ this.options = $.extend({}, Affix.DEFAULTS, options)
1901
+ this.$window = $(window)
1902
+ .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
1903
+ .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
1904
+
1905
+ this.$element = $(element)
1906
+ this.affixed =
1907
+ this.unpin = null
1908
+
1909
+ this.checkPosition()
1910
+ }
1911
+
1912
+ Affix.RESET = 'affix affix-top affix-bottom'
1913
+
1914
+ Affix.DEFAULTS = {
1915
+ offset: 0
1916
+ }
1917
+
1918
+ Affix.prototype.checkPositionWithEventLoop = function () {
1919
+ setTimeout($.proxy(this.checkPosition, this), 1)
1920
+ }
1921
+
1922
+ Affix.prototype.checkPosition = function () {
1923
+ if (!this.$element.is(':visible')) return
1924
+
1925
+ var scrollHeight = $(document).height()
1926
+ var scrollTop = this.$window.scrollTop()
1927
+ var position = this.$element.offset()
1928
+ var offset = this.options.offset
1929
+ var offsetTop = offset.top
1930
+ var offsetBottom = offset.bottom
1931
+
1932
+ if (typeof offset != 'object') offsetBottom = offsetTop = offset
1933
+ if (typeof offsetTop == 'function') offsetTop = offset.top()
1934
+ if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()
1935
+
1936
+ var affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ? false :
1937
+ offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :
1938
+ offsetTop != null && (scrollTop <= offsetTop) ? 'top' : false
1939
+
1940
+ if (this.affixed === affix) return
1941
+ if (this.unpin) this.$element.css('top', '')
1942
+
1943
+ this.affixed = affix
1944
+ this.unpin = affix == 'bottom' ? position.top - scrollTop : null
1945
+
1946
+ this.$element.removeClass(Affix.RESET).addClass('affix' + (affix ? '-' + affix : ''))
1947
+
1948
+ if (affix == 'bottom') {
1949
+ this.$element.offset({ top: document.body.offsetHeight - offsetBottom - this.$element.height() })
1950
+ }
1951
+ }
1952
+
1953
+
1954
+ // AFFIX PLUGIN DEFINITION
1955
+ // =======================
1956
+
1957
+ var old = $.fn.affix
1958
+
1959
+ $.fn.affix = function (option) {
1960
+ return this.each(function () {
1961
+ var $this = $(this)
1962
+ var data = $this.data('bs.affix')
1963
+ var options = typeof option == 'object' && option
1964
+
1965
+ if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
1966
+ if (typeof option == 'string') data[option]()
1967
+ })
1968
+ }
1969
+
1970
+ $.fn.affix.Constructor = Affix
1971
+
1972
+
1973
+ // AFFIX NO CONFLICT
1974
+ // =================
1975
+
1976
+ $.fn.affix.noConflict = function () {
1977
+ $.fn.affix = old
1978
+ return this
1979
+ }
1980
+
1981
+
1982
+ // AFFIX DATA-API
1983
+ // ==============
1984
+
1985
+ $(window).on('load', function () {
1986
+ $('[data-spy="affix"]').each(function () {
1987
+ var $spy = $(this)
1988
+ var data = $spy.data()
1989
+
1990
+ data.offset = data.offset || {}
1991
+
1992
+ if (data.offsetBottom) data.offset.bottom = data.offsetBottom
1993
+ if (data.offsetTop) data.offset.top = data.offsetTop
1994
+
1995
+ $spy.affix(data)
1996
+ })
1997
+ })
1998
+
1999
+ }(window.jQuery);