Le repo des sources pour le site web des JM2L
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 

2321 linhas
66 KiB

  1. /*!
  2. * Bootstrap v3.3.1 (http://getbootstrap.com)
  3. * Copyright 2011-2014 Twitter, Inc.
  4. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  5. */
  6. if (typeof jQuery === 'undefined') {
  7. throw new Error('Bootstrap\'s JavaScript requires jQuery')
  8. }
  9. +function ($) {
  10. var version = $.fn.jquery.split(' ')[0].split('.')
  11. if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1)) {
  12. throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher')
  13. }
  14. }(jQuery);
  15. /* ========================================================================
  16. * Bootstrap: transition.js v3.3.1
  17. * http://getbootstrap.com/javascript/#transitions
  18. * ========================================================================
  19. * Copyright 2011-2014 Twitter, Inc.
  20. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  21. * ======================================================================== */
  22. +function ($) {
  23. 'use strict';
  24. // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
  25. // ============================================================
  26. function transitionEnd() {
  27. var el = document.createElement('bootstrap')
  28. var transEndEventNames = {
  29. WebkitTransition : 'webkitTransitionEnd',
  30. MozTransition : 'transitionend',
  31. OTransition : 'oTransitionEnd otransitionend',
  32. transition : 'transitionend'
  33. }
  34. for (var name in transEndEventNames) {
  35. if (el.style[name] !== undefined) {
  36. return { end: transEndEventNames[name] }
  37. }
  38. }
  39. return false // explicit for ie8 ( ._.)
  40. }
  41. // http://blog.alexmaccaw.com/css-transitions
  42. $.fn.emulateTransitionEnd = function (duration) {
  43. var called = false
  44. var $el = this
  45. $(this).one('bsTransitionEnd', function () { called = true })
  46. var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
  47. setTimeout(callback, duration)
  48. return this
  49. }
  50. $(function () {
  51. $.support.transition = transitionEnd()
  52. if (!$.support.transition) return
  53. $.event.special.bsTransitionEnd = {
  54. bindType: $.support.transition.end,
  55. delegateType: $.support.transition.end,
  56. handle: function (e) {
  57. if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
  58. }
  59. }
  60. })
  61. }(jQuery);
  62. /* ========================================================================
  63. * Bootstrap: alert.js v3.3.1
  64. * http://getbootstrap.com/javascript/#alerts
  65. * ========================================================================
  66. * Copyright 2011-2014 Twitter, Inc.
  67. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  68. * ======================================================================== */
  69. +function ($) {
  70. 'use strict';
  71. // ALERT CLASS DEFINITION
  72. // ======================
  73. var dismiss = '[data-dismiss="alert"]'
  74. var Alert = function (el) {
  75. $(el).on('click', dismiss, this.close)
  76. }
  77. Alert.VERSION = '3.3.1'
  78. Alert.TRANSITION_DURATION = 150
  79. Alert.prototype.close = function (e) {
  80. var $this = $(this)
  81. var selector = $this.attr('data-target')
  82. if (!selector) {
  83. selector = $this.attr('href')
  84. selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
  85. }
  86. var $parent = $(selector)
  87. if (e) e.preventDefault()
  88. if (!$parent.length) {
  89. $parent = $this.closest('.alert')
  90. }
  91. $parent.trigger(e = $.Event('close.bs.alert'))
  92. if (e.isDefaultPrevented()) return
  93. $parent.removeClass('in')
  94. function removeElement() {
  95. // detach from parent, fire event then clean up data
  96. $parent.detach().trigger('closed.bs.alert').remove()
  97. }
  98. $.support.transition && $parent.hasClass('fade') ?
  99. $parent
  100. .one('bsTransitionEnd', removeElement)
  101. .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
  102. removeElement()
  103. }
  104. // ALERT PLUGIN DEFINITION
  105. // =======================
  106. function Plugin(option) {
  107. return this.each(function () {
  108. var $this = $(this)
  109. var data = $this.data('bs.alert')
  110. if (!data) $this.data('bs.alert', (data = new Alert(this)))
  111. if (typeof option == 'string') data[option].call($this)
  112. })
  113. }
  114. var old = $.fn.alert
  115. $.fn.alert = Plugin
  116. $.fn.alert.Constructor = Alert
  117. // ALERT NO CONFLICT
  118. // =================
  119. $.fn.alert.noConflict = function () {
  120. $.fn.alert = old
  121. return this
  122. }
  123. // ALERT DATA-API
  124. // ==============
  125. $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
  126. }(jQuery);
  127. /* ========================================================================
  128. * Bootstrap: button.js v3.3.1
  129. * http://getbootstrap.com/javascript/#buttons
  130. * ========================================================================
  131. * Copyright 2011-2014 Twitter, Inc.
  132. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  133. * ======================================================================== */
  134. +function ($) {
  135. 'use strict';
  136. // BUTTON PUBLIC CLASS DEFINITION
  137. // ==============================
  138. var Button = function (element, options) {
  139. this.$element = $(element)
  140. this.options = $.extend({}, Button.DEFAULTS, options)
  141. this.isLoading = false
  142. }
  143. Button.VERSION = '3.3.1'
  144. Button.DEFAULTS = {
  145. loadingText: 'loading...'
  146. }
  147. Button.prototype.setState = function (state) {
  148. var d = 'disabled'
  149. var $el = this.$element
  150. var val = $el.is('input') ? 'val' : 'html'
  151. var data = $el.data()
  152. state = state + 'Text'
  153. if (data.resetText == null) $el.data('resetText', $el[val]())
  154. // push to event loop to allow forms to submit
  155. setTimeout($.proxy(function () {
  156. $el[val](data[state] == null ? this.options[state] : data[state])
  157. if (state == 'loadingText') {
  158. this.isLoading = true
  159. $el.addClass(d).attr(d, d)
  160. } else if (this.isLoading) {
  161. this.isLoading = false
  162. $el.removeClass(d).removeAttr(d)
  163. }
  164. }, this), 0)
  165. }
  166. Button.prototype.toggle = function () {
  167. var changed = true
  168. var $parent = this.$element.closest('[data-toggle="buttons"]')
  169. if ($parent.length) {
  170. var $input = this.$element.find('input')
  171. if ($input.prop('type') == 'radio') {
  172. if ($input.prop('checked') && this.$element.hasClass('active')) changed = false
  173. else $parent.find('.active').removeClass('active')
  174. }
  175. if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
  176. } else {
  177. this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
  178. }
  179. if (changed) this.$element.toggleClass('active')
  180. }
  181. // BUTTON PLUGIN DEFINITION
  182. // ========================
  183. function Plugin(option) {
  184. return this.each(function () {
  185. var $this = $(this)
  186. var data = $this.data('bs.button')
  187. var options = typeof option == 'object' && option
  188. if (!data) $this.data('bs.button', (data = new Button(this, options)))
  189. if (option == 'toggle') data.toggle()
  190. else if (option) data.setState(option)
  191. })
  192. }
  193. var old = $.fn.button
  194. $.fn.button = Plugin
  195. $.fn.button.Constructor = Button
  196. // BUTTON NO CONFLICT
  197. // ==================
  198. $.fn.button.noConflict = function () {
  199. $.fn.button = old
  200. return this
  201. }
  202. // BUTTON DATA-API
  203. // ===============
  204. $(document)
  205. .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
  206. var $btn = $(e.target)
  207. if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
  208. Plugin.call($btn, 'toggle')
  209. e.preventDefault()
  210. })
  211. .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
  212. $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
  213. })
  214. }(jQuery);
  215. /* ========================================================================
  216. * Bootstrap: carousel.js v3.3.1
  217. * http://getbootstrap.com/javascript/#carousel
  218. * ========================================================================
  219. * Copyright 2011-2014 Twitter, Inc.
  220. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  221. * ======================================================================== */
  222. +function ($) {
  223. 'use strict';
  224. // CAROUSEL CLASS DEFINITION
  225. // =========================
  226. var Carousel = function (element, options) {
  227. this.$element = $(element)
  228. this.$indicators = this.$element.find('.carousel-indicators')
  229. this.options = options
  230. this.paused =
  231. this.sliding =
  232. this.interval =
  233. this.$active =
  234. this.$items = null
  235. this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
  236. this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
  237. .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
  238. .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
  239. }
  240. Carousel.VERSION = '3.3.1'
  241. Carousel.TRANSITION_DURATION = 600
  242. Carousel.DEFAULTS = {
  243. interval: 5000,
  244. pause: 'hover',
  245. wrap: true,
  246. keyboard: true
  247. }
  248. Carousel.prototype.keydown = function (e) {
  249. if (/input|textarea/i.test(e.target.tagName)) return
  250. switch (e.which) {
  251. case 37: this.prev(); break
  252. case 39: this.next(); break
  253. default: return
  254. }
  255. e.preventDefault()
  256. }
  257. Carousel.prototype.cycle = function (e) {
  258. e || (this.paused = false)
  259. this.interval && clearInterval(this.interval)
  260. this.options.interval
  261. && !this.paused
  262. && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
  263. return this
  264. }
  265. Carousel.prototype.getItemIndex = function (item) {
  266. this.$items = item.parent().children('.item')
  267. return this.$items.index(item || this.$active)
  268. }
  269. Carousel.prototype.getItemForDirection = function (direction, active) {
  270. var delta = direction == 'prev' ? -1 : 1
  271. var activeIndex = this.getItemIndex(active)
  272. var itemIndex = (activeIndex + delta) % this.$items.length
  273. return this.$items.eq(itemIndex)
  274. }
  275. Carousel.prototype.to = function (pos) {
  276. var that = this
  277. var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
  278. if (pos > (this.$items.length - 1) || pos < 0) return
  279. if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
  280. if (activeIndex == pos) return this.pause().cycle()
  281. return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
  282. }
  283. Carousel.prototype.pause = function (e) {
  284. e || (this.paused = true)
  285. if (this.$element.find('.next, .prev').length && $.support.transition) {
  286. this.$element.trigger($.support.transition.end)
  287. this.cycle(true)
  288. }
  289. this.interval = clearInterval(this.interval)
  290. return this
  291. }
  292. Carousel.prototype.next = function () {
  293. if (this.sliding) return
  294. return this.slide('next')
  295. }
  296. Carousel.prototype.prev = function () {
  297. if (this.sliding) return
  298. return this.slide('prev')
  299. }
  300. Carousel.prototype.slide = function (type, next) {
  301. var $active = this.$element.find('.item.active')
  302. var $next = next || this.getItemForDirection(type, $active)
  303. var isCycling = this.interval
  304. var direction = type == 'next' ? 'left' : 'right'
  305. var fallback = type == 'next' ? 'first' : 'last'
  306. var that = this
  307. if (!$next.length) {
  308. if (!this.options.wrap) return
  309. $next = this.$element.find('.item')[fallback]()
  310. }
  311. if ($next.hasClass('active')) return (this.sliding = false)
  312. var relatedTarget = $next[0]
  313. var slideEvent = $.Event('slide.bs.carousel', {
  314. relatedTarget: relatedTarget,
  315. direction: direction
  316. })
  317. this.$element.trigger(slideEvent)
  318. if (slideEvent.isDefaultPrevented()) return
  319. this.sliding = true
  320. isCycling && this.pause()
  321. if (this.$indicators.length) {
  322. this.$indicators.find('.active').removeClass('active')
  323. var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
  324. $nextIndicator && $nextIndicator.addClass('active')
  325. }
  326. var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
  327. if ($.support.transition && this.$element.hasClass('slide')) {
  328. $next.addClass(type)
  329. $next[0].offsetWidth // force reflow
  330. $active.addClass(direction)
  331. $next.addClass(direction)
  332. $active
  333. .one('bsTransitionEnd', function () {
  334. $next.removeClass([type, direction].join(' ')).addClass('active')
  335. $active.removeClass(['active', direction].join(' '))
  336. that.sliding = false
  337. setTimeout(function () {
  338. that.$element.trigger(slidEvent)
  339. }, 0)
  340. })
  341. .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
  342. } else {
  343. $active.removeClass('active')
  344. $next.addClass('active')
  345. this.sliding = false
  346. this.$element.trigger(slidEvent)
  347. }
  348. isCycling && this.cycle()
  349. return this
  350. }
  351. // CAROUSEL PLUGIN DEFINITION
  352. // ==========================
  353. function Plugin(option) {
  354. return this.each(function () {
  355. var $this = $(this)
  356. var data = $this.data('bs.carousel')
  357. var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
  358. var action = typeof option == 'string' ? option : options.slide
  359. if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
  360. if (typeof option == 'number') data.to(option)
  361. else if (action) data[action]()
  362. else if (options.interval) data.pause().cycle()
  363. })
  364. }
  365. var old = $.fn.carousel
  366. $.fn.carousel = Plugin
  367. $.fn.carousel.Constructor = Carousel
  368. // CAROUSEL NO CONFLICT
  369. // ====================
  370. $.fn.carousel.noConflict = function () {
  371. $.fn.carousel = old
  372. return this
  373. }
  374. // CAROUSEL DATA-API
  375. // =================
  376. var clickHandler = function (e) {
  377. var href
  378. var $this = $(this)
  379. var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
  380. if (!$target.hasClass('carousel')) return
  381. var options = $.extend({}, $target.data(), $this.data())
  382. var slideIndex = $this.attr('data-slide-to')
  383. if (slideIndex) options.interval = false
  384. Plugin.call($target, options)
  385. if (slideIndex) {
  386. $target.data('bs.carousel').to(slideIndex)
  387. }
  388. e.preventDefault()
  389. }
  390. $(document)
  391. .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
  392. .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
  393. $(window).on('load', function () {
  394. $('[data-ride="carousel"]').each(function () {
  395. var $carousel = $(this)
  396. Plugin.call($carousel, $carousel.data())
  397. })
  398. })
  399. }(jQuery);
  400. /* ========================================================================
  401. * Bootstrap: collapse.js v3.3.1
  402. * http://getbootstrap.com/javascript/#collapse
  403. * ========================================================================
  404. * Copyright 2011-2014 Twitter, Inc.
  405. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  406. * ======================================================================== */
  407. +function ($) {
  408. 'use strict';
  409. // COLLAPSE PUBLIC CLASS DEFINITION
  410. // ================================
  411. var Collapse = function (element, options) {
  412. this.$element = $(element)
  413. this.options = $.extend({}, Collapse.DEFAULTS, options)
  414. this.$trigger = $(this.options.trigger).filter('[href="#' + element.id + '"], [data-target="#' + element.id + '"]')
  415. this.transitioning = null
  416. if (this.options.parent) {
  417. this.$parent = this.getParent()
  418. } else {
  419. this.addAriaAndCollapsedClass(this.$element, this.$trigger)
  420. }
  421. if (this.options.toggle) this.toggle()
  422. }
  423. Collapse.VERSION = '3.3.1'
  424. Collapse.TRANSITION_DURATION = 350
  425. Collapse.DEFAULTS = {
  426. toggle: true,
  427. trigger: '[data-toggle="collapse"]'
  428. }
  429. Collapse.prototype.dimension = function () {
  430. var hasWidth = this.$element.hasClass('width')
  431. return hasWidth ? 'width' : 'height'
  432. }
  433. Collapse.prototype.show = function () {
  434. if (this.transitioning || this.$element.hasClass('in')) return
  435. var activesData
  436. var actives = this.$parent && this.$parent.find('> .panel').children('.in, .collapsing')
  437. if (actives && actives.length) {
  438. activesData = actives.data('bs.collapse')
  439. if (activesData && activesData.transitioning) return
  440. }
  441. var startEvent = $.Event('show.bs.collapse')
  442. this.$element.trigger(startEvent)
  443. if (startEvent.isDefaultPrevented()) return
  444. if (actives && actives.length) {
  445. Plugin.call(actives, 'hide')
  446. activesData || actives.data('bs.collapse', null)
  447. }
  448. var dimension = this.dimension()
  449. this.$element
  450. .removeClass('collapse')
  451. .addClass('collapsing')[dimension](0)
  452. .attr('aria-expanded', true)
  453. this.$trigger
  454. .removeClass('collapsed')
  455. .attr('aria-expanded', true)
  456. this.transitioning = 1
  457. var complete = function () {
  458. this.$element
  459. .removeClass('collapsing')
  460. .addClass('collapse in')[dimension]('')
  461. this.transitioning = 0
  462. this.$element
  463. .trigger('shown.bs.collapse')
  464. }
  465. if (!$.support.transition) return complete.call(this)
  466. var scrollSize = $.camelCase(['scroll', dimension].join('-'))
  467. this.$element
  468. .one('bsTransitionEnd', $.proxy(complete, this))
  469. .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
  470. }
  471. Collapse.prototype.hide = function () {
  472. if (this.transitioning || !this.$element.hasClass('in')) return
  473. var startEvent = $.Event('hide.bs.collapse')
  474. this.$element.trigger(startEvent)
  475. if (startEvent.isDefaultPrevented()) return
  476. var dimension = this.dimension()
  477. this.$element[dimension](this.$element[dimension]())[0].offsetHeight
  478. this.$element
  479. .addClass('collapsing')
  480. .removeClass('collapse in')
  481. .attr('aria-expanded', false)
  482. this.$trigger
  483. .addClass('collapsed')
  484. .attr('aria-expanded', false)
  485. this.transitioning = 1
  486. var complete = function () {
  487. this.transitioning = 0
  488. this.$element
  489. .removeClass('collapsing')
  490. .addClass('collapse')
  491. .trigger('hidden.bs.collapse')
  492. }
  493. if (!$.support.transition) return complete.call(this)
  494. this.$element
  495. [dimension](0)
  496. .one('bsTransitionEnd', $.proxy(complete, this))
  497. .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
  498. }
  499. Collapse.prototype.toggle = function () {
  500. this[this.$element.hasClass('in') ? 'hide' : 'show']()
  501. }
  502. Collapse.prototype.getParent = function () {
  503. return $(this.options.parent)
  504. .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
  505. .each($.proxy(function (i, element) {
  506. var $element = $(element)
  507. this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
  508. }, this))
  509. .end()
  510. }
  511. Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
  512. var isOpen = $element.hasClass('in')
  513. $element.attr('aria-expanded', isOpen)
  514. $trigger
  515. .toggleClass('collapsed', !isOpen)
  516. .attr('aria-expanded', isOpen)
  517. }
  518. function getTargetFromTrigger($trigger) {
  519. var href
  520. var target = $trigger.attr('data-target')
  521. || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
  522. return $(target)
  523. }
  524. // COLLAPSE PLUGIN DEFINITION
  525. // ==========================
  526. function Plugin(option) {
  527. return this.each(function () {
  528. var $this = $(this)
  529. var data = $this.data('bs.collapse')
  530. var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
  531. if (!data && options.toggle && option == 'show') options.toggle = false
  532. if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
  533. if (typeof option == 'string') data[option]()
  534. })
  535. }
  536. var old = $.fn.collapse
  537. $.fn.collapse = Plugin
  538. $.fn.collapse.Constructor = Collapse
  539. // COLLAPSE NO CONFLICT
  540. // ====================
  541. $.fn.collapse.noConflict = function () {
  542. $.fn.collapse = old
  543. return this
  544. }
  545. // COLLAPSE DATA-API
  546. // =================
  547. $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
  548. var $this = $(this)
  549. if (!$this.attr('data-target')) e.preventDefault()
  550. var $target = getTargetFromTrigger($this)
  551. var data = $target.data('bs.collapse')
  552. var option = data ? 'toggle' : $.extend({}, $this.data(), { trigger: this })
  553. Plugin.call($target, option)
  554. })
  555. }(jQuery);
  556. /* ========================================================================
  557. * Bootstrap: dropdown.js v3.3.1
  558. * http://getbootstrap.com/javascript/#dropdowns
  559. * ========================================================================
  560. * Copyright 2011-2014 Twitter, Inc.
  561. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  562. * ======================================================================== */
  563. +function ($) {
  564. 'use strict';
  565. // DROPDOWN CLASS DEFINITION
  566. // =========================
  567. var backdrop = '.dropdown-backdrop'
  568. var toggle = '[data-toggle="dropdown"]'
  569. var Dropdown = function (element) {
  570. $(element).on('click.bs.dropdown', this.toggle)
  571. }
  572. Dropdown.VERSION = '3.3.1'
  573. Dropdown.prototype.toggle = function (e) {
  574. var $this = $(this)
  575. if ($this.is('.disabled, :disabled')) return
  576. var $parent = getParent($this)
  577. var isActive = $parent.hasClass('open')
  578. clearMenus()
  579. if (!isActive) {
  580. if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
  581. // if mobile we use a backdrop because click events don't delegate
  582. $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
  583. }
  584. var relatedTarget = { relatedTarget: this }
  585. $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
  586. if (e.isDefaultPrevented()) return
  587. $this
  588. .trigger('focus')
  589. .attr('aria-expanded', 'true')
  590. $parent
  591. .toggleClass('open')
  592. .trigger('shown.bs.dropdown', relatedTarget)
  593. }
  594. return false
  595. }
  596. Dropdown.prototype.keydown = function (e) {
  597. if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
  598. var $this = $(this)
  599. e.preventDefault()
  600. e.stopPropagation()
  601. if ($this.is('.disabled, :disabled')) return
  602. var $parent = getParent($this)
  603. var isActive = $parent.hasClass('open')
  604. if ((!isActive && e.which != 27) || (isActive && e.which == 27)) {
  605. if (e.which == 27) $parent.find(toggle).trigger('focus')
  606. return $this.trigger('click')
  607. }
  608. var desc = ' li:not(.divider):visible a'
  609. var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc)
  610. if (!$items.length) return
  611. var index = $items.index(e.target)
  612. if (e.which == 38 && index > 0) index-- // up
  613. if (e.which == 40 && index < $items.length - 1) index++ // down
  614. if (!~index) index = 0
  615. $items.eq(index).trigger('focus')
  616. }
  617. function clearMenus(e) {
  618. if (e && e.which === 3) return
  619. $(backdrop).remove()
  620. $(toggle).each(function () {
  621. var $this = $(this)
  622. var $parent = getParent($this)
  623. var relatedTarget = { relatedTarget: this }
  624. if (!$parent.hasClass('open')) return
  625. $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
  626. if (e.isDefaultPrevented()) return
  627. $this.attr('aria-expanded', 'false')
  628. $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
  629. })
  630. }
  631. function getParent($this) {
  632. var selector = $this.attr('data-target')
  633. if (!selector) {
  634. selector = $this.attr('href')
  635. selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
  636. }
  637. var $parent = selector && $(selector)
  638. return $parent && $parent.length ? $parent : $this.parent()
  639. }
  640. // DROPDOWN PLUGIN DEFINITION
  641. // ==========================
  642. function Plugin(option) {
  643. return this.each(function () {
  644. var $this = $(this)
  645. var data = $this.data('bs.dropdown')
  646. if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
  647. if (typeof option == 'string') data[option].call($this)
  648. })
  649. }
  650. var old = $.fn.dropdown
  651. $.fn.dropdown = Plugin
  652. $.fn.dropdown.Constructor = Dropdown
  653. // DROPDOWN NO CONFLICT
  654. // ====================
  655. $.fn.dropdown.noConflict = function () {
  656. $.fn.dropdown = old
  657. return this
  658. }
  659. // APPLY TO STANDARD DROPDOWN ELEMENTS
  660. // ===================================
  661. $(document)
  662. .on('click.bs.dropdown.data-api', clearMenus)
  663. .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
  664. .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
  665. .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
  666. .on('keydown.bs.dropdown.data-api', '[role="menu"]', Dropdown.prototype.keydown)
  667. .on('keydown.bs.dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown)
  668. }(jQuery);
  669. /* ========================================================================
  670. * Bootstrap: modal.js v3.3.1
  671. * http://getbootstrap.com/javascript/#modals
  672. * ========================================================================
  673. * Copyright 2011-2014 Twitter, Inc.
  674. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  675. * ======================================================================== */
  676. +function ($) {
  677. 'use strict';
  678. // MODAL CLASS DEFINITION
  679. // ======================
  680. var Modal = function (element, options) {
  681. this.options = options
  682. this.$body = $(document.body)
  683. this.$element = $(element)
  684. this.$backdrop =
  685. this.isShown = null
  686. this.scrollbarWidth = 0
  687. if (this.options.remote) {
  688. this.$element
  689. .find('.modal-content')
  690. .load(this.options.remote, $.proxy(function () {
  691. this.$element.trigger('loaded.bs.modal')
  692. }, this))
  693. }
  694. }
  695. Modal.VERSION = '3.3.1'
  696. Modal.TRANSITION_DURATION = 300
  697. Modal.BACKDROP_TRANSITION_DURATION = 150
  698. Modal.DEFAULTS = {
  699. backdrop: true,
  700. keyboard: true,
  701. show: true
  702. }
  703. Modal.prototype.toggle = function (_relatedTarget) {
  704. return this.isShown ? this.hide() : this.show(_relatedTarget)
  705. }
  706. Modal.prototype.show = function (_relatedTarget) {
  707. var that = this
  708. var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
  709. this.$element.trigger(e)
  710. if (this.isShown || e.isDefaultPrevented()) return
  711. this.isShown = true
  712. this.checkScrollbar()
  713. this.setScrollbar()
  714. this.$body.addClass('modal-open')
  715. this.escape()
  716. this.resize()
  717. this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
  718. this.backdrop(function () {
  719. var transition = $.support.transition && that.$element.hasClass('fade')
  720. if (!that.$element.parent().length) {
  721. that.$element.appendTo(that.$body) // don't move modals dom position
  722. }
  723. that.$element
  724. .show()
  725. .scrollTop(0)
  726. if (that.options.backdrop) that.adjustBackdrop()
  727. that.adjustDialog()
  728. if (transition) {
  729. that.$element[0].offsetWidth // force reflow
  730. }
  731. that.$element
  732. .addClass('in')
  733. .attr('aria-hidden', false)
  734. that.enforceFocus()
  735. var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
  736. transition ?
  737. that.$element.find('.modal-dialog') // wait for modal to slide in
  738. .one('bsTransitionEnd', function () {
  739. that.$element.trigger('focus').trigger(e)
  740. })
  741. .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
  742. that.$element.trigger('focus').trigger(e)
  743. })
  744. }
  745. Modal.prototype.hide = function (e) {
  746. if (e) e.preventDefault()
  747. e = $.Event('hide.bs.modal')
  748. this.$element.trigger(e)
  749. if (!this.isShown || e.isDefaultPrevented()) return
  750. this.isShown = false
  751. this.escape()
  752. this.resize()
  753. $(document).off('focusin.bs.modal')
  754. this.$element
  755. .removeClass('in')
  756. .attr('aria-hidden', true)
  757. .off('click.dismiss.bs.modal')
  758. $.support.transition && this.$element.hasClass('fade') ?
  759. this.$element
  760. .one('bsTransitionEnd', $.proxy(this.hideModal, this))
  761. .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
  762. this.hideModal()
  763. }
  764. Modal.prototype.enforceFocus = function () {
  765. $(document)
  766. .off('focusin.bs.modal') // guard against infinite focus loop
  767. .on('focusin.bs.modal', $.proxy(function (e) {
  768. if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
  769. this.$element.trigger('focus')
  770. }
  771. }, this))
  772. }
  773. Modal.prototype.escape = function () {
  774. if (this.isShown && this.options.keyboard) {
  775. this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
  776. e.which == 27 && this.hide()
  777. }, this))
  778. } else if (!this.isShown) {
  779. this.$element.off('keydown.dismiss.bs.modal')
  780. }
  781. }
  782. Modal.prototype.resize = function () {
  783. if (this.isShown) {
  784. $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
  785. } else {
  786. $(window).off('resize.bs.modal')
  787. }
  788. }
  789. Modal.prototype.hideModal = function () {
  790. var that = this
  791. this.$element.hide()
  792. this.backdrop(function () {
  793. that.$body.removeClass('modal-open')
  794. that.resetAdjustments()
  795. that.resetScrollbar()
  796. that.$element.trigger('hidden.bs.modal')
  797. })
  798. }
  799. Modal.prototype.removeBackdrop = function () {
  800. this.$backdrop && this.$backdrop.remove()
  801. this.$backdrop = null
  802. }
  803. Modal.prototype.backdrop = function (callback) {
  804. var that = this
  805. var animate = this.$element.hasClass('fade') ? 'fade' : ''
  806. if (this.isShown && this.options.backdrop) {
  807. var doAnimate = $.support.transition && animate
  808. this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
  809. .prependTo(this.$element)
  810. .on('click.dismiss.bs.modal', $.proxy(function (e) {
  811. if (e.target !== e.currentTarget) return
  812. this.options.backdrop == 'static'
  813. ? this.$element[0].focus.call(this.$element[0])
  814. : this.hide.call(this)
  815. }, this))
  816. if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
  817. this.$backdrop.addClass('in')
  818. if (!callback) return
  819. doAnimate ?
  820. this.$backdrop
  821. .one('bsTransitionEnd', callback)
  822. .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
  823. callback()
  824. } else if (!this.isShown && this.$backdrop) {
  825. this.$backdrop.removeClass('in')
  826. var callbackRemove = function () {
  827. that.removeBackdrop()
  828. callback && callback()
  829. }
  830. $.support.transition && this.$element.hasClass('fade') ?
  831. this.$backdrop
  832. .one('bsTransitionEnd', callbackRemove)
  833. .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
  834. callbackRemove()
  835. } else if (callback) {
  836. callback()
  837. }
  838. }
  839. // these following methods are used to handle overflowing modals
  840. Modal.prototype.handleUpdate = function () {
  841. if (this.options.backdrop) this.adjustBackdrop()
  842. this.adjustDialog()
  843. }
  844. Modal.prototype.adjustBackdrop = function () {
  845. this.$backdrop
  846. .css('height', 0)
  847. .css('height', this.$element[0].scrollHeight)
  848. }
  849. Modal.prototype.adjustDialog = function () {
  850. var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
  851. this.$element.css({
  852. paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
  853. paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
  854. })
  855. }
  856. Modal.prototype.resetAdjustments = function () {
  857. this.$element.css({
  858. paddingLeft: '',
  859. paddingRight: ''
  860. })
  861. }
  862. Modal.prototype.checkScrollbar = function () {
  863. this.bodyIsOverflowing = document.body.scrollHeight > document.documentElement.clientHeight
  864. this.scrollbarWidth = this.measureScrollbar()
  865. }
  866. Modal.prototype.setScrollbar = function () {
  867. var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
  868. if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
  869. }
  870. Modal.prototype.resetScrollbar = function () {
  871. this.$body.css('padding-right', '')
  872. }
  873. Modal.prototype.measureScrollbar = function () { // thx walsh
  874. var scrollDiv = document.createElement('div')
  875. scrollDiv.className = 'modal-scrollbar-measure'
  876. this.$body.append(scrollDiv)
  877. var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
  878. this.$body[0].removeChild(scrollDiv)
  879. return scrollbarWidth
  880. }
  881. // MODAL PLUGIN DEFINITION
  882. // =======================
  883. function Plugin(option, _relatedTarget) {
  884. return this.each(function () {
  885. var $this = $(this)
  886. var data = $this.data('bs.modal')
  887. var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
  888. if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
  889. if (typeof option == 'string') data[option](_relatedTarget)
  890. else if (options.show) data.show(_relatedTarget)
  891. })
  892. }
  893. var old = $.fn.modal
  894. $.fn.modal = Plugin
  895. $.fn.modal.Constructor = Modal
  896. // MODAL NO CONFLICT
  897. // =================
  898. $.fn.modal.noConflict = function () {
  899. $.fn.modal = old
  900. return this
  901. }
  902. // MODAL DATA-API
  903. // ==============
  904. $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
  905. var $this = $(this)
  906. var href = $this.attr('href')
  907. var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
  908. var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
  909. if ($this.is('a')) e.preventDefault()
  910. $target.one('show.bs.modal', function (showEvent) {
  911. if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
  912. $target.one('hidden.bs.modal', function () {
  913. $this.is(':visible') && $this.trigger('focus')
  914. })
  915. })
  916. Plugin.call($target, option, this)
  917. })
  918. }(jQuery);
  919. /* ========================================================================
  920. * Bootstrap: tooltip.js v3.3.1
  921. * http://getbootstrap.com/javascript/#tooltip
  922. * Inspired by the original jQuery.tipsy by Jason Frame
  923. * ========================================================================
  924. * Copyright 2011-2014 Twitter, Inc.
  925. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  926. * ======================================================================== */
  927. +function ($) {
  928. 'use strict';
  929. // TOOLTIP PUBLIC CLASS DEFINITION
  930. // ===============================
  931. var Tooltip = function (element, options) {
  932. this.type =
  933. this.options =
  934. this.enabled =
  935. this.timeout =
  936. this.hoverState =
  937. this.$element = null
  938. this.init('tooltip', element, options)
  939. }
  940. Tooltip.VERSION = '3.3.1'
  941. Tooltip.TRANSITION_DURATION = 150
  942. Tooltip.DEFAULTS = {
  943. animation: true,
  944. placement: 'top',
  945. selector: false,
  946. template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
  947. trigger: 'hover focus',
  948. title: '',
  949. delay: 0,
  950. html: false,
  951. container: false,
  952. viewport: {
  953. selector: 'body',
  954. padding: 0
  955. }
  956. }
  957. Tooltip.prototype.init = function (type, element, options) {
  958. this.enabled = true
  959. this.type = type
  960. this.$element = $(element)
  961. this.options = this.getOptions(options)
  962. this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
  963. var triggers = this.options.trigger.split(' ')
  964. for (var i = triggers.length; i--;) {
  965. var trigger = triggers[i]
  966. if (trigger == 'click') {
  967. this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
  968. } else if (trigger != 'manual') {
  969. var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
  970. var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
  971. this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
  972. this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
  973. }
  974. }
  975. this.options.selector ?
  976. (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
  977. this.fixTitle()
  978. }
  979. Tooltip.prototype.getDefaults = function () {
  980. return Tooltip.DEFAULTS
  981. }
  982. Tooltip.prototype.getOptions = function (options) {
  983. options = $.extend({}, this.getDefaults(), this.$element.data(), options)
  984. if (options.delay && typeof options.delay == 'number') {
  985. options.delay = {
  986. show: options.delay,
  987. hide: options.delay
  988. }
  989. }
  990. return options
  991. }
  992. Tooltip.prototype.getDelegateOptions = function () {
  993. var options = {}
  994. var defaults = this.getDefaults()
  995. this._options && $.each(this._options, function (key, value) {
  996. if (defaults[key] != value) options[key] = value
  997. })
  998. return options
  999. }
  1000. Tooltip.prototype.enter = function (obj) {
  1001. var self = obj instanceof this.constructor ?
  1002. obj : $(obj.currentTarget).data('bs.' + this.type)
  1003. if (self && self.$tip && self.$tip.is(':visible')) {
  1004. self.hoverState = 'in'
  1005. return
  1006. }
  1007. if (!self) {
  1008. self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
  1009. $(obj.currentTarget).data('bs.' + this.type, self)
  1010. }
  1011. clearTimeout(self.timeout)
  1012. self.hoverState = 'in'
  1013. if (!self.options.delay || !self.options.delay.show) return self.show()
  1014. self.timeout = setTimeout(function () {
  1015. if (self.hoverState == 'in') self.show()
  1016. }, self.options.delay.show)
  1017. }
  1018. Tooltip.prototype.leave = function (obj) {
  1019. var self = obj instanceof this.constructor ?
  1020. obj : $(obj.currentTarget).data('bs.' + this.type)
  1021. if (!self) {
  1022. self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
  1023. $(obj.currentTarget).data('bs.' + this.type, self)
  1024. }
  1025. clearTimeout(self.timeout)
  1026. self.hoverState = 'out'
  1027. if (!self.options.delay || !self.options.delay.hide) return self.hide()
  1028. self.timeout = setTimeout(function () {
  1029. if (self.hoverState == 'out') self.hide()
  1030. }, self.options.delay.hide)
  1031. }
  1032. Tooltip.prototype.show = function () {
  1033. var e = $.Event('show.bs.' + this.type)
  1034. if (this.hasContent() && this.enabled) {
  1035. this.$element.trigger(e)
  1036. var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
  1037. if (e.isDefaultPrevented() || !inDom) return
  1038. var that = this
  1039. var $tip = this.tip()
  1040. var tipId = this.getUID(this.type)
  1041. this.setContent()
  1042. $tip.attr('id', tipId)
  1043. this.$element.attr('aria-describedby', tipId)
  1044. if (this.options.animation) $tip.addClass('fade')
  1045. var placement = typeof this.options.placement == 'function' ?
  1046. this.options.placement.call(this, $tip[0], this.$element[0]) :
  1047. this.options.placement
  1048. var autoToken = /\s?auto?\s?/i
  1049. var autoPlace = autoToken.test(placement)
  1050. if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
  1051. $tip
  1052. .detach()
  1053. .css({ top: 0, left: 0, display: 'block' })
  1054. .addClass(placement)
  1055. .data('bs.' + this.type, this)
  1056. this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
  1057. var pos = this.getPosition()
  1058. var actualWidth = $tip[0].offsetWidth
  1059. var actualHeight = $tip[0].offsetHeight
  1060. if (autoPlace) {
  1061. var orgPlacement = placement
  1062. var $container = this.options.container ? $(this.options.container) : this.$element.parent()
  1063. var containerDim = this.getPosition($container)
  1064. placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top' :
  1065. placement == 'top' && pos.top - actualHeight < containerDim.top ? 'bottom' :
  1066. placement == 'right' && pos.right + actualWidth > containerDim.width ? 'left' :
  1067. placement == 'left' && pos.left - actualWidth < containerDim.left ? 'right' :
  1068. placement
  1069. $tip
  1070. .removeClass(orgPlacement)
  1071. .addClass(placement)
  1072. }
  1073. var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
  1074. this.applyPlacement(calculatedOffset, placement)
  1075. var complete = function () {
  1076. var prevHoverState = that.hoverState
  1077. that.$element.trigger('shown.bs.' + that.type)
  1078. that.hoverState = null
  1079. if (prevHoverState == 'out') that.leave(that)
  1080. }
  1081. $.support.transition && this.$tip.hasClass('fade') ?
  1082. $tip
  1083. .one('bsTransitionEnd', complete)
  1084. .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
  1085. complete()
  1086. }
  1087. }
  1088. Tooltip.prototype.applyPlacement = function (offset, placement) {
  1089. var $tip = this.tip()
  1090. var width = $tip[0].offsetWidth
  1091. var height = $tip[0].offsetHeight
  1092. // manually read margins because getBoundingClientRect includes difference
  1093. var marginTop = parseInt($tip.css('margin-top'), 10)
  1094. var marginLeft = parseInt($tip.css('margin-left'), 10)
  1095. // we must check for NaN for ie 8/9
  1096. if (isNaN(marginTop)) marginTop = 0
  1097. if (isNaN(marginLeft)) marginLeft = 0
  1098. offset.top = offset.top + marginTop
  1099. offset.left = offset.left + marginLeft
  1100. // $.fn.offset doesn't round pixel values
  1101. // so we use setOffset directly with our own function B-0
  1102. $.offset.setOffset($tip[0], $.extend({
  1103. using: function (props) {
  1104. $tip.css({
  1105. top: Math.round(props.top),
  1106. left: Math.round(props.left)
  1107. })
  1108. }
  1109. }, offset), 0)
  1110. $tip.addClass('in')
  1111. // check to see if placing tip in new offset caused the tip to resize itself
  1112. var actualWidth = $tip[0].offsetWidth
  1113. var actualHeight = $tip[0].offsetHeight
  1114. if (placement == 'top' && actualHeight != height) {
  1115. offset.top = offset.top + height - actualHeight
  1116. }
  1117. var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
  1118. if (delta.left) offset.left += delta.left
  1119. else offset.top += delta.top
  1120. var isVertical = /top|bottom/.test(placement)
  1121. var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
  1122. var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
  1123. $tip.offset(offset)
  1124. this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
  1125. }
  1126. Tooltip.prototype.replaceArrow = function (delta, dimension, isHorizontal) {
  1127. this.arrow()
  1128. .css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
  1129. .css(isHorizontal ? 'top' : 'left', '')
  1130. }
  1131. Tooltip.prototype.setContent = function () {
  1132. var $tip = this.tip()
  1133. var title = this.getTitle()
  1134. $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
  1135. $tip.removeClass('fade in top bottom left right')
  1136. }
  1137. Tooltip.prototype.hide = function (callback) {
  1138. var that = this
  1139. var $tip = this.tip()
  1140. var e = $.Event('hide.bs.' + this.type)
  1141. function complete() {
  1142. if (that.hoverState != 'in') $tip.detach()
  1143. that.$element
  1144. .removeAttr('aria-describedby')
  1145. .trigger('hidden.bs.' + that.type)
  1146. callback && callback()
  1147. }
  1148. this.$element.trigger(e)
  1149. if (e.isDefaultPrevented()) return
  1150. $tip.removeClass('in')
  1151. $.support.transition && this.$tip.hasClass('fade') ?
  1152. $tip
  1153. .one('bsTransitionEnd', complete)
  1154. .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
  1155. complete()
  1156. this.hoverState = null
  1157. return this
  1158. }
  1159. Tooltip.prototype.fixTitle = function () {
  1160. var $e = this.$element
  1161. if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
  1162. $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
  1163. }
  1164. }
  1165. Tooltip.prototype.hasContent = function () {
  1166. return this.getTitle()
  1167. }
  1168. Tooltip.prototype.getPosition = function ($element) {
  1169. $element = $element || this.$element
  1170. var el = $element[0]
  1171. var isBody = el.tagName == 'BODY'
  1172. var elRect = el.getBoundingClientRect()
  1173. if (elRect.width == null) {
  1174. // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
  1175. elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
  1176. }
  1177. var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
  1178. var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
  1179. var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
  1180. return $.extend({}, elRect, scroll, outerDims, elOffset)
  1181. }
  1182. Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
  1183. return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
  1184. placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
  1185. placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
  1186. /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
  1187. }
  1188. Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
  1189. var delta = { top: 0, left: 0 }
  1190. if (!this.$viewport) return delta
  1191. var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
  1192. var viewportDimensions = this.getPosition(this.$viewport)
  1193. if (/right|left/.test(placement)) {
  1194. var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
  1195. var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
  1196. if (topEdgeOffset < viewportDimensions.top) { // top overflow
  1197. delta.top = viewportDimensions.top - topEdgeOffset
  1198. } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
  1199. delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
  1200. }
  1201. } else {
  1202. var leftEdgeOffset = pos.left - viewportPadding
  1203. var rightEdgeOffset = pos.left + viewportPadding + actualWidth
  1204. if (leftEdgeOffset < viewportDimensions.left) { // left overflow
  1205. delta.left = viewportDimensions.left - leftEdgeOffset
  1206. } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
  1207. delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
  1208. }
  1209. }
  1210. return delta
  1211. }
  1212. Tooltip.prototype.getTitle = function () {
  1213. var title
  1214. var $e = this.$element
  1215. var o = this.options
  1216. title = $e.attr('data-original-title')
  1217. || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
  1218. return title
  1219. }
  1220. Tooltip.prototype.getUID = function (prefix) {
  1221. do prefix += ~~(Math.random() * 1000000)
  1222. while (document.getElementById(prefix))
  1223. return prefix
  1224. }
  1225. Tooltip.prototype.tip = function () {
  1226. return (this.$tip = this.$tip || $(this.options.template))
  1227. }
  1228. Tooltip.prototype.arrow = function () {
  1229. return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
  1230. }
  1231. Tooltip.prototype.enable = function () {
  1232. this.enabled = true
  1233. }
  1234. Tooltip.prototype.disable = function () {
  1235. this.enabled = false
  1236. }
  1237. Tooltip.prototype.toggleEnabled = function () {
  1238. this.enabled = !this.enabled
  1239. }
  1240. Tooltip.prototype.toggle = function (e) {
  1241. var self = this
  1242. if (e) {
  1243. self = $(e.currentTarget).data('bs.' + this.type)
  1244. if (!self) {
  1245. self = new this.constructor(e.currentTarget, this.getDelegateOptions())
  1246. $(e.currentTarget).data('bs.' + this.type, self)
  1247. }
  1248. }
  1249. self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
  1250. }
  1251. Tooltip.prototype.destroy = function () {
  1252. var that = this
  1253. clearTimeout(this.timeout)
  1254. this.hide(function () {
  1255. that.$element.off('.' + that.type).removeData('bs.' + that.type)
  1256. })
  1257. }
  1258. // TOOLTIP PLUGIN DEFINITION
  1259. // =========================
  1260. function Plugin(option) {
  1261. return this.each(function () {
  1262. var $this = $(this)
  1263. var data = $this.data('bs.tooltip')
  1264. var options = typeof option == 'object' && option
  1265. var selector = options && options.selector
  1266. if (!data && option == 'destroy') return
  1267. if (selector) {
  1268. if (!data) $this.data('bs.tooltip', (data = {}))
  1269. if (!data[selector]) data[selector] = new Tooltip(this, options)
  1270. } else {
  1271. if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
  1272. }
  1273. if (typeof option == 'string') data[option]()
  1274. })
  1275. }
  1276. var old = $.fn.tooltip
  1277. $.fn.tooltip = Plugin
  1278. $.fn.tooltip.Constructor = Tooltip
  1279. // TOOLTIP NO CONFLICT
  1280. // ===================
  1281. $.fn.tooltip.noConflict = function () {
  1282. $.fn.tooltip = old
  1283. return this
  1284. }
  1285. }(jQuery);
  1286. /* ========================================================================
  1287. * Bootstrap: popover.js v3.3.1
  1288. * http://getbootstrap.com/javascript/#popovers
  1289. * ========================================================================
  1290. * Copyright 2011-2014 Twitter, Inc.
  1291. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  1292. * ======================================================================== */
  1293. +function ($) {
  1294. 'use strict';
  1295. // POPOVER PUBLIC CLASS DEFINITION
  1296. // ===============================
  1297. var Popover = function (element, options) {
  1298. this.init('popover', element, options)
  1299. }
  1300. if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
  1301. Popover.VERSION = '3.3.1'
  1302. Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
  1303. placement: 'right',
  1304. trigger: 'click',
  1305. content: '',
  1306. template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
  1307. })
  1308. // NOTE: POPOVER EXTENDS tooltip.js
  1309. // ================================
  1310. Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
  1311. Popover.prototype.constructor = Popover
  1312. Popover.prototype.getDefaults = function () {
  1313. return Popover.DEFAULTS
  1314. }
  1315. Popover.prototype.setContent = function () {
  1316. var $tip = this.tip()
  1317. var title = this.getTitle()
  1318. var content = this.getContent()
  1319. $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
  1320. $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
  1321. this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
  1322. ](content)
  1323. $tip.removeClass('fade top bottom left right in')
  1324. // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
  1325. // this manually by checking the contents.
  1326. if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
  1327. }
  1328. Popover.prototype.hasContent = function () {
  1329. return this.getTitle() || this.getContent()
  1330. }
  1331. Popover.prototype.getContent = function () {
  1332. var $e = this.$element
  1333. var o = this.options
  1334. return $e.attr('data-content')
  1335. || (typeof o.content == 'function' ?
  1336. o.content.call($e[0]) :
  1337. o.content)
  1338. }
  1339. Popover.prototype.arrow = function () {
  1340. return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
  1341. }
  1342. Popover.prototype.tip = function () {
  1343. if (!this.$tip) this.$tip = $(this.options.template)
  1344. return this.$tip
  1345. }
  1346. // POPOVER PLUGIN DEFINITION
  1347. // =========================
  1348. function Plugin(option) {
  1349. return this.each(function () {
  1350. var $this = $(this)
  1351. var data = $this.data('bs.popover')
  1352. var options = typeof option == 'object' && option
  1353. var selector = options && options.selector
  1354. if (!data && option == 'destroy') return
  1355. if (selector) {
  1356. if (!data) $this.data('bs.popover', (data = {}))
  1357. if (!data[selector]) data[selector] = new Popover(this, options)
  1358. } else {
  1359. if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
  1360. }
  1361. if (typeof option == 'string') data[option]()
  1362. })
  1363. }
  1364. var old = $.fn.popover
  1365. $.fn.popover = Plugin
  1366. $.fn.popover.Constructor = Popover
  1367. // POPOVER NO CONFLICT
  1368. // ===================
  1369. $.fn.popover.noConflict = function () {
  1370. $.fn.popover = old
  1371. return this
  1372. }
  1373. }(jQuery);
  1374. /* ========================================================================
  1375. * Bootstrap: scrollspy.js v3.3.1
  1376. * http://getbootstrap.com/javascript/#scrollspy
  1377. * ========================================================================
  1378. * Copyright 2011-2014 Twitter, Inc.
  1379. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  1380. * ======================================================================== */
  1381. +function ($) {
  1382. 'use strict';
  1383. // SCROLLSPY CLASS DEFINITION
  1384. // ==========================
  1385. function ScrollSpy(element, options) {
  1386. var process = $.proxy(this.process, this)
  1387. this.$body = $('body')
  1388. this.$scrollElement = $(element).is('body') ? $(window) : $(element)
  1389. this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
  1390. this.selector = (this.options.target || '') + ' .nav li > a'
  1391. this.offsets = []
  1392. this.targets = []
  1393. this.activeTarget = null
  1394. this.scrollHeight = 0
  1395. this.$scrollElement.on('scroll.bs.scrollspy', process)
  1396. this.refresh()
  1397. this.process()
  1398. }
  1399. ScrollSpy.VERSION = '3.3.1'
  1400. ScrollSpy.DEFAULTS = {
  1401. offset: 10
  1402. }
  1403. ScrollSpy.prototype.getScrollHeight = function () {
  1404. return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
  1405. }
  1406. ScrollSpy.prototype.refresh = function () {
  1407. var offsetMethod = 'offset'
  1408. var offsetBase = 0
  1409. if (!$.isWindow(this.$scrollElement[0])) {
  1410. offsetMethod = 'position'
  1411. offsetBase = this.$scrollElement.scrollTop()
  1412. }
  1413. this.offsets = []
  1414. this.targets = []
  1415. this.scrollHeight = this.getScrollHeight()
  1416. var self = this
  1417. this.$body
  1418. .find(this.selector)
  1419. .map(function () {
  1420. var $el = $(this)
  1421. var href = $el.data('target') || $el.attr('href')
  1422. var $href = /^#./.test(href) && $(href)
  1423. return ($href
  1424. && $href.length
  1425. && $href.is(':visible')
  1426. && [[$href[offsetMethod]().top + offsetBase, href]]) || null
  1427. })
  1428. .sort(function (a, b) { return a[0] - b[0] })
  1429. .each(function () {
  1430. self.offsets.push(this[0])
  1431. self.targets.push(this[1])
  1432. })
  1433. }
  1434. ScrollSpy.prototype.process = function () {
  1435. var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
  1436. var scrollHeight = this.getScrollHeight()
  1437. var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
  1438. var offsets = this.offsets
  1439. var targets = this.targets
  1440. var activeTarget = this.activeTarget
  1441. var i
  1442. if (this.scrollHeight != scrollHeight) {
  1443. this.refresh()
  1444. }
  1445. if (scrollTop >= maxScroll) {
  1446. return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
  1447. }
  1448. if (activeTarget && scrollTop < offsets[0]) {
  1449. this.activeTarget = null
  1450. return this.clear()
  1451. }
  1452. for (i = offsets.length; i--;) {
  1453. activeTarget != targets[i]
  1454. && scrollTop >= offsets[i]
  1455. && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
  1456. && this.activate(targets[i])
  1457. }
  1458. }
  1459. ScrollSpy.prototype.activate = function (target) {
  1460. this.activeTarget = target
  1461. this.clear()
  1462. var selector = this.selector +
  1463. '[data-target="' + target + '"],' +
  1464. this.selector + '[href="' + target + '"]'
  1465. var active = $(selector)
  1466. .parents('li')
  1467. .addClass('active')
  1468. if (active.parent('.dropdown-menu').length) {
  1469. active = active
  1470. .closest('li.dropdown')
  1471. .addClass('active')
  1472. }
  1473. active.trigger('activate.bs.scrollspy')
  1474. }
  1475. ScrollSpy.prototype.clear = function () {
  1476. $(this.selector)
  1477. .parentsUntil(this.options.target, '.active')
  1478. .removeClass('active')
  1479. }
  1480. // SCROLLSPY PLUGIN DEFINITION
  1481. // ===========================
  1482. function Plugin(option) {
  1483. return this.each(function () {
  1484. var $this = $(this)
  1485. var data = $this.data('bs.scrollspy')
  1486. var options = typeof option == 'object' && option
  1487. if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
  1488. if (typeof option == 'string') data[option]()
  1489. })
  1490. }
  1491. var old = $.fn.scrollspy
  1492. $.fn.scrollspy = Plugin
  1493. $.fn.scrollspy.Constructor = ScrollSpy
  1494. // SCROLLSPY NO CONFLICT
  1495. // =====================
  1496. $.fn.scrollspy.noConflict = function () {
  1497. $.fn.scrollspy = old
  1498. return this
  1499. }
  1500. // SCROLLSPY DATA-API
  1501. // ==================
  1502. $(window).on('load.bs.scrollspy.data-api', function () {
  1503. $('[data-spy="scroll"]').each(function () {
  1504. var $spy = $(this)
  1505. Plugin.call($spy, $spy.data())
  1506. })
  1507. })
  1508. }(jQuery);
  1509. /* ========================================================================
  1510. * Bootstrap: tab.js v3.3.1
  1511. * http://getbootstrap.com/javascript/#tabs
  1512. * ========================================================================
  1513. * Copyright 2011-2014 Twitter, Inc.
  1514. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  1515. * ======================================================================== */
  1516. +function ($) {
  1517. 'use strict';
  1518. // TAB CLASS DEFINITION
  1519. // ====================
  1520. var Tab = function (element) {
  1521. this.element = $(element)
  1522. }
  1523. Tab.VERSION = '3.3.1'
  1524. Tab.TRANSITION_DURATION = 150
  1525. Tab.prototype.show = function () {
  1526. var $this = this.element
  1527. var $ul = $this.closest('ul:not(.dropdown-menu)')
  1528. var selector = $this.data('target')
  1529. if (!selector) {
  1530. selector = $this.attr('href')
  1531. selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
  1532. }
  1533. if ($this.parent('li').hasClass('active')) return
  1534. var $previous = $ul.find('.active:last a')
  1535. var hideEvent = $.Event('hide.bs.tab', {
  1536. relatedTarget: $this[0]
  1537. })
  1538. var showEvent = $.Event('show.bs.tab', {
  1539. relatedTarget: $previous[0]
  1540. })
  1541. $previous.trigger(hideEvent)
  1542. $this.trigger(showEvent)
  1543. if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
  1544. var $target = $(selector)
  1545. this.activate($this.closest('li'), $ul)
  1546. this.activate($target, $target.parent(), function () {
  1547. $previous.trigger({
  1548. type: 'hidden.bs.tab',
  1549. relatedTarget: $this[0]
  1550. })
  1551. $this.trigger({
  1552. type: 'shown.bs.tab',
  1553. relatedTarget: $previous[0]
  1554. })
  1555. })
  1556. }
  1557. Tab.prototype.activate = function (element, container, callback) {
  1558. var $active = container.find('> .active')
  1559. var transition = callback
  1560. && $.support.transition
  1561. && (($active.length && $active.hasClass('fade')) || !!container.find('> .fade').length)
  1562. function next() {
  1563. $active
  1564. .removeClass('active')
  1565. .find('> .dropdown-menu > .active')
  1566. .removeClass('active')
  1567. .end()
  1568. .find('[data-toggle="tab"]')
  1569. .attr('aria-expanded', false)
  1570. element
  1571. .addClass('active')
  1572. .find('[data-toggle="tab"]')
  1573. .attr('aria-expanded', true)
  1574. if (transition) {
  1575. element[0].offsetWidth // reflow for transition
  1576. element.addClass('in')
  1577. } else {
  1578. element.removeClass('fade')
  1579. }
  1580. if (element.parent('.dropdown-menu')) {
  1581. element
  1582. .closest('li.dropdown')
  1583. .addClass('active')
  1584. .end()
  1585. .find('[data-toggle="tab"]')
  1586. .attr('aria-expanded', true)
  1587. }
  1588. callback && callback()
  1589. }
  1590. $active.length && transition ?
  1591. $active
  1592. .one('bsTransitionEnd', next)
  1593. .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
  1594. next()
  1595. $active.removeClass('in')
  1596. }
  1597. // TAB PLUGIN DEFINITION
  1598. // =====================
  1599. function Plugin(option) {
  1600. return this.each(function () {
  1601. var $this = $(this)
  1602. var data = $this.data('bs.tab')
  1603. if (!data) $this.data('bs.tab', (data = new Tab(this)))
  1604. if (typeof option == 'string') data[option]()
  1605. })
  1606. }
  1607. var old = $.fn.tab
  1608. $.fn.tab = Plugin
  1609. $.fn.tab.Constructor = Tab
  1610. // TAB NO CONFLICT
  1611. // ===============
  1612. $.fn.tab.noConflict = function () {
  1613. $.fn.tab = old
  1614. return this
  1615. }
  1616. // TAB DATA-API
  1617. // ============
  1618. var clickHandler = function (e) {
  1619. e.preventDefault()
  1620. Plugin.call($(this), 'show')
  1621. }
  1622. $(document)
  1623. .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
  1624. .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
  1625. }(jQuery);
  1626. /* ========================================================================
  1627. * Bootstrap: affix.js v3.3.1
  1628. * http://getbootstrap.com/javascript/#affix
  1629. * ========================================================================
  1630. * Copyright 2011-2014 Twitter, Inc.
  1631. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  1632. * ======================================================================== */
  1633. +function ($) {
  1634. 'use strict';
  1635. // AFFIX CLASS DEFINITION
  1636. // ======================
  1637. var Affix = function (element, options) {
  1638. this.options = $.extend({}, Affix.DEFAULTS, options)
  1639. this.$target = $(this.options.target)
  1640. .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
  1641. .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
  1642. this.$element = $(element)
  1643. this.affixed =
  1644. this.unpin =
  1645. this.pinnedOffset = null
  1646. this.checkPosition()
  1647. }
  1648. Affix.VERSION = '3.3.1'
  1649. Affix.RESET = 'affix affix-top affix-bottom'
  1650. Affix.DEFAULTS = {
  1651. offset: 0,
  1652. target: window
  1653. }
  1654. Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
  1655. var scrollTop = this.$target.scrollTop()
  1656. var position = this.$element.offset()
  1657. var targetHeight = this.$target.height()
  1658. if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
  1659. if (this.affixed == 'bottom') {
  1660. if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
  1661. return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
  1662. }
  1663. var initializing = this.affixed == null
  1664. var colliderTop = initializing ? scrollTop : position.top
  1665. var colliderHeight = initializing ? targetHeight : height
  1666. if (offsetTop != null && colliderTop <= offsetTop) return 'top'
  1667. if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
  1668. return false
  1669. }
  1670. Affix.prototype.getPinnedOffset = function () {
  1671. if (this.pinnedOffset) return this.pinnedOffset
  1672. this.$element.removeClass(Affix.RESET).addClass('affix')
  1673. var scrollTop = this.$target.scrollTop()
  1674. var position = this.$element.offset()
  1675. return (this.pinnedOffset = position.top - scrollTop)
  1676. }
  1677. Affix.prototype.checkPositionWithEventLoop = function () {
  1678. setTimeout($.proxy(this.checkPosition, this), 1)
  1679. }
  1680. Affix.prototype.checkPosition = function () {
  1681. if (!this.$element.is(':visible')) return
  1682. var height = this.$element.height()
  1683. var offset = this.options.offset
  1684. var offsetTop = offset.top
  1685. var offsetBottom = offset.bottom
  1686. var scrollHeight = $('body').height()
  1687. if (typeof offset != 'object') offsetBottom = offsetTop = offset
  1688. if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
  1689. if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
  1690. var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
  1691. if (this.affixed != affix) {
  1692. if (this.unpin != null) this.$element.css('top', '')
  1693. var affixType = 'affix' + (affix ? '-' + affix : '')
  1694. var e = $.Event(affixType + '.bs.affix')
  1695. this.$element.trigger(e)
  1696. if (e.isDefaultPrevented()) return
  1697. this.affixed = affix
  1698. this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
  1699. this.$element
  1700. .removeClass(Affix.RESET)
  1701. .addClass(affixType)
  1702. .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
  1703. }
  1704. if (affix == 'bottom') {
  1705. this.$element.offset({
  1706. top: scrollHeight - height - offsetBottom
  1707. })
  1708. }
  1709. }
  1710. // AFFIX PLUGIN DEFINITION
  1711. // =======================
  1712. function Plugin(option) {
  1713. return this.each(function () {
  1714. var $this = $(this)
  1715. var data = $this.data('bs.affix')
  1716. var options = typeof option == 'object' && option
  1717. if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
  1718. if (typeof option == 'string') data[option]()
  1719. })
  1720. }
  1721. var old = $.fn.affix
  1722. $.fn.affix = Plugin
  1723. $.fn.affix.Constructor = Affix
  1724. // AFFIX NO CONFLICT
  1725. // =================
  1726. $.fn.affix.noConflict = function () {
  1727. $.fn.affix = old
  1728. return this
  1729. }
  1730. // AFFIX DATA-API
  1731. // ==============
  1732. $(window).on('load', function () {
  1733. $('[data-spy="affix"]').each(function () {
  1734. var $spy = $(this)
  1735. var data = $spy.data()
  1736. data.offset = data.offset || {}
  1737. if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
  1738. if (data.offsetTop != null) data.offset.top = data.offsetTop
  1739. Plugin.call($spy, data)
  1740. })
  1741. })
  1742. }(jQuery);