hanami-bootstrap 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cd9467b8c450c8f0669d176372f3aead56bd304c
4
+ data.tar.gz: 1e3e5b5191121cbae6a44d1e01b0fe305710178f
5
+ SHA512:
6
+ metadata.gz: b1bdc2abd32d09ebe3d8aac68707307f63d60c99e40d5e665786bcb619069cef8e18f30050d9289a9bbe58c91564fee61db89f9f5cccc828c74d50f877480786
7
+ data.tar.gz: 4c553f021475a1971453b9b2a2ff8597635f3608b8ba80f70eaff01a74c5c712585dd43c7e85fa21c3022788e09b3940b36a32731d64171bcebe0f6d38c007cd
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.2
4
+ before_install: gem install bundler -v 1.11.2
@@ -0,0 +1,49 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all people who
5
+ contribute through reporting issues, posting feature requests, updating
6
+ documentation, submitting pull requests or patches, and other activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This code of conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting a project maintainer at antondavydov.o@gmail.com. All
39
+ complaints will be reviewed and investigated and will result in a response that
40
+ is deemed necessary and appropriate to the circumstances. Maintainers are
41
+ obligated to maintain confidentiality with regard to the reporter of an
42
+ incident.
43
+
44
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
45
+ version 1.3.0, available at
46
+ [http://contributor-covenant.org/version/1/3/0/][version]
47
+
48
+ [homepage]: http://contributor-covenant.org
49
+ [version]: http://contributor-covenant.org/version/1/3/0/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in hanami-bootstrap.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Anton Davydov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,38 @@
1
+ # Hanami::Bootstrap
2
+ [Bootstrap](http://getbootstrap.com/) wrapper for [hanami](http://hanamirb.org/) framework.
3
+ This wrapper provide HEAD version of bootstrap.
4
+
5
+ Also you can use [bootstrap-rubygem](https://github.com/twbs/bootstrap-rubygem) gem which support hanami framework.
6
+
7
+ ## Installation
8
+ **Important:** this wrapper required jquery library.
9
+ You can use [jquery-lotus](https://github.com/Nerian/jquery-lotus) gem or add jquery.js to you assets directory.
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ``` ruby
14
+ gem 'hanami-bootstrap'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install hanami-bootstrap
24
+
25
+ ## Usage
26
+ Add bootstrap to your template:
27
+
28
+ ``` erb
29
+ <%= stylesheet 'bootstrap' %>
30
+ <%= javascript 'bootstrap' %>
31
+ ```
32
+
33
+ ## Contributing
34
+ Bug reports and pull requests are welcome on GitHub at https://github.com/davydovanton/hanami-bootstrap. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
35
+
36
+
37
+ ## License
38
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :spec
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'hanami/bootstrap/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "hanami-bootstrap"
8
+ spec.version = Hanami::Bootstrap::VERSION
9
+ spec.authors = ["Anton Davydov"]
10
+ spec.email = ["antondavydov.o@gmail.com"]
11
+
12
+ spec.summary = %q{Twitter bootstrap library for hanami applications}
13
+ spec.description = %q{Twitter bootstrap library for hanami applications}
14
+ spec.homepage = "https://github.com/davydovanton/hanami-bootstrap"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_dependency "hanami-assets", "~> 0.2.1"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.11"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "minitest", "~> 5.0"
27
+ end
@@ -0,0 +1,22 @@
1
+ require 'hanami/bootstrap/version'
2
+ require 'hanami/assets'
3
+
4
+ module Hanami
5
+ module Bootstrap
6
+ class << self
7
+ def load!
8
+ ::Hanami::Assets.sources << assets_path
9
+ end
10
+
11
+ def gem_path
12
+ @gem_path ||= File.expand_path '../..', File.dirname(__FILE__)
13
+ end
14
+
15
+ def assets_path
16
+ @assets_path ||= File.join gem_path, 'vendor', 'assets'
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ Hanami::Bootstrap.load!
@@ -0,0 +1,5 @@
1
+ module Hanami
2
+ module Bootstrap
3
+ VERSION = '0.2.0'
4
+ end
5
+ end
@@ -0,0 +1,2365 @@
1
+ /*!
2
+ * Bootstrap v3.3.6 (http://getbootstrap.com)
3
+ * Copyright 2011-2016 Twitter, Inc.
4
+ * Licensed under the MIT license
5
+ */
6
+
7
+ if (typeof jQuery === 'undefined') {
8
+ throw new Error('Bootstrap\'s JavaScript requires jQuery')
9
+ }
10
+
11
+ +function ($) {
12
+ 'use strict';
13
+ var version = $.fn.jquery.split(' ')[0].split('.')
14
+ if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 2)) {
15
+ throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 3')
16
+ }
17
+ }(jQuery);
18
+
19
+ /* ========================================================================
20
+ * Bootstrap: transition.js v3.3.6
21
+ * http://getbootstrap.com/javascript/#transitions
22
+ * ========================================================================
23
+ * Copyright 2011-2016 Twitter, Inc.
24
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
25
+ * ======================================================================== */
26
+
27
+
28
+ +function ($) {
29
+ 'use strict';
30
+
31
+ // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
32
+ // ============================================================
33
+
34
+ function transitionEnd() {
35
+ var el = document.createElement('bootstrap')
36
+
37
+ var transEndEventNames = {
38
+ WebkitTransition : 'webkitTransitionEnd',
39
+ MozTransition : 'transitionend',
40
+ OTransition : 'oTransitionEnd otransitionend',
41
+ transition : 'transitionend'
42
+ }
43
+
44
+ for (var name in transEndEventNames) {
45
+ if (el.style[name] !== undefined) {
46
+ return { end: transEndEventNames[name] }
47
+ }
48
+ }
49
+
50
+ return false // explicit for ie8 ( ._.)
51
+ }
52
+
53
+ // http://blog.alexmaccaw.com/css-transitions
54
+ $.fn.emulateTransitionEnd = function (duration) {
55
+ var called = false
56
+ var $el = this
57
+ $(this).one('bsTransitionEnd', function () { called = true })
58
+ var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
59
+ setTimeout(callback, duration)
60
+ return this
61
+ }
62
+
63
+ $(function () {
64
+ $.support.transition = transitionEnd()
65
+
66
+ if (!$.support.transition) return
67
+
68
+ $.event.special.bsTransitionEnd = {
69
+ bindType: $.support.transition.end,
70
+ delegateType: $.support.transition.end,
71
+ handle: function (e) {
72
+ if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
73
+ }
74
+ }
75
+ })
76
+
77
+ }(jQuery);
78
+
79
+ /* ========================================================================
80
+ * Bootstrap: alert.js v3.3.6
81
+ * http://getbootstrap.com/javascript/#alerts
82
+ * ========================================================================
83
+ * Copyright 2011-2016 Twitter, Inc.
84
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
85
+ * ======================================================================== */
86
+
87
+
88
+ +function ($) {
89
+ 'use strict';
90
+
91
+ // ALERT CLASS DEFINITION
92
+ // ======================
93
+
94
+ var dismiss = '[data-dismiss="alert"]'
95
+ var Alert = function (el) {
96
+ $(el).on('click', dismiss, this.close)
97
+ }
98
+
99
+ Alert.VERSION = '3.3.6'
100
+
101
+ Alert.TRANSITION_DURATION = 150
102
+
103
+ Alert.prototype.close = function (e) {
104
+ var $this = $(this)
105
+ var selector = $this.attr('data-target')
106
+
107
+ if (!selector) {
108
+ selector = $this.attr('href')
109
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
110
+ }
111
+
112
+ var $parent = $(selector)
113
+
114
+ if (e) e.preventDefault()
115
+
116
+ if (!$parent.length) {
117
+ $parent = $this.closest('.alert')
118
+ }
119
+
120
+ $parent.trigger(e = $.Event('close.bs.alert'))
121
+
122
+ if (e.isDefaultPrevented()) return
123
+
124
+ $parent.removeClass('in')
125
+
126
+ function removeElement() {
127
+ // detach from parent, fire event then clean up data
128
+ $parent.detach().trigger('closed.bs.alert').remove()
129
+ }
130
+
131
+ $.support.transition && $parent.hasClass('fade') ?
132
+ $parent
133
+ .one('bsTransitionEnd', removeElement)
134
+ .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
135
+ removeElement()
136
+ }
137
+
138
+
139
+ // ALERT PLUGIN DEFINITION
140
+ // =======================
141
+
142
+ function Plugin(option) {
143
+ return this.each(function () {
144
+ var $this = $(this)
145
+ var data = $this.data('bs.alert')
146
+
147
+ if (!data) $this.data('bs.alert', (data = new Alert(this)))
148
+ if (typeof option == 'string') data[option].call($this)
149
+ })
150
+ }
151
+
152
+ var old = $.fn.alert
153
+
154
+ $.fn.alert = Plugin
155
+ $.fn.alert.Constructor = Alert
156
+
157
+
158
+ // ALERT NO CONFLICT
159
+ // =================
160
+
161
+ $.fn.alert.noConflict = function () {
162
+ $.fn.alert = old
163
+ return this
164
+ }
165
+
166
+
167
+ // ALERT DATA-API
168
+ // ==============
169
+
170
+ $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
171
+
172
+ }(jQuery);
173
+
174
+ /* ========================================================================
175
+ * Bootstrap: button.js v3.3.6
176
+ * http://getbootstrap.com/javascript/#buttons
177
+ * ========================================================================
178
+ * Copyright 2011-2016 Twitter, Inc.
179
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
180
+ * ======================================================================== */
181
+
182
+
183
+ +function ($) {
184
+ '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
+ this.isLoading = false
193
+ }
194
+
195
+ Button.VERSION = '3.3.6'
196
+
197
+ Button.DEFAULTS = {
198
+ loadingText: 'loading...'
199
+ }
200
+
201
+ Button.prototype.setState = function (state) {
202
+ var d = 'disabled'
203
+ var $el = this.$element
204
+ var val = $el.is('input') ? 'val' : 'html'
205
+ var data = $el.data()
206
+
207
+ state += 'Text'
208
+
209
+ if (data.resetText == null) $el.data('resetText', $el[val]())
210
+
211
+ // push to event loop to allow forms to submit
212
+ setTimeout($.proxy(function () {
213
+ $el[val](data[state] == null ? this.options[state] : data[state])
214
+
215
+ if (state == 'loadingText') {
216
+ this.isLoading = true
217
+ $el.addClass(d).attr(d, d)
218
+ } else if (this.isLoading) {
219
+ this.isLoading = false
220
+ $el.removeClass(d).removeAttr(d)
221
+ }
222
+ }, this), 0)
223
+ }
224
+
225
+ Button.prototype.toggle = function () {
226
+ var changed = true
227
+ var $parent = this.$element.closest('[data-toggle="buttons"]')
228
+
229
+ if ($parent.length) {
230
+ var $input = this.$element.find('input')
231
+ if ($input.prop('type') == 'radio') {
232
+ if ($input.prop('checked')) changed = false
233
+ $parent.find('.active').removeClass('active')
234
+ this.$element.addClass('active')
235
+ } else if ($input.prop('type') == 'checkbox') {
236
+ if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false
237
+ this.$element.toggleClass('active')
238
+ }
239
+ $input.prop('checked', this.$element.hasClass('active'))
240
+ if (changed) $input.trigger('change')
241
+ } else {
242
+ this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
243
+ this.$element.toggleClass('active')
244
+ }
245
+ }
246
+
247
+
248
+ // BUTTON PLUGIN DEFINITION
249
+ // ========================
250
+
251
+ function Plugin(option) {
252
+ return this.each(function () {
253
+ var $this = $(this)
254
+ var data = $this.data('bs.button')
255
+ var options = typeof option == 'object' && option
256
+
257
+ if (!data) $this.data('bs.button', (data = new Button(this, options)))
258
+
259
+ if (option == 'toggle') data.toggle()
260
+ else if (option) data.setState(option)
261
+ })
262
+ }
263
+
264
+ var old = $.fn.button
265
+
266
+ $.fn.button = Plugin
267
+ $.fn.button.Constructor = Button
268
+
269
+
270
+ // BUTTON NO CONFLICT
271
+ // ==================
272
+
273
+ $.fn.button.noConflict = function () {
274
+ $.fn.button = old
275
+ return this
276
+ }
277
+
278
+
279
+ // BUTTON DATA-API
280
+ // ===============
281
+
282
+ $(document)
283
+ .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
284
+ var $btn = $(e.target)
285
+ if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
286
+ Plugin.call($btn, 'toggle')
287
+ if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault()
288
+ })
289
+ .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
290
+ $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
291
+ })
292
+
293
+ }(jQuery);
294
+
295
+ /* ========================================================================
296
+ * Bootstrap: carousel.js v3.3.6
297
+ * http://getbootstrap.com/javascript/#carousel
298
+ * ========================================================================
299
+ * Copyright 2011-2016 Twitter, Inc.
300
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
301
+ * ======================================================================== */
302
+
303
+
304
+ +function ($) {
305
+ 'use strict';
306
+
307
+ // CAROUSEL CLASS DEFINITION
308
+ // =========================
309
+
310
+ var Carousel = function (element, options) {
311
+ this.$element = $(element)
312
+ this.$indicators = this.$element.find('.carousel-indicators')
313
+ this.options = options
314
+ this.paused = null
315
+ this.sliding = null
316
+ this.interval = null
317
+ this.$active = null
318
+ this.$items = null
319
+
320
+ this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
321
+
322
+ this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
323
+ .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
324
+ .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
325
+ }
326
+
327
+ Carousel.VERSION = '3.3.6'
328
+
329
+ Carousel.TRANSITION_DURATION = 600
330
+
331
+ Carousel.DEFAULTS = {
332
+ interval: 5000,
333
+ pause: 'hover',
334
+ wrap: true,
335
+ keyboard: true
336
+ }
337
+
338
+ Carousel.prototype.keydown = function (e) {
339
+ if (/input|textarea/i.test(e.target.tagName)) return
340
+ switch (e.which) {
341
+ case 37: this.prev(); break
342
+ case 39: this.next(); break
343
+ default: return
344
+ }
345
+
346
+ e.preventDefault()
347
+ }
348
+
349
+ Carousel.prototype.cycle = function (e) {
350
+ e || (this.paused = false)
351
+
352
+ this.interval && clearInterval(this.interval)
353
+
354
+ this.options.interval
355
+ && !this.paused
356
+ && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
357
+
358
+ return this
359
+ }
360
+
361
+ Carousel.prototype.getItemIndex = function (item) {
362
+ this.$items = item.parent().children('.item')
363
+ return this.$items.index(item || this.$active)
364
+ }
365
+
366
+ Carousel.prototype.getItemForDirection = function (direction, active) {
367
+ var activeIndex = this.getItemIndex(active)
368
+ var willWrap = (direction == 'prev' && activeIndex === 0)
369
+ || (direction == 'next' && activeIndex == (this.$items.length - 1))
370
+ if (willWrap && !this.options.wrap) return active
371
+ var delta = direction == 'prev' ? -1 : 1
372
+ var itemIndex = (activeIndex + delta) % this.$items.length
373
+ return this.$items.eq(itemIndex)
374
+ }
375
+
376
+ Carousel.prototype.to = function (pos) {
377
+ var that = this
378
+ var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
379
+
380
+ if (pos > (this.$items.length - 1) || pos < 0) return
381
+
382
+ if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
383
+ if (activeIndex == pos) return this.pause().cycle()
384
+
385
+ return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
386
+ }
387
+
388
+ Carousel.prototype.pause = function (e) {
389
+ e || (this.paused = true)
390
+
391
+ if (this.$element.find('.next, .prev').length && $.support.transition) {
392
+ this.$element.trigger($.support.transition.end)
393
+ this.cycle(true)
394
+ }
395
+
396
+ this.interval = clearInterval(this.interval)
397
+
398
+ return this
399
+ }
400
+
401
+ Carousel.prototype.next = function () {
402
+ if (this.sliding) return
403
+ return this.slide('next')
404
+ }
405
+
406
+ Carousel.prototype.prev = function () {
407
+ if (this.sliding) return
408
+ return this.slide('prev')
409
+ }
410
+
411
+ Carousel.prototype.slide = function (type, next) {
412
+ var $active = this.$element.find('.item.active')
413
+ var $next = next || this.getItemForDirection(type, $active)
414
+ var isCycling = this.interval
415
+ var direction = type == 'next' ? 'left' : 'right'
416
+ var that = this
417
+
418
+ if ($next.hasClass('active')) return (this.sliding = false)
419
+
420
+ var relatedTarget = $next[0]
421
+ var slideEvent = $.Event('slide.bs.carousel', {
422
+ relatedTarget: relatedTarget,
423
+ direction: direction
424
+ })
425
+ this.$element.trigger(slideEvent)
426
+ if (slideEvent.isDefaultPrevented()) return
427
+
428
+ this.sliding = true
429
+
430
+ isCycling && this.pause()
431
+
432
+ if (this.$indicators.length) {
433
+ this.$indicators.find('.active').removeClass('active')
434
+ var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
435
+ $nextIndicator && $nextIndicator.addClass('active')
436
+ }
437
+
438
+ var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
439
+ if ($.support.transition && this.$element.hasClass('slide')) {
440
+ $next.addClass(type)
441
+ $next[0].offsetWidth // force reflow
442
+ $active.addClass(direction)
443
+ $next.addClass(direction)
444
+ $active
445
+ .one('bsTransitionEnd', function () {
446
+ $next.removeClass([type, direction].join(' ')).addClass('active')
447
+ $active.removeClass(['active', direction].join(' '))
448
+ that.sliding = false
449
+ setTimeout(function () {
450
+ that.$element.trigger(slidEvent)
451
+ }, 0)
452
+ })
453
+ .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
454
+ } else {
455
+ $active.removeClass('active')
456
+ $next.addClass('active')
457
+ this.sliding = false
458
+ this.$element.trigger(slidEvent)
459
+ }
460
+
461
+ isCycling && this.cycle()
462
+
463
+ return this
464
+ }
465
+
466
+
467
+ // CAROUSEL PLUGIN DEFINITION
468
+ // ==========================
469
+
470
+ function Plugin(option) {
471
+ return this.each(function () {
472
+ var $this = $(this)
473
+ var data = $this.data('bs.carousel')
474
+ var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
475
+ var action = typeof option == 'string' ? option : options.slide
476
+
477
+ if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
478
+ if (typeof option == 'number') data.to(option)
479
+ else if (action) data[action]()
480
+ else if (options.interval) data.pause().cycle()
481
+ })
482
+ }
483
+
484
+ var old = $.fn.carousel
485
+
486
+ $.fn.carousel = Plugin
487
+ $.fn.carousel.Constructor = Carousel
488
+
489
+
490
+ // CAROUSEL NO CONFLICT
491
+ // ====================
492
+
493
+ $.fn.carousel.noConflict = function () {
494
+ $.fn.carousel = old
495
+ return this
496
+ }
497
+
498
+
499
+ // CAROUSEL DATA-API
500
+ // =================
501
+
502
+ var clickHandler = function (e) {
503
+ var href
504
+ var $this = $(this)
505
+ var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
506
+ if (!$target.hasClass('carousel')) return
507
+ var options = $.extend({}, $target.data(), $this.data())
508
+ var slideIndex = $this.attr('data-slide-to')
509
+ if (slideIndex) options.interval = false
510
+
511
+ Plugin.call($target, options)
512
+
513
+ if (slideIndex) {
514
+ $target.data('bs.carousel').to(slideIndex)
515
+ }
516
+
517
+ e.preventDefault()
518
+ }
519
+
520
+ $(document)
521
+ .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
522
+ .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
523
+
524
+ $(window).on('load', function () {
525
+ $('[data-ride="carousel"]').each(function () {
526
+ var $carousel = $(this)
527
+ Plugin.call($carousel, $carousel.data())
528
+ })
529
+ })
530
+
531
+ }(jQuery);
532
+
533
+ /* ========================================================================
534
+ * Bootstrap: collapse.js v3.3.6
535
+ * http://getbootstrap.com/javascript/#collapse
536
+ * ========================================================================
537
+ * Copyright 2011-2016 Twitter, Inc.
538
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
539
+ * ======================================================================== */
540
+
541
+
542
+ +function ($) {
543
+ 'use strict';
544
+
545
+ // COLLAPSE PUBLIC CLASS DEFINITION
546
+ // ================================
547
+
548
+ var Collapse = function (element, options) {
549
+ this.$element = $(element)
550
+ this.options = $.extend({}, Collapse.DEFAULTS, options)
551
+ this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
552
+ '[data-toggle="collapse"][data-target="#' + element.id + '"]')
553
+ this.transitioning = null
554
+
555
+ if (this.options.parent) {
556
+ this.$parent = this.getParent()
557
+ } else {
558
+ this.addAriaAndCollapsedClass(this.$element, this.$trigger)
559
+ }
560
+
561
+ if (this.options.toggle) this.toggle()
562
+ }
563
+
564
+ Collapse.VERSION = '3.3.6'
565
+
566
+ Collapse.TRANSITION_DURATION = 350
567
+
568
+ Collapse.DEFAULTS = {
569
+ toggle: true
570
+ }
571
+
572
+ Collapse.prototype.dimension = function () {
573
+ var hasWidth = this.$element.hasClass('width')
574
+ return hasWidth ? 'width' : 'height'
575
+ }
576
+
577
+ Collapse.prototype.show = function () {
578
+ if (this.transitioning || this.$element.hasClass('in')) return
579
+
580
+ var activesData
581
+ var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
582
+
583
+ if (actives && actives.length) {
584
+ activesData = actives.data('bs.collapse')
585
+ if (activesData && activesData.transitioning) return
586
+ }
587
+
588
+ var startEvent = $.Event('show.bs.collapse')
589
+ this.$element.trigger(startEvent)
590
+ if (startEvent.isDefaultPrevented()) return
591
+
592
+ if (actives && actives.length) {
593
+ Plugin.call(actives, 'hide')
594
+ activesData || actives.data('bs.collapse', null)
595
+ }
596
+
597
+ var dimension = this.dimension()
598
+
599
+ this.$element
600
+ .removeClass('collapse')
601
+ .addClass('collapsing')[dimension](0)
602
+ .attr('aria-expanded', true)
603
+
604
+ this.$trigger
605
+ .removeClass('collapsed')
606
+ .attr('aria-expanded', true)
607
+
608
+ this.transitioning = 1
609
+
610
+ var complete = function () {
611
+ this.$element
612
+ .removeClass('collapsing')
613
+ .addClass('collapse in')[dimension]('')
614
+ this.transitioning = 0
615
+ this.$element
616
+ .trigger('shown.bs.collapse')
617
+ }
618
+
619
+ if (!$.support.transition) return complete.call(this)
620
+
621
+ var scrollSize = $.camelCase(['scroll', dimension].join('-'))
622
+
623
+ this.$element
624
+ .one('bsTransitionEnd', $.proxy(complete, this))
625
+ .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
626
+ }
627
+
628
+ Collapse.prototype.hide = function () {
629
+ if (this.transitioning || !this.$element.hasClass('in')) return
630
+
631
+ var startEvent = $.Event('hide.bs.collapse')
632
+ this.$element.trigger(startEvent)
633
+ if (startEvent.isDefaultPrevented()) return
634
+
635
+ var dimension = this.dimension()
636
+
637
+ this.$element[dimension](this.$element[dimension]())[0].offsetHeight
638
+
639
+ this.$element
640
+ .addClass('collapsing')
641
+ .removeClass('collapse in')
642
+ .attr('aria-expanded', false)
643
+
644
+ this.$trigger
645
+ .addClass('collapsed')
646
+ .attr('aria-expanded', false)
647
+
648
+ this.transitioning = 1
649
+
650
+ var complete = function () {
651
+ this.transitioning = 0
652
+ this.$element
653
+ .removeClass('collapsing')
654
+ .addClass('collapse')
655
+ .trigger('hidden.bs.collapse')
656
+ }
657
+
658
+ if (!$.support.transition) return complete.call(this)
659
+
660
+ this.$element
661
+ [dimension](0)
662
+ .one('bsTransitionEnd', $.proxy(complete, this))
663
+ .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
664
+ }
665
+
666
+ Collapse.prototype.toggle = function () {
667
+ this[this.$element.hasClass('in') ? 'hide' : 'show']()
668
+ }
669
+
670
+ Collapse.prototype.getParent = function () {
671
+ return $(this.options.parent)
672
+ .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
673
+ .each($.proxy(function (i, element) {
674
+ var $element = $(element)
675
+ this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
676
+ }, this))
677
+ .end()
678
+ }
679
+
680
+ Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
681
+ var isOpen = $element.hasClass('in')
682
+
683
+ $element.attr('aria-expanded', isOpen)
684
+ $trigger
685
+ .toggleClass('collapsed', !isOpen)
686
+ .attr('aria-expanded', isOpen)
687
+ }
688
+
689
+ function getTargetFromTrigger($trigger) {
690
+ var href
691
+ var target = $trigger.attr('data-target')
692
+ || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
693
+
694
+ return $(target)
695
+ }
696
+
697
+
698
+ // COLLAPSE PLUGIN DEFINITION
699
+ // ==========================
700
+
701
+ function Plugin(option) {
702
+ return this.each(function () {
703
+ var $this = $(this)
704
+ var data = $this.data('bs.collapse')
705
+ var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
706
+
707
+ if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
708
+ if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
709
+ if (typeof option == 'string') data[option]()
710
+ })
711
+ }
712
+
713
+ var old = $.fn.collapse
714
+
715
+ $.fn.collapse = Plugin
716
+ $.fn.collapse.Constructor = Collapse
717
+
718
+
719
+ // COLLAPSE NO CONFLICT
720
+ // ====================
721
+
722
+ $.fn.collapse.noConflict = function () {
723
+ $.fn.collapse = old
724
+ return this
725
+ }
726
+
727
+
728
+ // COLLAPSE DATA-API
729
+ // =================
730
+
731
+ $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
732
+ var $this = $(this)
733
+
734
+ if (!$this.attr('data-target')) e.preventDefault()
735
+
736
+ var $target = getTargetFromTrigger($this)
737
+ var data = $target.data('bs.collapse')
738
+ var option = data ? 'toggle' : $this.data()
739
+
740
+ Plugin.call($target, option)
741
+ })
742
+
743
+ }(jQuery);
744
+
745
+ /* ========================================================================
746
+ * Bootstrap: dropdown.js v3.3.6
747
+ * http://getbootstrap.com/javascript/#dropdowns
748
+ * ========================================================================
749
+ * Copyright 2011-2016 Twitter, Inc.
750
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
751
+ * ======================================================================== */
752
+
753
+
754
+ +function ($) {
755
+ 'use strict';
756
+
757
+ // DROPDOWN CLASS DEFINITION
758
+ // =========================
759
+
760
+ var backdrop = '.dropdown-backdrop'
761
+ var toggle = '[data-toggle="dropdown"]'
762
+ var Dropdown = function (element) {
763
+ $(element).on('click.bs.dropdown', this.toggle)
764
+ }
765
+
766
+ Dropdown.VERSION = '3.3.6'
767
+
768
+ function getParent($this) {
769
+ var selector = $this.attr('data-target')
770
+
771
+ if (!selector) {
772
+ selector = $this.attr('href')
773
+ selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
774
+ }
775
+
776
+ var $parent = selector && $(selector)
777
+
778
+ return $parent && $parent.length ? $parent : $this.parent()
779
+ }
780
+
781
+ function clearMenus(e) {
782
+ if (e && e.which === 3) return
783
+ $(backdrop).remove()
784
+ $(toggle).each(function () {
785
+ var $this = $(this)
786
+ var $parent = getParent($this)
787
+ var relatedTarget = { relatedTarget: this }
788
+
789
+ if (!$parent.hasClass('open')) return
790
+
791
+ if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
792
+
793
+ $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
794
+
795
+ if (e.isDefaultPrevented()) return
796
+
797
+ $this.attr('aria-expanded', 'false')
798
+ $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget))
799
+ })
800
+ }
801
+
802
+ Dropdown.prototype.toggle = function (e) {
803
+ var $this = $(this)
804
+
805
+ if ($this.is('.disabled, :disabled')) return
806
+
807
+ var $parent = getParent($this)
808
+ var isActive = $parent.hasClass('open')
809
+
810
+ clearMenus()
811
+
812
+ if (!isActive) {
813
+ if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
814
+ // if mobile we use a backdrop because click events don't delegate
815
+ $(document.createElement('div'))
816
+ .addClass('dropdown-backdrop')
817
+ .insertAfter($(this))
818
+ .on('click', clearMenus)
819
+ }
820
+
821
+ var relatedTarget = { relatedTarget: this }
822
+ $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
823
+
824
+ if (e.isDefaultPrevented()) return
825
+
826
+ $this
827
+ .trigger('focus')
828
+ .attr('aria-expanded', 'true')
829
+
830
+ $parent
831
+ .toggleClass('open')
832
+ .trigger($.Event('shown.bs.dropdown', relatedTarget))
833
+ }
834
+
835
+ return false
836
+ }
837
+
838
+ Dropdown.prototype.keydown = function (e) {
839
+ if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
840
+
841
+ var $this = $(this)
842
+
843
+ e.preventDefault()
844
+ e.stopPropagation()
845
+
846
+ if ($this.is('.disabled, :disabled')) return
847
+
848
+ var $parent = getParent($this)
849
+ var isActive = $parent.hasClass('open')
850
+
851
+ if (!isActive && e.which != 27 || isActive && e.which == 27) {
852
+ if (e.which == 27) $parent.find(toggle).trigger('focus')
853
+ return $this.trigger('click')
854
+ }
855
+
856
+ var desc = ' li:not(.disabled):visible a'
857
+ var $items = $parent.find('.dropdown-menu' + desc)
858
+
859
+ if (!$items.length) return
860
+
861
+ var index = $items.index(e.target)
862
+
863
+ if (e.which == 38 && index > 0) index-- // up
864
+ if (e.which == 40 && index < $items.length - 1) index++ // down
865
+ if (!~index) index = 0
866
+
867
+ $items.eq(index).trigger('focus')
868
+ }
869
+
870
+
871
+ // DROPDOWN PLUGIN DEFINITION
872
+ // ==========================
873
+
874
+ function Plugin(option) {
875
+ return this.each(function () {
876
+ var $this = $(this)
877
+ var data = $this.data('bs.dropdown')
878
+
879
+ if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
880
+ if (typeof option == 'string') data[option].call($this)
881
+ })
882
+ }
883
+
884
+ var old = $.fn.dropdown
885
+
886
+ $.fn.dropdown = Plugin
887
+ $.fn.dropdown.Constructor = Dropdown
888
+
889
+
890
+ // DROPDOWN NO CONFLICT
891
+ // ====================
892
+
893
+ $.fn.dropdown.noConflict = function () {
894
+ $.fn.dropdown = old
895
+ return this
896
+ }
897
+
898
+
899
+ // APPLY TO STANDARD DROPDOWN ELEMENTS
900
+ // ===================================
901
+
902
+ $(document)
903
+ .on('click.bs.dropdown.data-api', clearMenus)
904
+ .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
905
+ .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
906
+ .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
907
+ .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
908
+
909
+ }(jQuery);
910
+
911
+ /* ========================================================================
912
+ * Bootstrap: modal.js v3.3.6
913
+ * http://getbootstrap.com/javascript/#modals
914
+ * ========================================================================
915
+ * Copyright 2011-2016 Twitter, Inc.
916
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
917
+ * ======================================================================== */
918
+
919
+
920
+ +function ($) {
921
+ 'use strict';
922
+
923
+ // MODAL CLASS DEFINITION
924
+ // ======================
925
+
926
+ var Modal = function (element, options) {
927
+ this.options = options
928
+ this.$body = $(document.body)
929
+ this.$element = $(element)
930
+ this.$dialog = this.$element.find('.modal-dialog')
931
+ this.$backdrop = null
932
+ this.isShown = null
933
+ this.originalBodyPad = null
934
+ this.scrollbarWidth = 0
935
+ this.ignoreBackdropClick = false
936
+
937
+ if (this.options.remote) {
938
+ this.$element
939
+ .find('.modal-content')
940
+ .load(this.options.remote, $.proxy(function () {
941
+ this.$element.trigger('loaded.bs.modal')
942
+ }, this))
943
+ }
944
+ }
945
+
946
+ Modal.VERSION = '3.3.6'
947
+
948
+ Modal.TRANSITION_DURATION = 300
949
+ Modal.BACKDROP_TRANSITION_DURATION = 150
950
+
951
+ Modal.DEFAULTS = {
952
+ backdrop: true,
953
+ keyboard: true,
954
+ show: true
955
+ }
956
+
957
+ Modal.prototype.toggle = function (_relatedTarget) {
958
+ return this.isShown ? this.hide() : this.show(_relatedTarget)
959
+ }
960
+
961
+ Modal.prototype.show = function (_relatedTarget) {
962
+ var that = this
963
+ var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
964
+
965
+ this.$element.trigger(e)
966
+
967
+ if (this.isShown || e.isDefaultPrevented()) return
968
+
969
+ this.isShown = true
970
+
971
+ this.checkScrollbar()
972
+ this.setScrollbar()
973
+ this.$body.addClass('modal-open')
974
+
975
+ this.escape()
976
+ this.resize()
977
+
978
+ this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
979
+
980
+ this.$dialog.on('mousedown.dismiss.bs.modal', function () {
981
+ that.$element.one('mouseup.dismiss.bs.modal', function (e) {
982
+ if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true
983
+ })
984
+ })
985
+
986
+ this.backdrop(function () {
987
+ var transition = $.support.transition && that.$element.hasClass('fade')
988
+
989
+ if (!that.$element.parent().length) {
990
+ that.$element.appendTo(that.$body) // don't move modals dom position
991
+ }
992
+
993
+ that.$element
994
+ .show()
995
+ .scrollTop(0)
996
+
997
+ that.adjustDialog()
998
+
999
+ if (transition) {
1000
+ that.$element[0].offsetWidth // force reflow
1001
+ }
1002
+
1003
+ that.$element.addClass('in')
1004
+
1005
+ that.enforceFocus()
1006
+
1007
+ var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
1008
+
1009
+ transition ?
1010
+ that.$dialog // wait for modal to slide in
1011
+ .one('bsTransitionEnd', function () {
1012
+ that.$element.trigger('focus').trigger(e)
1013
+ })
1014
+ .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
1015
+ that.$element.trigger('focus').trigger(e)
1016
+ })
1017
+ }
1018
+
1019
+ Modal.prototype.hide = function (e) {
1020
+ if (e) e.preventDefault()
1021
+
1022
+ e = $.Event('hide.bs.modal')
1023
+
1024
+ this.$element.trigger(e)
1025
+
1026
+ if (!this.isShown || e.isDefaultPrevented()) return
1027
+
1028
+ this.isShown = false
1029
+
1030
+ this.escape()
1031
+ this.resize()
1032
+
1033
+ $(document).off('focusin.bs.modal')
1034
+
1035
+ this.$element
1036
+ .removeClass('in')
1037
+ .off('click.dismiss.bs.modal')
1038
+ .off('mouseup.dismiss.bs.modal')
1039
+
1040
+ this.$dialog.off('mousedown.dismiss.bs.modal')
1041
+
1042
+ $.support.transition && this.$element.hasClass('fade') ?
1043
+ this.$element
1044
+ .one('bsTransitionEnd', $.proxy(this.hideModal, this))
1045
+ .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
1046
+ this.hideModal()
1047
+ }
1048
+
1049
+ Modal.prototype.enforceFocus = function () {
1050
+ $(document)
1051
+ .off('focusin.bs.modal') // guard against infinite focus loop
1052
+ .on('focusin.bs.modal', $.proxy(function (e) {
1053
+ if (document !== event.target &&
1054
+ this.$element[0] !== e.target &&
1055
+ !this.$element.has(e.target).length) {
1056
+ this.$element.trigger('focus')
1057
+ }
1058
+ }, this))
1059
+ }
1060
+
1061
+ Modal.prototype.escape = function () {
1062
+ if (this.isShown && this.options.keyboard) {
1063
+ this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
1064
+ e.which == 27 && this.hide()
1065
+ }, this))
1066
+ } else if (!this.isShown) {
1067
+ this.$element.off('keydown.dismiss.bs.modal')
1068
+ }
1069
+ }
1070
+
1071
+ Modal.prototype.resize = function () {
1072
+ if (this.isShown) {
1073
+ $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
1074
+ } else {
1075
+ $(window).off('resize.bs.modal')
1076
+ }
1077
+ }
1078
+
1079
+ Modal.prototype.hideModal = function () {
1080
+ var that = this
1081
+ this.$element.hide()
1082
+ this.backdrop(function () {
1083
+ that.$body.removeClass('modal-open')
1084
+ that.resetAdjustments()
1085
+ that.resetScrollbar()
1086
+ that.$element.trigger('hidden.bs.modal')
1087
+ })
1088
+ }
1089
+
1090
+ Modal.prototype.removeBackdrop = function () {
1091
+ this.$backdrop && this.$backdrop.remove()
1092
+ this.$backdrop = null
1093
+ }
1094
+
1095
+ Modal.prototype.backdrop = function (callback) {
1096
+ var that = this
1097
+ var animate = this.$element.hasClass('fade') ? 'fade' : ''
1098
+
1099
+ if (this.isShown && this.options.backdrop) {
1100
+ var doAnimate = $.support.transition && animate
1101
+
1102
+ this.$backdrop = $(document.createElement('div'))
1103
+ .addClass('modal-backdrop ' + animate)
1104
+ .appendTo(this.$body)
1105
+
1106
+ this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
1107
+ if (this.ignoreBackdropClick) {
1108
+ this.ignoreBackdropClick = false
1109
+ return
1110
+ }
1111
+ if (e.target !== e.currentTarget) return
1112
+ this.options.backdrop == 'static'
1113
+ ? this.$element[0].focus()
1114
+ : this.hide()
1115
+ }, this))
1116
+
1117
+ if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
1118
+
1119
+ this.$backdrop.addClass('in')
1120
+
1121
+ if (!callback) return
1122
+
1123
+ doAnimate ?
1124
+ this.$backdrop
1125
+ .one('bsTransitionEnd', callback)
1126
+ .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
1127
+ callback()
1128
+
1129
+ } else if (!this.isShown && this.$backdrop) {
1130
+ this.$backdrop.removeClass('in')
1131
+
1132
+ var callbackRemove = function () {
1133
+ that.removeBackdrop()
1134
+ callback && callback()
1135
+ }
1136
+ $.support.transition && this.$element.hasClass('fade') ?
1137
+ this.$backdrop
1138
+ .one('bsTransitionEnd', callbackRemove)
1139
+ .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
1140
+ callbackRemove()
1141
+
1142
+ } else if (callback) {
1143
+ callback()
1144
+ }
1145
+ }
1146
+
1147
+ // these following methods are used to handle overflowing modals
1148
+
1149
+ Modal.prototype.handleUpdate = function () {
1150
+ this.adjustDialog()
1151
+ }
1152
+
1153
+ Modal.prototype.adjustDialog = function () {
1154
+ var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
1155
+
1156
+ this.$element.css({
1157
+ paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
1158
+ paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
1159
+ })
1160
+ }
1161
+
1162
+ Modal.prototype.resetAdjustments = function () {
1163
+ this.$element.css({
1164
+ paddingLeft: '',
1165
+ paddingRight: ''
1166
+ })
1167
+ }
1168
+
1169
+ Modal.prototype.checkScrollbar = function () {
1170
+ var fullWindowWidth = window.innerWidth
1171
+ if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
1172
+ var documentElementRect = document.documentElement.getBoundingClientRect()
1173
+ fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)
1174
+ }
1175
+ this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth
1176
+ this.scrollbarWidth = this.measureScrollbar()
1177
+ }
1178
+
1179
+ Modal.prototype.setScrollbar = function () {
1180
+ var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
1181
+ this.originalBodyPad = document.body.style.paddingRight || ''
1182
+ if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
1183
+ }
1184
+
1185
+ Modal.prototype.resetScrollbar = function () {
1186
+ this.$body.css('padding-right', this.originalBodyPad)
1187
+ }
1188
+
1189
+ Modal.prototype.measureScrollbar = function () { // thx walsh
1190
+ var scrollDiv = document.createElement('div')
1191
+ scrollDiv.className = 'modal-scrollbar-measure'
1192
+ this.$body.append(scrollDiv)
1193
+ var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
1194
+ this.$body[0].removeChild(scrollDiv)
1195
+ return scrollbarWidth
1196
+ }
1197
+
1198
+
1199
+ // MODAL PLUGIN DEFINITION
1200
+ // =======================
1201
+
1202
+ function Plugin(option, _relatedTarget) {
1203
+ return this.each(function () {
1204
+ var $this = $(this)
1205
+ var data = $this.data('bs.modal')
1206
+ var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
1207
+
1208
+ if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
1209
+ if (typeof option == 'string') data[option](_relatedTarget)
1210
+ else if (options.show) data.show(_relatedTarget)
1211
+ })
1212
+ }
1213
+
1214
+ var old = $.fn.modal
1215
+
1216
+ $.fn.modal = Plugin
1217
+ $.fn.modal.Constructor = Modal
1218
+
1219
+
1220
+ // MODAL NO CONFLICT
1221
+ // =================
1222
+
1223
+ $.fn.modal.noConflict = function () {
1224
+ $.fn.modal = old
1225
+ return this
1226
+ }
1227
+
1228
+
1229
+ // MODAL DATA-API
1230
+ // ==============
1231
+
1232
+ $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
1233
+ var $this = $(this)
1234
+ var href = $this.attr('href')
1235
+ var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
1236
+ var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
1237
+
1238
+ if ($this.is('a')) e.preventDefault()
1239
+
1240
+ $target.one('show.bs.modal', function (showEvent) {
1241
+ if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
1242
+ $target.one('hidden.bs.modal', function () {
1243
+ $this.is(':visible') && $this.trigger('focus')
1244
+ })
1245
+ })
1246
+ Plugin.call($target, option, this)
1247
+ })
1248
+
1249
+ }(jQuery);
1250
+
1251
+ /* ========================================================================
1252
+ * Bootstrap: tooltip.js v3.3.6
1253
+ * http://getbootstrap.com/javascript/#tooltip
1254
+ * Inspired by the original jQuery.tipsy by Jason Frame
1255
+ * ========================================================================
1256
+ * Copyright 2011-2016 Twitter, Inc.
1257
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1258
+ * ======================================================================== */
1259
+
1260
+
1261
+ +function ($) {
1262
+ 'use strict';
1263
+
1264
+ // TOOLTIP PUBLIC CLASS DEFINITION
1265
+ // ===============================
1266
+
1267
+ var Tooltip = function (element, options) {
1268
+ this.type = null
1269
+ this.options = null
1270
+ this.enabled = null
1271
+ this.timeout = null
1272
+ this.hoverState = null
1273
+ this.$element = null
1274
+ this.inState = null
1275
+
1276
+ this.init('tooltip', element, options)
1277
+ }
1278
+
1279
+ Tooltip.VERSION = '3.3.6'
1280
+
1281
+ Tooltip.TRANSITION_DURATION = 150
1282
+
1283
+ Tooltip.DEFAULTS = {
1284
+ animation: true,
1285
+ placement: 'top',
1286
+ selector: false,
1287
+ template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
1288
+ trigger: 'hover focus',
1289
+ title: '',
1290
+ delay: 0,
1291
+ html: false,
1292
+ container: false,
1293
+ viewport: {
1294
+ selector: 'body',
1295
+ padding: 0
1296
+ }
1297
+ }
1298
+
1299
+ Tooltip.prototype.init = function (type, element, options) {
1300
+ this.enabled = true
1301
+ this.type = type
1302
+ this.$element = $(element)
1303
+ this.options = this.getOptions(options)
1304
+ this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
1305
+ this.inState = { click: false, hover: false, focus: false }
1306
+
1307
+ if (this.$element[0] instanceof document.constructor && !this.options.selector) {
1308
+ throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
1309
+ }
1310
+
1311
+ var triggers = this.options.trigger.split(' ')
1312
+
1313
+ for (var i = triggers.length; i--;) {
1314
+ var trigger = triggers[i]
1315
+
1316
+ if (trigger == 'click') {
1317
+ this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
1318
+ } else if (trigger != 'manual') {
1319
+ var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
1320
+ var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
1321
+
1322
+ this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
1323
+ this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
1324
+ }
1325
+ }
1326
+
1327
+ this.options.selector ?
1328
+ (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
1329
+ this.fixTitle()
1330
+ }
1331
+
1332
+ Tooltip.prototype.getDefaults = function () {
1333
+ return Tooltip.DEFAULTS
1334
+ }
1335
+
1336
+ Tooltip.prototype.getOptions = function (options) {
1337
+ options = $.extend({}, this.getDefaults(), this.$element.data(), options)
1338
+
1339
+ if (options.delay && typeof options.delay == 'number') {
1340
+ options.delay = {
1341
+ show: options.delay,
1342
+ hide: options.delay
1343
+ }
1344
+ }
1345
+
1346
+ return options
1347
+ }
1348
+
1349
+ Tooltip.prototype.getDelegateOptions = function () {
1350
+ var options = {}
1351
+ var defaults = this.getDefaults()
1352
+
1353
+ this._options && $.each(this._options, function (key, value) {
1354
+ if (defaults[key] != value) options[key] = value
1355
+ })
1356
+
1357
+ return options
1358
+ }
1359
+
1360
+ Tooltip.prototype.enter = function (obj) {
1361
+ var self = obj instanceof this.constructor ?
1362
+ obj : $(obj.currentTarget).data('bs.' + this.type)
1363
+
1364
+ if (!self) {
1365
+ self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
1366
+ $(obj.currentTarget).data('bs.' + this.type, self)
1367
+ }
1368
+
1369
+ if (obj instanceof $.Event) {
1370
+ self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
1371
+ }
1372
+
1373
+ if (self.tip().hasClass('in') || self.hoverState == 'in') {
1374
+ self.hoverState = 'in'
1375
+ return
1376
+ }
1377
+
1378
+ clearTimeout(self.timeout)
1379
+
1380
+ self.hoverState = 'in'
1381
+
1382
+ if (!self.options.delay || !self.options.delay.show) return self.show()
1383
+
1384
+ self.timeout = setTimeout(function () {
1385
+ if (self.hoverState == 'in') self.show()
1386
+ }, self.options.delay.show)
1387
+ }
1388
+
1389
+ Tooltip.prototype.isInStateTrue = function () {
1390
+ for (var key in this.inState) {
1391
+ if (this.inState[key]) return true
1392
+ }
1393
+
1394
+ return false
1395
+ }
1396
+
1397
+ Tooltip.prototype.leave = function (obj) {
1398
+ var self = obj instanceof this.constructor ?
1399
+ obj : $(obj.currentTarget).data('bs.' + this.type)
1400
+
1401
+ if (!self) {
1402
+ self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
1403
+ $(obj.currentTarget).data('bs.' + this.type, self)
1404
+ }
1405
+
1406
+ if (obj instanceof $.Event) {
1407
+ self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
1408
+ }
1409
+
1410
+ if (self.isInStateTrue()) return
1411
+
1412
+ clearTimeout(self.timeout)
1413
+
1414
+ self.hoverState = 'out'
1415
+
1416
+ if (!self.options.delay || !self.options.delay.hide) return self.hide()
1417
+
1418
+ self.timeout = setTimeout(function () {
1419
+ if (self.hoverState == 'out') self.hide()
1420
+ }, self.options.delay.hide)
1421
+ }
1422
+
1423
+ Tooltip.prototype.show = function () {
1424
+ var e = $.Event('show.bs.' + this.type)
1425
+
1426
+ if (this.hasContent() && this.enabled) {
1427
+ this.$element.trigger(e)
1428
+
1429
+ var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
1430
+ if (e.isDefaultPrevented() || !inDom) return
1431
+ var that = this
1432
+
1433
+ var $tip = this.tip()
1434
+
1435
+ var tipId = this.getUID(this.type)
1436
+
1437
+ this.setContent()
1438
+ $tip.attr('id', tipId)
1439
+ this.$element.attr('aria-describedby', tipId)
1440
+
1441
+ if (this.options.animation) $tip.addClass('fade')
1442
+
1443
+ var placement = typeof this.options.placement == 'function' ?
1444
+ this.options.placement.call(this, $tip[0], this.$element[0]) :
1445
+ this.options.placement
1446
+
1447
+ var autoToken = /\s?auto?\s?/i
1448
+ var autoPlace = autoToken.test(placement)
1449
+ if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
1450
+
1451
+ $tip
1452
+ .detach()
1453
+ .css({ top: 0, left: 0, display: 'block' })
1454
+ .addClass(placement)
1455
+ .data('bs.' + this.type, this)
1456
+
1457
+ this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
1458
+ this.$element.trigger('inserted.bs.' + this.type)
1459
+
1460
+ var pos = this.getPosition()
1461
+ var actualWidth = $tip[0].offsetWidth
1462
+ var actualHeight = $tip[0].offsetHeight
1463
+
1464
+ if (autoPlace) {
1465
+ var orgPlacement = placement
1466
+ var viewportDim = this.getPosition(this.$viewport)
1467
+
1468
+ placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' :
1469
+ placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' :
1470
+ placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' :
1471
+ placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' :
1472
+ placement
1473
+
1474
+ $tip
1475
+ .removeClass(orgPlacement)
1476
+ .addClass(placement)
1477
+ }
1478
+
1479
+ var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
1480
+
1481
+ this.applyPlacement(calculatedOffset, placement)
1482
+
1483
+ var complete = function () {
1484
+ var prevHoverState = that.hoverState
1485
+ that.$element.trigger('shown.bs.' + that.type)
1486
+ that.hoverState = null
1487
+
1488
+ if (prevHoverState == 'out') that.leave(that)
1489
+ }
1490
+
1491
+ $.support.transition && this.$tip.hasClass('fade') ?
1492
+ $tip
1493
+ .one('bsTransitionEnd', complete)
1494
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
1495
+ complete()
1496
+ }
1497
+ }
1498
+
1499
+ Tooltip.prototype.applyPlacement = function (offset, placement) {
1500
+ var $tip = this.tip()
1501
+ var width = $tip[0].offsetWidth
1502
+ var height = $tip[0].offsetHeight
1503
+
1504
+ // manually read margins because getBoundingClientRect includes difference
1505
+ var marginTop = parseInt($tip.css('margin-top'), 10)
1506
+ var marginLeft = parseInt($tip.css('margin-left'), 10)
1507
+
1508
+ // we must check for NaN for ie 8/9
1509
+ if (isNaN(marginTop)) marginTop = 0
1510
+ if (isNaN(marginLeft)) marginLeft = 0
1511
+
1512
+ offset.top += marginTop
1513
+ offset.left += marginLeft
1514
+
1515
+ // $.fn.offset doesn't round pixel values
1516
+ // so we use setOffset directly with our own function B-0
1517
+ $.offset.setOffset($tip[0], $.extend({
1518
+ using: function (props) {
1519
+ $tip.css({
1520
+ top: Math.round(props.top),
1521
+ left: Math.round(props.left)
1522
+ })
1523
+ }
1524
+ }, offset), 0)
1525
+
1526
+ $tip.addClass('in')
1527
+
1528
+ // check to see if placing tip in new offset caused the tip to resize itself
1529
+ var actualWidth = $tip[0].offsetWidth
1530
+ var actualHeight = $tip[0].offsetHeight
1531
+
1532
+ if (placement == 'top' && actualHeight != height) {
1533
+ offset.top = offset.top + height - actualHeight
1534
+ }
1535
+
1536
+ var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
1537
+
1538
+ if (delta.left) offset.left += delta.left
1539
+ else offset.top += delta.top
1540
+
1541
+ var isVertical = /top|bottom/.test(placement)
1542
+ var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
1543
+ var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
1544
+
1545
+ $tip.offset(offset)
1546
+ this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
1547
+ }
1548
+
1549
+ Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
1550
+ this.arrow()
1551
+ .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
1552
+ .css(isVertical ? 'top' : 'left', '')
1553
+ }
1554
+
1555
+ Tooltip.prototype.setContent = function () {
1556
+ var $tip = this.tip()
1557
+ var title = this.getTitle()
1558
+
1559
+ $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
1560
+ $tip.removeClass('fade in top bottom left right')
1561
+ }
1562
+
1563
+ Tooltip.prototype.hide = function (callback) {
1564
+ var that = this
1565
+ var $tip = $(this.$tip)
1566
+ var e = $.Event('hide.bs.' + this.type)
1567
+
1568
+ function complete() {
1569
+ if (that.hoverState != 'in') $tip.detach()
1570
+ that.$element
1571
+ .removeAttr('aria-describedby')
1572
+ .trigger('hidden.bs.' + that.type)
1573
+ callback && callback()
1574
+ }
1575
+
1576
+ this.$element.trigger(e)
1577
+
1578
+ if (e.isDefaultPrevented()) return
1579
+
1580
+ $tip.removeClass('in')
1581
+
1582
+ $.support.transition && $tip.hasClass('fade') ?
1583
+ $tip
1584
+ .one('bsTransitionEnd', complete)
1585
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
1586
+ complete()
1587
+
1588
+ this.hoverState = null
1589
+
1590
+ return this
1591
+ }
1592
+
1593
+ Tooltip.prototype.fixTitle = function () {
1594
+ var $e = this.$element
1595
+ if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
1596
+ $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
1597
+ }
1598
+ }
1599
+
1600
+ Tooltip.prototype.hasContent = function () {
1601
+ return this.getTitle()
1602
+ }
1603
+
1604
+ Tooltip.prototype.getPosition = function ($element) {
1605
+ $element = $element || this.$element
1606
+
1607
+ var el = $element[0]
1608
+ var isBody = el.tagName == 'BODY'
1609
+
1610
+ var elRect = el.getBoundingClientRect()
1611
+ if (elRect.width == null) {
1612
+ // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
1613
+ elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
1614
+ }
1615
+ var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
1616
+ var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
1617
+ var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
1618
+
1619
+ return $.extend({}, elRect, scroll, outerDims, elOffset)
1620
+ }
1621
+
1622
+ Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
1623
+ return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
1624
+ placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
1625
+ placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
1626
+ /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
1627
+
1628
+ }
1629
+
1630
+ Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
1631
+ var delta = { top: 0, left: 0 }
1632
+ if (!this.$viewport) return delta
1633
+
1634
+ var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
1635
+ var viewportDimensions = this.getPosition(this.$viewport)
1636
+
1637
+ if (/right|left/.test(placement)) {
1638
+ var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
1639
+ var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
1640
+ if (topEdgeOffset < viewportDimensions.top) { // top overflow
1641
+ delta.top = viewportDimensions.top - topEdgeOffset
1642
+ } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
1643
+ delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
1644
+ }
1645
+ } else {
1646
+ var leftEdgeOffset = pos.left - viewportPadding
1647
+ var rightEdgeOffset = pos.left + viewportPadding + actualWidth
1648
+ if (leftEdgeOffset < viewportDimensions.left) { // left overflow
1649
+ delta.left = viewportDimensions.left - leftEdgeOffset
1650
+ } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
1651
+ delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
1652
+ }
1653
+ }
1654
+
1655
+ return delta
1656
+ }
1657
+
1658
+ Tooltip.prototype.getTitle = function () {
1659
+ var title
1660
+ var $e = this.$element
1661
+ var o = this.options
1662
+
1663
+ title = $e.attr('data-original-title')
1664
+ || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
1665
+
1666
+ return title
1667
+ }
1668
+
1669
+ Tooltip.prototype.getUID = function (prefix) {
1670
+ do prefix += ~~(Math.random() * 1000000)
1671
+ while (document.getElementById(prefix))
1672
+ return prefix
1673
+ }
1674
+
1675
+ Tooltip.prototype.tip = function () {
1676
+ if (!this.$tip) {
1677
+ this.$tip = $(this.options.template)
1678
+ if (this.$tip.length != 1) {
1679
+ throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
1680
+ }
1681
+ }
1682
+ return this.$tip
1683
+ }
1684
+
1685
+ Tooltip.prototype.arrow = function () {
1686
+ return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
1687
+ }
1688
+
1689
+ Tooltip.prototype.enable = function () {
1690
+ this.enabled = true
1691
+ }
1692
+
1693
+ Tooltip.prototype.disable = function () {
1694
+ this.enabled = false
1695
+ }
1696
+
1697
+ Tooltip.prototype.toggleEnabled = function () {
1698
+ this.enabled = !this.enabled
1699
+ }
1700
+
1701
+ Tooltip.prototype.toggle = function (e) {
1702
+ var self = this
1703
+ if (e) {
1704
+ self = $(e.currentTarget).data('bs.' + this.type)
1705
+ if (!self) {
1706
+ self = new this.constructor(e.currentTarget, this.getDelegateOptions())
1707
+ $(e.currentTarget).data('bs.' + this.type, self)
1708
+ }
1709
+ }
1710
+
1711
+ if (e) {
1712
+ self.inState.click = !self.inState.click
1713
+ if (self.isInStateTrue()) self.enter(self)
1714
+ else self.leave(self)
1715
+ } else {
1716
+ self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
1717
+ }
1718
+ }
1719
+
1720
+ Tooltip.prototype.destroy = function () {
1721
+ var that = this
1722
+ clearTimeout(this.timeout)
1723
+ this.hide(function () {
1724
+ that.$element.off('.' + that.type).removeData('bs.' + that.type)
1725
+ if (that.$tip) {
1726
+ that.$tip.detach()
1727
+ }
1728
+ that.$tip = null
1729
+ that.$arrow = null
1730
+ that.$viewport = null
1731
+ })
1732
+ }
1733
+
1734
+
1735
+ // TOOLTIP PLUGIN DEFINITION
1736
+ // =========================
1737
+
1738
+ function Plugin(option) {
1739
+ return this.each(function () {
1740
+ var $this = $(this)
1741
+ var data = $this.data('bs.tooltip')
1742
+ var options = typeof option == 'object' && option
1743
+
1744
+ if (!data && /destroy|hide/.test(option)) return
1745
+ if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
1746
+ if (typeof option == 'string') data[option]()
1747
+ })
1748
+ }
1749
+
1750
+ var old = $.fn.tooltip
1751
+
1752
+ $.fn.tooltip = Plugin
1753
+ $.fn.tooltip.Constructor = Tooltip
1754
+
1755
+
1756
+ // TOOLTIP NO CONFLICT
1757
+ // ===================
1758
+
1759
+ $.fn.tooltip.noConflict = function () {
1760
+ $.fn.tooltip = old
1761
+ return this
1762
+ }
1763
+
1764
+ }(jQuery);
1765
+
1766
+ /* ========================================================================
1767
+ * Bootstrap: popover.js v3.3.6
1768
+ * http://getbootstrap.com/javascript/#popovers
1769
+ * ========================================================================
1770
+ * Copyright 2011-2016 Twitter, Inc.
1771
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1772
+ * ======================================================================== */
1773
+
1774
+
1775
+ +function ($) {
1776
+ 'use strict';
1777
+
1778
+ // POPOVER PUBLIC CLASS DEFINITION
1779
+ // ===============================
1780
+
1781
+ var Popover = function (element, options) {
1782
+ this.init('popover', element, options)
1783
+ }
1784
+
1785
+ if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
1786
+
1787
+ Popover.VERSION = '3.3.6'
1788
+
1789
+ Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
1790
+ placement: 'right',
1791
+ trigger: 'click',
1792
+ content: '',
1793
+ template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
1794
+ })
1795
+
1796
+
1797
+ // NOTE: POPOVER EXTENDS tooltip.js
1798
+ // ================================
1799
+
1800
+ Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
1801
+
1802
+ Popover.prototype.constructor = Popover
1803
+
1804
+ Popover.prototype.getDefaults = function () {
1805
+ return Popover.DEFAULTS
1806
+ }
1807
+
1808
+ Popover.prototype.setContent = function () {
1809
+ var $tip = this.tip()
1810
+ var title = this.getTitle()
1811
+ var content = this.getContent()
1812
+
1813
+ $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
1814
+ $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
1815
+ this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
1816
+ ](content)
1817
+
1818
+ $tip.removeClass('fade top bottom left right in')
1819
+
1820
+ // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
1821
+ // this manually by checking the contents.
1822
+ if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
1823
+ }
1824
+
1825
+ Popover.prototype.hasContent = function () {
1826
+ return this.getTitle() || this.getContent()
1827
+ }
1828
+
1829
+ Popover.prototype.getContent = function () {
1830
+ var $e = this.$element
1831
+ var o = this.options
1832
+
1833
+ return $e.attr('data-content')
1834
+ || (typeof o.content == 'function' ?
1835
+ o.content.call($e[0]) :
1836
+ o.content)
1837
+ }
1838
+
1839
+ Popover.prototype.arrow = function () {
1840
+ return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
1841
+ }
1842
+
1843
+
1844
+ // POPOVER PLUGIN DEFINITION
1845
+ // =========================
1846
+
1847
+ function Plugin(option) {
1848
+ return this.each(function () {
1849
+ var $this = $(this)
1850
+ var data = $this.data('bs.popover')
1851
+ var options = typeof option == 'object' && option
1852
+
1853
+ if (!data && /destroy|hide/.test(option)) return
1854
+ if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
1855
+ if (typeof option == 'string') data[option]()
1856
+ })
1857
+ }
1858
+
1859
+ var old = $.fn.popover
1860
+
1861
+ $.fn.popover = Plugin
1862
+ $.fn.popover.Constructor = Popover
1863
+
1864
+
1865
+ // POPOVER NO CONFLICT
1866
+ // ===================
1867
+
1868
+ $.fn.popover.noConflict = function () {
1869
+ $.fn.popover = old
1870
+ return this
1871
+ }
1872
+
1873
+ }(jQuery);
1874
+
1875
+ /* ========================================================================
1876
+ * Bootstrap: scrollspy.js v3.3.6
1877
+ * http://getbootstrap.com/javascript/#scrollspy
1878
+ * ========================================================================
1879
+ * Copyright 2011-2016 Twitter, Inc.
1880
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1881
+ * ======================================================================== */
1882
+
1883
+
1884
+ +function ($) {
1885
+ 'use strict';
1886
+
1887
+ // SCROLLSPY CLASS DEFINITION
1888
+ // ==========================
1889
+
1890
+ function ScrollSpy(element, options) {
1891
+ this.$body = $(document.body)
1892
+ this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
1893
+ this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
1894
+ this.selector = (this.options.target || '') + ' .nav li > a'
1895
+ this.offsets = []
1896
+ this.targets = []
1897
+ this.activeTarget = null
1898
+ this.scrollHeight = 0
1899
+
1900
+ this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
1901
+ this.refresh()
1902
+ this.process()
1903
+ }
1904
+
1905
+ ScrollSpy.VERSION = '3.3.6'
1906
+
1907
+ ScrollSpy.DEFAULTS = {
1908
+ offset: 10
1909
+ }
1910
+
1911
+ ScrollSpy.prototype.getScrollHeight = function () {
1912
+ return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
1913
+ }
1914
+
1915
+ ScrollSpy.prototype.refresh = function () {
1916
+ var that = this
1917
+ var offsetMethod = 'offset'
1918
+ var offsetBase = 0
1919
+
1920
+ this.offsets = []
1921
+ this.targets = []
1922
+ this.scrollHeight = this.getScrollHeight()
1923
+
1924
+ if (!$.isWindow(this.$scrollElement[0])) {
1925
+ offsetMethod = 'position'
1926
+ offsetBase = this.$scrollElement.scrollTop()
1927
+ }
1928
+
1929
+ this.$body
1930
+ .find(this.selector)
1931
+ .map(function () {
1932
+ var $el = $(this)
1933
+ var href = $el.data('target') || $el.attr('href')
1934
+ var $href = /^#./.test(href) && $(href)
1935
+
1936
+ return ($href
1937
+ && $href.length
1938
+ && $href.is(':visible')
1939
+ && [[$href[offsetMethod]().top + offsetBase, href]]) || null
1940
+ })
1941
+ .sort(function (a, b) { return a[0] - b[0] })
1942
+ .each(function () {
1943
+ that.offsets.push(this[0])
1944
+ that.targets.push(this[1])
1945
+ })
1946
+ }
1947
+
1948
+ ScrollSpy.prototype.process = function () {
1949
+ var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
1950
+ var scrollHeight = this.getScrollHeight()
1951
+ var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
1952
+ var offsets = this.offsets
1953
+ var targets = this.targets
1954
+ var activeTarget = this.activeTarget
1955
+ var i
1956
+
1957
+ if (this.scrollHeight != scrollHeight) {
1958
+ this.refresh()
1959
+ }
1960
+
1961
+ if (scrollTop >= maxScroll) {
1962
+ return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
1963
+ }
1964
+
1965
+ if (activeTarget && scrollTop < offsets[0]) {
1966
+ this.activeTarget = null
1967
+ return this.clear()
1968
+ }
1969
+
1970
+ for (i = offsets.length; i--;) {
1971
+ activeTarget != targets[i]
1972
+ && scrollTop >= offsets[i]
1973
+ && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
1974
+ && this.activate(targets[i])
1975
+ }
1976
+ }
1977
+
1978
+ ScrollSpy.prototype.activate = function (target) {
1979
+ this.activeTarget = target
1980
+
1981
+ this.clear()
1982
+
1983
+ var selector = this.selector +
1984
+ '[data-target="' + target + '"],' +
1985
+ this.selector + '[href="' + target + '"]'
1986
+
1987
+ var active = $(selector)
1988
+ .parents('li')
1989
+ .addClass('active')
1990
+
1991
+ if (active.parent('.dropdown-menu').length) {
1992
+ active = active
1993
+ .closest('li.dropdown')
1994
+ .addClass('active')
1995
+ }
1996
+
1997
+ active.trigger('activate.bs.scrollspy')
1998
+ }
1999
+
2000
+ ScrollSpy.prototype.clear = function () {
2001
+ $(this.selector)
2002
+ .parentsUntil(this.options.target, '.active')
2003
+ .removeClass('active')
2004
+ }
2005
+
2006
+
2007
+ // SCROLLSPY PLUGIN DEFINITION
2008
+ // ===========================
2009
+
2010
+ function Plugin(option) {
2011
+ return this.each(function () {
2012
+ var $this = $(this)
2013
+ var data = $this.data('bs.scrollspy')
2014
+ var options = typeof option == 'object' && option
2015
+
2016
+ if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
2017
+ if (typeof option == 'string') data[option]()
2018
+ })
2019
+ }
2020
+
2021
+ var old = $.fn.scrollspy
2022
+
2023
+ $.fn.scrollspy = Plugin
2024
+ $.fn.scrollspy.Constructor = ScrollSpy
2025
+
2026
+
2027
+ // SCROLLSPY NO CONFLICT
2028
+ // =====================
2029
+
2030
+ $.fn.scrollspy.noConflict = function () {
2031
+ $.fn.scrollspy = old
2032
+ return this
2033
+ }
2034
+
2035
+
2036
+ // SCROLLSPY DATA-API
2037
+ // ==================
2038
+
2039
+ $(window).on('load.bs.scrollspy.data-api', function () {
2040
+ $('[data-spy="scroll"]').each(function () {
2041
+ var $spy = $(this)
2042
+ Plugin.call($spy, $spy.data())
2043
+ })
2044
+ })
2045
+
2046
+ }(jQuery);
2047
+
2048
+ /* ========================================================================
2049
+ * Bootstrap: tab.js v3.3.6
2050
+ * http://getbootstrap.com/javascript/#tabs
2051
+ * ========================================================================
2052
+ * Copyright 2011-2016 Twitter, Inc.
2053
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
2054
+ * ======================================================================== */
2055
+
2056
+
2057
+ +function ($) {
2058
+ 'use strict';
2059
+
2060
+ // TAB CLASS DEFINITION
2061
+ // ====================
2062
+
2063
+ var Tab = function (element) {
2064
+ // jscs:disable requireDollarBeforejQueryAssignment
2065
+ this.element = $(element)
2066
+ // jscs:enable requireDollarBeforejQueryAssignment
2067
+ }
2068
+
2069
+ Tab.VERSION = '3.3.6'
2070
+
2071
+ Tab.TRANSITION_DURATION = 150
2072
+
2073
+ Tab.prototype.show = function () {
2074
+ var $this = this.element
2075
+ var $ul = $this.closest('ul:not(.dropdown-menu)')
2076
+ var selector = $this.data('target')
2077
+
2078
+ if (!selector) {
2079
+ selector = $this.attr('href')
2080
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
2081
+ }
2082
+
2083
+ if ($this.parent('li').hasClass('active')) return
2084
+
2085
+ var $previous = $ul.find('.active:last a')
2086
+ var hideEvent = $.Event('hide.bs.tab', {
2087
+ relatedTarget: $this[0]
2088
+ })
2089
+ var showEvent = $.Event('show.bs.tab', {
2090
+ relatedTarget: $previous[0]
2091
+ })
2092
+
2093
+ $previous.trigger(hideEvent)
2094
+ $this.trigger(showEvent)
2095
+
2096
+ if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
2097
+
2098
+ var $target = $(selector)
2099
+
2100
+ this.activate($this.closest('li'), $ul)
2101
+ this.activate($target, $target.parent(), function () {
2102
+ $previous.trigger({
2103
+ type: 'hidden.bs.tab',
2104
+ relatedTarget: $this[0]
2105
+ })
2106
+ $this.trigger({
2107
+ type: 'shown.bs.tab',
2108
+ relatedTarget: $previous[0]
2109
+ })
2110
+ })
2111
+ }
2112
+
2113
+ Tab.prototype.activate = function (element, container, callback) {
2114
+ var $active = container.find('> .active')
2115
+ var transition = callback
2116
+ && $.support.transition
2117
+ && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)
2118
+
2119
+ function next() {
2120
+ $active
2121
+ .removeClass('active')
2122
+ .find('> .dropdown-menu > .active')
2123
+ .removeClass('active')
2124
+ .end()
2125
+ .find('[data-toggle="tab"]')
2126
+ .attr('aria-expanded', false)
2127
+
2128
+ element
2129
+ .addClass('active')
2130
+ .find('[data-toggle="tab"]')
2131
+ .attr('aria-expanded', true)
2132
+
2133
+ if (transition) {
2134
+ element[0].offsetWidth // reflow for transition
2135
+ element.addClass('in')
2136
+ } else {
2137
+ element.removeClass('fade')
2138
+ }
2139
+
2140
+ if (element.parent('.dropdown-menu').length) {
2141
+ element
2142
+ .closest('li.dropdown')
2143
+ .addClass('active')
2144
+ .end()
2145
+ .find('[data-toggle="tab"]')
2146
+ .attr('aria-expanded', true)
2147
+ }
2148
+
2149
+ callback && callback()
2150
+ }
2151
+
2152
+ $active.length && transition ?
2153
+ $active
2154
+ .one('bsTransitionEnd', next)
2155
+ .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
2156
+ next()
2157
+
2158
+ $active.removeClass('in')
2159
+ }
2160
+
2161
+
2162
+ // TAB PLUGIN DEFINITION
2163
+ // =====================
2164
+
2165
+ function Plugin(option) {
2166
+ return this.each(function () {
2167
+ var $this = $(this)
2168
+ var data = $this.data('bs.tab')
2169
+
2170
+ if (!data) $this.data('bs.tab', (data = new Tab(this)))
2171
+ if (typeof option == 'string') data[option]()
2172
+ })
2173
+ }
2174
+
2175
+ var old = $.fn.tab
2176
+
2177
+ $.fn.tab = Plugin
2178
+ $.fn.tab.Constructor = Tab
2179
+
2180
+
2181
+ // TAB NO CONFLICT
2182
+ // ===============
2183
+
2184
+ $.fn.tab.noConflict = function () {
2185
+ $.fn.tab = old
2186
+ return this
2187
+ }
2188
+
2189
+
2190
+ // TAB DATA-API
2191
+ // ============
2192
+
2193
+ var clickHandler = function (e) {
2194
+ e.preventDefault()
2195
+ Plugin.call($(this), 'show')
2196
+ }
2197
+
2198
+ $(document)
2199
+ .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
2200
+ .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
2201
+
2202
+ }(jQuery);
2203
+
2204
+ /* ========================================================================
2205
+ * Bootstrap: affix.js v3.3.6
2206
+ * http://getbootstrap.com/javascript/#affix
2207
+ * ========================================================================
2208
+ * Copyright 2011-2016 Twitter, Inc.
2209
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
2210
+ * ======================================================================== */
2211
+
2212
+
2213
+ +function ($) {
2214
+ 'use strict';
2215
+
2216
+ // AFFIX CLASS DEFINITION
2217
+ // ======================
2218
+
2219
+ var Affix = function (element, options) {
2220
+ this.options = $.extend({}, Affix.DEFAULTS, options)
2221
+
2222
+ this.$target = $(this.options.target)
2223
+ .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
2224
+ .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
2225
+
2226
+ this.$element = $(element)
2227
+ this.affixed = null
2228
+ this.unpin = null
2229
+ this.pinnedOffset = null
2230
+
2231
+ this.checkPosition()
2232
+ }
2233
+
2234
+ Affix.VERSION = '3.3.6'
2235
+
2236
+ Affix.RESET = 'affix affix-top affix-bottom'
2237
+
2238
+ Affix.DEFAULTS = {
2239
+ offset: 0,
2240
+ target: window
2241
+ }
2242
+
2243
+ Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
2244
+ var scrollTop = this.$target.scrollTop()
2245
+ var position = this.$element.offset()
2246
+ var targetHeight = this.$target.height()
2247
+
2248
+ if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
2249
+
2250
+ if (this.affixed == 'bottom') {
2251
+ if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
2252
+ return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
2253
+ }
2254
+
2255
+ var initializing = this.affixed == null
2256
+ var colliderTop = initializing ? scrollTop : position.top
2257
+ var colliderHeight = initializing ? targetHeight : height
2258
+
2259
+ if (offsetTop != null && scrollTop <= offsetTop) return 'top'
2260
+ if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
2261
+
2262
+ return false
2263
+ }
2264
+
2265
+ Affix.prototype.getPinnedOffset = function () {
2266
+ if (this.pinnedOffset) return this.pinnedOffset
2267
+ this.$element.removeClass(Affix.RESET).addClass('affix')
2268
+ var scrollTop = this.$target.scrollTop()
2269
+ var position = this.$element.offset()
2270
+ return (this.pinnedOffset = position.top - scrollTop)
2271
+ }
2272
+
2273
+ Affix.prototype.checkPositionWithEventLoop = function () {
2274
+ setTimeout($.proxy(this.checkPosition, this), 1)
2275
+ }
2276
+
2277
+ Affix.prototype.checkPosition = function () {
2278
+ if (!this.$element.is(':visible')) return
2279
+
2280
+ var height = this.$element.height()
2281
+ var offset = this.options.offset
2282
+ var offsetTop = offset.top
2283
+ var offsetBottom = offset.bottom
2284
+ var scrollHeight = Math.max($(document).height(), $(document.body).height())
2285
+
2286
+ if (typeof offset != 'object') offsetBottom = offsetTop = offset
2287
+ if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
2288
+ if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
2289
+
2290
+ var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
2291
+
2292
+ if (this.affixed != affix) {
2293
+ if (this.unpin != null) this.$element.css('top', '')
2294
+
2295
+ var affixType = 'affix' + (affix ? '-' + affix : '')
2296
+ var e = $.Event(affixType + '.bs.affix')
2297
+
2298
+ this.$element.trigger(e)
2299
+
2300
+ if (e.isDefaultPrevented()) return
2301
+
2302
+ this.affixed = affix
2303
+ this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
2304
+
2305
+ this.$element
2306
+ .removeClass(Affix.RESET)
2307
+ .addClass(affixType)
2308
+ .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
2309
+ }
2310
+
2311
+ if (affix == 'bottom') {
2312
+ this.$element.offset({
2313
+ top: scrollHeight - height - offsetBottom
2314
+ })
2315
+ }
2316
+ }
2317
+
2318
+
2319
+ // AFFIX PLUGIN DEFINITION
2320
+ // =======================
2321
+
2322
+ function Plugin(option) {
2323
+ return this.each(function () {
2324
+ var $this = $(this)
2325
+ var data = $this.data('bs.affix')
2326
+ var options = typeof option == 'object' && option
2327
+
2328
+ if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
2329
+ if (typeof option == 'string') data[option]()
2330
+ })
2331
+ }
2332
+
2333
+ var old = $.fn.affix
2334
+
2335
+ $.fn.affix = Plugin
2336
+ $.fn.affix.Constructor = Affix
2337
+
2338
+
2339
+ // AFFIX NO CONFLICT
2340
+ // =================
2341
+
2342
+ $.fn.affix.noConflict = function () {
2343
+ $.fn.affix = old
2344
+ return this
2345
+ }
2346
+
2347
+
2348
+ // AFFIX DATA-API
2349
+ // ==============
2350
+
2351
+ $(window).on('load', function () {
2352
+ $('[data-spy="affix"]').each(function () {
2353
+ var $spy = $(this)
2354
+ var data = $spy.data()
2355
+
2356
+ data.offset = data.offset || {}
2357
+
2358
+ if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
2359
+ if (data.offsetTop != null) data.offset.top = data.offsetTop
2360
+
2361
+ Plugin.call($spy, data)
2362
+ })
2363
+ })
2364
+
2365
+ }(jQuery);