From d1fbe200f46002431cdeebf965c4b789ef7ed267 Mon Sep 17 00:00:00 2001 From: fat Date: Wed, 6 May 2015 13:34:14 -0700 Subject: remove closureness from plugins --- js/.jscsrc | 5 + js/affix.js | 162 ++ js/alert.js | 280 +--- js/button.js | 279 ++-- js/carousel.js | 669 ++------ js/collapse.js | 526 ++---- js/dropdown.js | 377 ++--- js/externs/bootstrap.js | 6 - js/externs/jQuery.js | 2159 ------------------------- js/modal.js | 771 +++------ js/popover.js | 317 +--- js/scrollspy.js | 424 ++--- js/tab.js | 397 ++--- js/tests/closure.html | 83 - js/tests/index.html | 4 +- js/tests/unit/affix.js | 107 ++ js/tests/unit/button.js | 160 +- js/tests/unit/carousel.js | 300 ++-- js/tests/unit/collapse.js | 2 +- js/tests/unit/modal.js | 249 ++- js/tests/unit/phantom.js | 4 +- js/tests/unit/popover.js | 44 +- js/tests/unit/tooltip.js | 657 +++++--- js/tests/visual/affix-with-sticky-footer.html | 317 ++++ js/tests/visual/affix.html | 306 ++++ js/tests/visual/alert.html | 9 +- js/tests/visual/button.html | 13 +- js/tests/visual/carousel.html | 15 +- js/tests/visual/collapse.html | 9 +- js/tests/visual/dropdown.html | 9 +- js/tests/visual/modal.html | 90 +- js/tests/visual/popover.html | 9 +- js/tests/visual/scrollspy.html | 9 +- js/tests/visual/tab.html | 9 +- js/tests/visual/tooltip.html | 9 +- js/tooltip.js | 1124 +++++-------- js/util.js | 165 -- 37 files changed, 3482 insertions(+), 6593 deletions(-) create mode 100644 js/affix.js delete mode 100644 js/externs/bootstrap.js delete mode 100644 js/externs/jQuery.js delete mode 100644 js/tests/closure.html create mode 100644 js/tests/unit/affix.js create mode 100644 js/tests/visual/affix-with-sticky-footer.html create mode 100644 js/tests/visual/affix.html delete mode 100644 js/util.js (limited to 'js') diff --git a/js/.jscsrc b/js/.jscsrc index caf1938f2..9544d2d2b 100644 --- a/js/.jscsrc +++ b/js/.jscsrc @@ -17,8 +17,11 @@ "requireCamelCaseOrUpperCaseIdentifiers": true, "requireCapitalizedConstructors": true, "requireCommaBeforeLineBreak": true, + "requireDollarBeforejQueryAssignment": true, "requireDotNotation": true, "requireLineFeedAtFileEnd": true, + "requirePaddingNewLinesAfterUseStrict": true, + "requirePaddingNewLinesBeforeExport": true, "requireSpaceAfterBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!==", ">", "<", ">=", "<="], "requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch"], "requireSpaceAfterLineComment": true, @@ -31,7 +34,9 @@ "requireSpacesInFunctionExpression": { "beforeOpeningCurlyBrace": true }, "requireSpacesInNamedFunctionExpression": { "beforeOpeningCurlyBrace": true }, "requireSpacesInsideObjectBrackets": "allButNested", + "validateAlignedFunctionParameters": true, "validateIndentation": 2, "validateLineBreaks": "LF", + "validateNewlineAfterArrayElements": true, "validateQuoteMarks": "'" } diff --git a/js/affix.js b/js/affix.js new file mode 100644 index 000000000..999737912 --- /dev/null +++ b/js/affix.js @@ -0,0 +1,162 @@ +/* ======================================================================== + * Bootstrap: affix.js v3.3.4 + * http://getbootstrap.com/javascript/#affix + * ======================================================================== + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // AFFIX CLASS DEFINITION + // ====================== + + var Affix = function (element, options) { + this.options = $.extend({}, Affix.DEFAULTS, options) + + this.$target = $(this.options.target) + .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this)) + .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this)) + + this.$element = $(element) + this.affixed = null + this.unpin = null + this.pinnedOffset = null + + this.checkPosition() + } + + Affix.VERSION = '3.3.4' + + Affix.RESET = 'affix affix-top affix-bottom' + + Affix.DEFAULTS = { + offset: 0, + target: window + } + + Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) { + var scrollTop = this.$target.scrollTop() + var position = this.$element.offset() + var targetHeight = this.$target.height() + + if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false + + if (this.affixed == 'bottom') { + if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom' + return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom' + } + + var initializing = this.affixed == null + var colliderTop = initializing ? scrollTop : position.top + var colliderHeight = initializing ? targetHeight : height + + if (offsetTop != null && scrollTop <= offsetTop) return 'top' + if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom' + + return false + } + + Affix.prototype.getPinnedOffset = function () { + if (this.pinnedOffset) return this.pinnedOffset + this.$element.removeClass(Affix.RESET).addClass('affix') + var scrollTop = this.$target.scrollTop() + var position = this.$element.offset() + return (this.pinnedOffset = position.top - scrollTop) + } + + Affix.prototype.checkPositionWithEventLoop = function () { + setTimeout($.proxy(this.checkPosition, this), 1) + } + + Affix.prototype.checkPosition = function () { + if (!this.$element.is(':visible')) return + + var height = this.$element.height() + var offset = this.options.offset + var offsetTop = offset.top + var offsetBottom = offset.bottom + var scrollHeight = Math.max($(document).height(), $(document.body).height()) + + if (typeof offset != 'object') offsetBottom = offsetTop = offset + if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element) + if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element) + + var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom) + + if (this.affixed != affix) { + if (this.unpin != null) this.$element.css('top', '') + + var affixType = 'affix' + (affix ? '-' + affix : '') + var e = $.Event(affixType + '.bs.affix') + + this.$element.trigger(e) + + if (e.isDefaultPrevented()) return + + this.affixed = affix + this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null + + this.$element + .removeClass(Affix.RESET) + .addClass(affixType) + .trigger(affixType.replace('affix', 'affixed') + '.bs.affix') + } + + if (affix == 'bottom') { + this.$element.offset({ + top: scrollHeight - height - offsetBottom + }) + } + } + + + // AFFIX PLUGIN DEFINITION + // ======================= + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.affix') + var options = typeof option == 'object' && option + + if (!data) $this.data('bs.affix', (data = new Affix(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.affix + + $.fn.affix = Plugin + $.fn.affix.Constructor = Affix + + + // AFFIX NO CONFLICT + // ================= + + $.fn.affix.noConflict = function () { + $.fn.affix = old + return this + } + + + // AFFIX DATA-API + // ============== + + $(window).on('load', function () { + $('[data-spy="affix"]').each(function () { + var $spy = $(this) + var data = $spy.data() + + data.offset = data.offset || {} + + if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom + if (data.offsetTop != null) data.offset.top = data.offsetTop + + Plugin.call($spy, data) + }) + }) + +}(jQuery); diff --git a/js/alert.js b/js/alert.js index 38bce06a4..1925ef011 100644 --- a/js/alert.js +++ b/js/alert.js @@ -1,260 +1,94 @@ -/** ======================================================================= - * Bootstrap: alert.js v4.0.0 +/* ======================================================================== + * Bootstrap: alert.js v3.3.4 * http://getbootstrap.com/javascript/#alerts * ======================================================================== * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== - * @fileoverview - Bootstrap's generic alert component. Add dismiss - * functionality to all alert messages with this plugin. - * - * Public Methods & Properties: - * - * + $.alert - * + $.alert.noConflict - * + $.alert.Constructor - * + $.alert.Constructor.VERSION - * + $.alert.Constructor.prototype.close - * - * ======================================================================== - */ - -'use strict'; - - -/** - * Our Alert class. - * @param {Element=} opt_element - * @constructor - */ -var Alert = function (opt_element) { - if (opt_element) { - $(opt_element).on('click', Alert._DISMISS_SELECTOR, Alert._handleDismiss(this)) - } -} - - -/** - * @const - * @type {string} - */ -Alert['VERSION'] = '4.0.0' - - -/** - * @const - * @type {string} - * @private - */ -Alert._NAME = 'alert' - - -/** - * @const - * @type {string} - * @private - */ -Alert._DATA_KEY = 'bs.alert' - - -/** - * @const - * @type {string} - * @private - */ -Alert._DISMISS_SELECTOR = '[data-dismiss="alert"]' - - -/** - * @const - * @type {number} - * @private - */ -Alert._TRANSITION_DURATION = 150 - + * ======================================================================== */ -/** - * @const - * @type {Function} - * @private - */ -Alert._JQUERY_NO_CONFLICT = $.fn[Alert._NAME] ++function ($) { + 'use strict'; -/** - * @const - * @enum {string} - * @private - */ -Alert._Event = { - CLOSE : 'close.bs.alert', - CLOSED : 'closed.bs.alert' -} + // ALERT CLASS DEFINITION + // ====================== + var dismiss = '[data-dismiss="alert"]' + var Alert = function (el) { + $(el).on('click', dismiss, this.close) + } -/** - * @const - * @enum {string} - * @private - */ -Alert._ClassName = { - ALERT : 'alert', - FADE : 'fade', - IN : 'in' -} + Alert.VERSION = '3.3.4' + Alert.TRANSITION_DURATION = 150 -/** - * Provides the jQuery Interface for the alert component. - * @param {string=} opt_config - * @this {jQuery} - * @return {jQuery} - * @private - */ -Alert._jQueryInterface = function (opt_config) { - return this.each(function () { - var $this = $(this) - var data = $this.data(Alert._DATA_KEY) + Alert.prototype.close = function (e) { + var $this = $(this) + var selector = $this.attr('data-target') - if (!data) { - data = new Alert(this) - $this.data(Alert._DATA_KEY, data) + if (!selector) { + selector = $this.attr('href') + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 } - if (opt_config === 'close') { - data[opt_config](this) - } - }) -} + var $parent = $(selector) + if (e) e.preventDefault() -/** - * Close the alert component - * @param {Alert} alertInstance - * @return {Function} - * @private - */ -Alert._handleDismiss = function (alertInstance) { - return function (event) { - if (event) { - event.preventDefault() + if (!$parent.length) { + $parent = $this.closest('.alert') } - alertInstance['close'](this) - } -} - + $parent.trigger(e = $.Event('close.bs.alert')) -/** - * Close the alert component - * @param {Element} element - */ -Alert.prototype['close'] = function (element) { - var rootElement = this._getRootElement(element) - var customEvent = this._triggerCloseEvent(rootElement) + if (e.isDefaultPrevented()) return - if (customEvent.isDefaultPrevented()) return + $parent.removeClass('in') - this._removeElement(rootElement) -} - - -/** - * Tries to get the alert's root element - * @return {Element} - * @private - */ -Alert.prototype._getRootElement = function (element) { - var parent = false - var selector = Bootstrap.getSelectorFromElement(element) - - if (selector) { - parent = $(selector)[0] - } + function removeElement() { + // detach from parent, fire event then clean up data + $parent.detach().trigger('closed.bs.alert').remove() + } - if (!parent) { - parent = $(element).closest('.' + Alert._ClassName.ALERT)[0] + $.support.transition && $parent.hasClass('fade') ? + $parent + .one('bsTransitionEnd', removeElement) + .emulateTransitionEnd(Alert.TRANSITION_DURATION) : + removeElement() } - return parent -} - -/** - * Trigger close event on element - * @return {$.Event} - * @private - */ -Alert.prototype._triggerCloseEvent = function (element) { - var closeEvent = $.Event(Alert._Event.CLOSE) - $(element).trigger(closeEvent) - return closeEvent -} + // ALERT PLUGIN DEFINITION + // ======================= + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.alert') -/** - * Trigger closed event and remove element from dom - * @private - */ -Alert.prototype._removeElement = function (element) { - $(element).removeClass(Alert._ClassName.IN) - - if (!Bootstrap.transition || !$(element).hasClass(Alert._ClassName.FADE)) { - this._destroyElement(element) - return + if (!data) $this.data('bs.alert', (data = new Alert(this))) + if (typeof option == 'string') data[option].call($this) + }) } - $(element) - .one(Bootstrap.TRANSITION_END, this._destroyElement.bind(this, element)) - .emulateTransitionEnd(Alert._TRANSITION_DURATION) -} - + var old = $.fn.alert -/** - * clean up any lingering jquery data and kill element - * @private - */ -Alert.prototype._destroyElement = function (element) { - $(element) - .detach() - .trigger(Alert._Event.CLOSED) - .remove() -} + $.fn.alert = Plugin + $.fn.alert.Constructor = Alert -/** - * ------------------------------------------------------------------------ - * jQuery Interface + noConflict implementaiton - * ------------------------------------------------------------------------ - */ - -/** - * @const - * @type {Function} - */ -$.fn[Alert._NAME] = Alert._jQueryInterface - - -/** - * @const - * @type {Function} - */ -$.fn[Alert._NAME]['Constructor'] = Alert + // ALERT NO CONFLICT + // ================= + $.fn.alert.noConflict = function () { + $.fn.alert = old + return this + } -/** - * @return {Function} - */ -$.fn[Alert._NAME]['noConflict'] = function () { - $.fn[Alert._NAME] = Alert._JQUERY_NO_CONFLICT - return Alert._jQueryInterface -} + // ALERT DATA-API + // ============== -/** - * ------------------------------------------------------------------------ - * Data Api implementation - * ------------------------------------------------------------------------ - */ + $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) -$(document).on('click.bs.alert.data-api', Alert._DISMISS_SELECTOR, Alert._handleDismiss(new Alert)) +}(jQuery); diff --git a/js/button.js b/js/button.js index 8ee2d6b08..3e2e34512 100644 --- a/js/button.js +++ b/js/button.js @@ -1,207 +1,120 @@ -/** ======================================================================= - * Bootstrap: button.js v4.0.0 +/* ======================================================================== + * Bootstrap: button.js v3.3.4 * http://getbootstrap.com/javascript/#buttons * ======================================================================== * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== - * @fileoverview - Bootstrap's generic button component. - * - * Note (@fat): Deprecated "setState" – imo, better solutions for managing a - * buttons state should exist outside this plugin. - * - * Public Methods & Properties: - * - * + $.button - * + $.button.noConflict - * + $.button.Constructor - * + $.button.Constructor.VERSION - * + $.button.Constructor.prototype.toggle - * - * ======================================================================== - */ - -'use strict'; - - -/** - * Our Button class. - * @param {Element!} element - * @constructor - */ -var Button = function (element) { - - /** @private {Element} */ - this._element = element - -} - - -/** - * @const - * @type {string} - */ -Button['VERSION'] = '4.0.0' - - -/** - * @const - * @type {string} - * @private - */ -Button._NAME = 'button' - - -/** - * @const - * @type {string} - * @private - */ -Button._DATA_KEY = 'bs.button' - - -/** - * @const - * @type {Function} - * @private - */ -Button._JQUERY_NO_CONFLICT = $.fn[Button._NAME] - - -/** - * @const - * @enum {string} - * @private - */ -Button._ClassName = { - ACTIVE : 'active', - BUTTON : 'btn', - FOCUS : 'focus' -} - - -/** - * @const - * @enum {string} - * @private - */ -Button._Selector = { - DATA_TOGGLE_CARROT : '[data-toggle^="button"]', - DATA_TOGGLE : '[data-toggle="buttons"]', - INPUT : 'input', - ACTIVE : '.active', - BUTTON : '.btn' -} - - -/** - * Provides the jQuery Interface for the Button component. - * @param {string=} opt_config - * @this {jQuery} - * @return {jQuery} - * @private - */ -Button._jQueryInterface = function (opt_config) { - return this.each(function () { - var data = $(this).data(Button._DATA_KEY) - - if (!data) { - data = new Button(this) - $(this).data(Button._DATA_KEY, data) - } + * ======================================================================== */ - if (opt_config === 'toggle') { - data[opt_config]() - } - }) -} - - -/** - * Toggle's the button active state - */ -Button.prototype['toggle'] = function () { - var triggerChangeEvent = true - var rootElement = $(this._element).closest(Button._Selector.DATA_TOGGLE)[0] - - if (rootElement) { - var input = $(this._element).find(Button._Selector.INPUT)[0] - if (input) { - if (input.type == 'radio') { - if (input.checked && $(this._element).hasClass(Button._ClassName.ACTIVE)) { - triggerChangeEvent = false - } else { - var activeElement = $(rootElement).find(Button._Selector.ACTIVE)[0] - if (activeElement) { - $(activeElement).removeClass(Button._ClassName.ACTIVE) - } - } + ++function ($) { + 'use strict'; + + // BUTTON PUBLIC CLASS DEFINITION + // ============================== + + var Button = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, Button.DEFAULTS, options) + this.isLoading = false + } + + Button.VERSION = '3.3.4' + + Button.DEFAULTS = { + loadingText: 'loading...' + } + + Button.prototype.setState = function (state) { + var d = 'disabled' + var $el = this.$element + var val = $el.is('input') ? 'val' : 'html' + var data = $el.data() + + state += 'Text' + + if (data.resetText == null) $el.data('resetText', $el[val]()) + + // push to event loop to allow forms to submit + setTimeout($.proxy(function () { + $el[val](data[state] == null ? this.options[state] : data[state]) + + if (state == 'loadingText') { + this.isLoading = true + $el.addClass(d).attr(d, d) + } else if (this.isLoading) { + this.isLoading = false + $el.removeClass(d).removeAttr(d) } + }, this), 0) + } - if (triggerChangeEvent) { - input.checked = !$(this._element).hasClass(Button._ClassName.ACTIVE) - $(this._element).trigger('change') + Button.prototype.toggle = function () { + var changed = true + var $parent = this.$element.closest('[data-toggle="buttons"]') + + if ($parent.length) { + var $input = this.$element.find('input') + if ($input.prop('type') == 'radio') { + if ($input.prop('checked')) changed = false + $parent.find('.active').removeClass('active') + this.$element.addClass('active') + } else if ($input.prop('type') == 'checkbox') { + if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false + this.$element.toggleClass('active') } + $input.prop('checked', this.$element.hasClass('active')) + if (changed) $input.trigger('change') + } else { + this.$element.attr('aria-pressed', !this.$element.hasClass('active')) + this.$element.toggleClass('active') } - } else { - this._element.setAttribute('aria-pressed', !$(this._element).hasClass(Button._ClassName.ACTIVE)) } - if (triggerChangeEvent) { - $(this._element).toggleClass(Button._ClassName.ACTIVE) - } -} + // BUTTON PLUGIN DEFINITION + // ======================== -/** - * ------------------------------------------------------------------------ - * jQuery Interface + noConflict implementaiton - * ------------------------------------------------------------------------ - */ + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.button') + var options = typeof option == 'object' && option -/** - * @const - * @type {Function} - */ -$.fn[Button._NAME] = Button._jQueryInterface + if (!data) $this.data('bs.button', (data = new Button(this, options))) + if (option == 'toggle') data.toggle() + else if (option) data.setState(option) + }) + } -/** - * @const - * @type {Function} - */ -$.fn[Button._NAME]['Constructor'] = Button + var old = $.fn.button + $.fn.button = Plugin + $.fn.button.Constructor = Button -/** - * @const - * @type {Function} - */ -$.fn[Button._NAME]['noConflict'] = function () { - $.fn[Button._NAME] = Button._JQUERY_NO_CONFLICT - return this -} + // BUTTON NO CONFLICT + // ================== -/** - * ------------------------------------------------------------------------ - * Data Api implementation - * ------------------------------------------------------------------------ - */ + $.fn.button.noConflict = function () { + $.fn.button = old + return this + } -$(document) - .on('click.bs.button.data-api', Button._Selector.DATA_TOGGLE_CARROT, function (event) { - event.preventDefault() - var button = event.target + // BUTTON DATA-API + // =============== - if (!$(button).hasClass(Button._ClassName.BUTTON)) { - button = $(button).closest(Button._Selector.BUTTON) - } + $(document) + .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { + var $btn = $(e.target) + if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') + Plugin.call($btn, 'toggle') + if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault() + }) + .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) { + $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type)) + }) - Button._jQueryInterface.call($(button), 'toggle') - }) - .on('focus.bs.button.data-api blur.bs.button.data-api', Button._Selector.DATA_TOGGLE_CARROT, function (event) { - var button = $(event.target).closest(Button._Selector.BUTTON)[0] - $(button).toggleClass(Button._ClassName.FOCUS, /^focus(in)?$/.test(event.type)) - }) +}(jQuery); diff --git a/js/carousel.js b/js/carousel.js index 8f33f4860..a38ef14d0 100644 --- a/js/carousel.js +++ b/js/carousel.js @@ -1,576 +1,237 @@ -/** ======================================================================= - * Bootstrap: carousel.js v4.0.0 +/* ======================================================================== + * Bootstrap: carousel.js v3.3.4 * http://getbootstrap.com/javascript/#carousel * ======================================================================== * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== - * @fileoverview - Bootstrap's carousel. A slideshow component for cycling - * through elements, like a carousel. Nested carousels are not supported. - * - * Public Methods & Properties: - * - * + $.carousel - * + $.carousel.noConflict - * + $.carousel.Constructor - * + $.carousel.Constructor.VERSION - * + $.carousel.Constructor.Defaults - * + $.carousel.Constructor.Defaults.interval - * + $.carousel.Constructor.Defaults.pause - * + $.carousel.Constructor.Defaults.wrap - * + $.carousel.Constructor.Defaults.keyboard - * + $.carousel.Constructor.Defaults.slide - * + $.carousel.Constructor.prototype.next - * + $.carousel.Constructor.prototype.prev - * + $.carousel.Constructor.prototype.pause - * + $.carousel.Constructor.prototype.cycle - * - * ======================================================================== - */ - -'use strict'; - - -/** - * Our carousel class. - * @param {Element!} element - * @param {Object=} opt_config - * @constructor - */ -var Carousel = function (element, opt_config) { - - /** @private {Element} */ - this._element = $(element)[0] - - /** @private {Element} */ - this._indicatorsElement = $(this._element).find(Carousel._Selector.INDICATORS)[0] - - /** @private {?Object} */ - this._config = opt_config || null - - /** @private {boolean} */ - this._isPaused = false - - /** @private {boolean} */ - this._isSliding = false - - /** @private {?number} */ - this._interval = null - - /** @private {?Element} */ - this._activeElement = null - - /** @private {?Array} */ - this._items = null - - this._addEventListeners() - -} - - -/** - * @const - * @type {string} - */ -Carousel['VERSION'] = '4.0.0' - - -/** - * @const - * @type {Object} - */ -Carousel['Defaults'] = { - 'interval' : 5000, - 'pause' : 'hover', - 'wrap' : true, - 'keyboard' : true, - 'slide' : false -} - - -/** - * @const - * @type {string} - * @private - */ -Carousel._NAME = 'carousel' - - -/** - * @const - * @type {string} - * @private - */ -Carousel._DATA_KEY = 'bs.carousel' - - -/** - * @const - * @type {number} - * @private - */ -Carousel._TRANSITION_DURATION = 600 - - -/** - * @const - * @enum {string} - * @private - */ -Carousel._Direction = { - NEXT : 'next', - PREVIOUS : 'prev' -} - - -/** - * @const - * @enum {string} - * @private - */ -Carousel._Event = { - SLIDE : 'slide.bs.carousel', - SLID : 'slid.bs.carousel' -} - - -/** - * @const - * @enum {string} - * @private - */ -Carousel._ClassName = { - CAROUSEL : 'carousel', - ACTIVE : 'active', - SLIDE : 'slide', - RIGHT : 'right', - LEFT : 'left', - ITEM : 'carousel-item' -} - - -/** - * @const - * @enum {string} - * @private - */ -Carousel._Selector = { - ACTIVE : '.active', - ACTIVE_ITEM : '.active.carousel-item', - ITEM : '.carousel-item', - NEXT_PREV : '.next, .prev', - INDICATORS : '.carousel-indicators' -} - - -/** - * @const - * @type {Function} - * @private - */ -Carousel._JQUERY_NO_CONFLICT = $.fn[Carousel._NAME] - - -/** - * @param {Object=} opt_config - * @this {jQuery} - * @return {jQuery} - * @private - */ -Carousel._jQueryInterface = function (opt_config) { - return this.each(function () { - var data = $(this).data(Carousel._DATA_KEY) - var config = $.extend({}, Carousel['Defaults'], $(this).data(), typeof opt_config == 'object' && opt_config) - var action = typeof opt_config == 'string' ? opt_config : config.slide - - if (!data) { - data = new Carousel(this, config) - $(this).data(Carousel._DATA_KEY, data) - } - - if (typeof opt_config == 'number') { - data.to(opt_config) - - } else if (action) { - data[action]() - - } else if (config.interval) { - data['pause']() - data['cycle']() - } - }) -} + * ======================================================================== */ -/** - * Click handler for data api - * @param {Event} event - * @this {Element} - * @private - */ -Carousel._dataApiClickHandler = function (event) { - var selector = Bootstrap.getSelectorFromElement(this) ++function ($) { + 'use strict'; - if (!selector) { - return - } - - var target = $(selector)[0] - - if (!target || !$(target).hasClass(Carousel._ClassName.CAROUSEL)) { - return - } + // CAROUSEL CLASS DEFINITION + // ========================= - var config = $.extend({}, $(target).data(), $(this).data()) + var Carousel = function (element, options) { + this.$element = $(element) + this.$indicators = this.$element.find('.carousel-indicators') + this.options = options + this.paused = null + this.sliding = null + this.interval = null + this.$active = null + this.$items = null - var slideIndex = this.getAttribute('data-slide-to') - if (slideIndex) { - config.interval = false - } - - Carousel._jQueryInterface.call($(target), config) + this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)) - if (slideIndex) { - $(target).data(Carousel._DATA_KEY).to(slideIndex) + this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element + .on('mouseenter.bs.carousel', $.proxy(this.pause, this)) + .on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) } - event.preventDefault() -} - - -/** - * Advance the carousel to the next slide - */ -Carousel.prototype['next'] = function () { - if (!this._isSliding) { - this._slide(Carousel._Direction.NEXT) - } -} + Carousel.VERSION = '3.3.4' + Carousel.TRANSITION_DURATION = 600 -/** - * Return the carousel to the previous slide - */ -Carousel.prototype['prev'] = function () { - if (!this._isSliding) { - this._slide(Carousel._Direction.PREVIOUS) + Carousel.DEFAULTS = { + interval: 5000, + pause: 'hover', + wrap: true, + keyboard: true } -} + Carousel.prototype.keydown = function (e) { + if (/input|textarea/i.test(e.target.tagName)) return + switch (e.which) { + case 37: this.prev(); break + case 39: this.next(); break + default: return + } -/** - * Pause the carousel cycle - * @param {Event=} opt_event - */ -Carousel.prototype['pause'] = function (opt_event) { - if (!opt_event) { - this._isPaused = true + e.preventDefault() } - if ($(this._element).find(Carousel._Selector.NEXT_PREV)[0] && Bootstrap.transition) { - $(this._element).trigger(Bootstrap.transition.end) - this['cycle'](true) - } + Carousel.prototype.cycle = function (e) { + e || (this.paused = false) - clearInterval(this._interval) - this._interval = null -} + this.interval && clearInterval(this.interval) + this.options.interval + && !this.paused + && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) -/** - * Cycle to the next carousel item - * @param {Event|boolean=} opt_event - */ -Carousel.prototype['cycle'] = function (opt_event) { - if (!opt_event) { - this._isPaused = false + return this } - if (this._interval) { - clearInterval(this._interval) - this._interval = null + Carousel.prototype.getItemIndex = function (item) { + this.$items = item.parent().children('.item') + return this.$items.index(item || this.$active) } - if (this._config['interval'] && !this._isPaused) { - this._interval = setInterval(this['next'].bind(this), this._config['interval']) + Carousel.prototype.getItemForDirection = function (direction, active) { + var activeIndex = this.getItemIndex(active) + var willWrap = (direction == 'prev' && activeIndex === 0) + || (direction == 'next' && activeIndex == (this.$items.length - 1)) + if (willWrap && !this.options.wrap) return active + var delta = direction == 'prev' ? -1 : 1 + var itemIndex = (activeIndex + delta) % this.$items.length + return this.$items.eq(itemIndex) } -} - -/** - * @return {Object} - */ -Carousel.prototype['getConfig'] = function () { - return this._config -} + Carousel.prototype.to = function (pos) { + var that = this + var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active')) + if (pos > (this.$items.length - 1) || pos < 0) return -/** - * Move active carousel item to specified index - * @param {number} index - */ -Carousel.prototype.to = function (index) { - this._activeElement = $(this._element).find(Carousel._Selector.ACTIVE_ITEM)[0] + if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" + if (activeIndex == pos) return this.pause().cycle() - var activeIndex = this._getItemIndex(this._activeElement) - - if (index > (this._items.length - 1) || index < 0) { - return - } - - if (this._isSliding) { - $(this._element).one(Carousel._Event.SLID, function () { this.to(index) }.bind(this)) - return + return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos)) } - if (activeIndex == index) { - this['pause']() - this['cycle']() - return - } + Carousel.prototype.pause = function (e) { + e || (this.paused = true) - var direction = index > activeIndex ? - Carousel._Direction.NEXT : - Carousel._Direction.PREVIOUS - - this._slide(direction, this._items[index]) -} + if (this.$element.find('.next, .prev').length && $.support.transition) { + this.$element.trigger($.support.transition.end) + this.cycle(true) + } + this.interval = clearInterval(this.interval) -/** - * Add event listeners to root element - * @private - */ -Carousel.prototype._addEventListeners = function () { - if (this._config['keyboard']) { - $(this._element).on('keydown.bs.carousel', this._keydown.bind(this)) + return this } - if (this._config['pause'] == 'hover' && !('ontouchstart' in document.documentElement)) { - $(this._element) - .on('mouseenter.bs.carousel', this['pause'].bind(this)) - .on('mouseleave.bs.carousel', this['cycle'].bind(this)) + Carousel.prototype.next = function () { + if (this.sliding) return + return this.slide('next') } -} - - -/** - * Keydown handler - * @param {Event} event - * @private - */ -Carousel.prototype._keydown = function (event) { - event.preventDefault() - if (/input|textarea/i.test(event.target.tagName)) return - - switch (event.which) { - case 37: this['prev'](); break - case 39: this['next'](); break - default: return - } -} - - -/** - * Get item index - * @param {Element} element - * @return {number} - * @private - */ -Carousel.prototype._getItemIndex = function (element) { - this._items = $.makeArray($(element).parent().find(Carousel._Selector.ITEM)) - - return this._items.indexOf(element) -} - - -/** - * Get next displayed item based on direction - * @param {Carousel._Direction} direction - * @param {Element} activeElement - * @return {Element} - * @private - */ -Carousel.prototype._getItemByDirection = function (direction, activeElement) { - var activeIndex = this._getItemIndex(activeElement) - var isGoingToWrap = (direction === Carousel._Direction.PREVIOUS && activeIndex === 0) || - (direction === Carousel._Direction.NEXT && activeIndex == (this._items.length - 1)) - - if (isGoingToWrap && !this._config['wrap']) { - return activeElement + Carousel.prototype.prev = function () { + if (this.sliding) return + return this.slide('prev') } - var delta = direction == Carousel._Direction.PREVIOUS ? -1 : 1 - var itemIndex = (activeIndex + delta) % this._items.length - - return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex] -} - + Carousel.prototype.slide = function (type, next) { + var $active = this.$element.find('.item.active') + var $next = next || this.getItemForDirection(type, $active) + var isCycling = this.interval + var direction = type == 'next' ? 'left' : 'right' + var that = this -/** - * Trigger slide event on element - * @param {Element} relatedTarget - * @param {Carousel._ClassName} directionalClassname - * @return {$.Event} - * @private - */ -Carousel.prototype._triggerSlideEvent = function (relatedTarget, directionalClassname) { - var slideEvent = $.Event(Carousel._Event.SLIDE, { - relatedTarget: relatedTarget, - direction: directionalClassname - }) - - $(this._element).trigger(slideEvent) + if ($next.hasClass('active')) return (this.sliding = false) - return slideEvent -} + var relatedTarget = $next[0] + var slideEvent = $.Event('slide.bs.carousel', { + relatedTarget: relatedTarget, + direction: direction + }) + this.$element.trigger(slideEvent) + if (slideEvent.isDefaultPrevented()) return + this.sliding = true -/** - * Set the active indicator if available - * @param {Element} element - * @private - */ -Carousel.prototype._setActiveIndicatorElement = function (element) { - if (this._indicatorsElement) { - $(this._indicatorsElement) - .find(Carousel._Selector.ACTIVE) - .removeClass(Carousel._ClassName.ACTIVE) + isCycling && this.pause() - var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)] - if (nextIndicator) { - $(nextIndicator).addClass(Carousel._ClassName.ACTIVE) + if (this.$indicators.length) { + this.$indicators.find('.active').removeClass('active') + var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)]) + $nextIndicator && $nextIndicator.addClass('active') } - } -} - -/** - * Slide the carousel element in a direction - * @param {Carousel._Direction} direction - * @param {Element=} opt_nextElement - */ -Carousel.prototype._slide = function (direction, opt_nextElement) { - var activeElement = $(this._element).find(Carousel._Selector.ACTIVE_ITEM)[0] - var nextElement = opt_nextElement || activeElement && this._getItemByDirection(direction, activeElement) - - var isCycling = !!this._interval + var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid" + if ($.support.transition && this.$element.hasClass('slide')) { + $next.addClass(type) + $next[0].offsetWidth // force reflow + $active.addClass(direction) + $next.addClass(direction) + $active + .one('bsTransitionEnd', function () { + $next.removeClass([type, direction].join(' ')).addClass('active') + $active.removeClass(['active', direction].join(' ')) + that.sliding = false + setTimeout(function () { + that.$element.trigger(slidEvent) + }, 0) + }) + .emulateTransitionEnd(Carousel.TRANSITION_DURATION) + } else { + $active.removeClass('active') + $next.addClass('active') + this.sliding = false + this.$element.trigger(slidEvent) + } - var directionalClassName = direction == Carousel._Direction.NEXT ? - Carousel._ClassName.LEFT : - Carousel._ClassName.RIGHT + isCycling && this.cycle() - if (nextElement && $(nextElement).hasClass(Carousel._ClassName.ACTIVE)) { - this._isSliding = false - return + return this } - var slideEvent = this._triggerSlideEvent(nextElement, directionalClassName) - if (slideEvent.isDefaultPrevented()) { - return - } - if (!activeElement || !nextElement) { - // some weirdness is happening, so we bail (maybe throw exception here alerting user that they're dom is off - return - } + // CAROUSEL PLUGIN DEFINITION + // ========================== - this._isSliding = true + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.carousel') + var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) + var action = typeof option == 'string' ? option : options.slide - if (isCycling) { - this['pause']() + if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) + if (typeof option == 'number') data.to(option) + else if (action) data[action]() + else if (options.interval) data.pause().cycle() + }) } - this._setActiveIndicatorElement(nextElement) + var old = $.fn.carousel - var slidEvent = $.Event(Carousel._Event.SLID, { relatedTarget: nextElement, direction: directionalClassName }) + $.fn.carousel = Plugin + $.fn.carousel.Constructor = Carousel - if (Bootstrap.transition && $(this._element).hasClass(Carousel._ClassName.SLIDE)) { - $(nextElement).addClass(direction) - Bootstrap.reflow(nextElement) + // CAROUSEL NO CONFLICT + // ==================== - $(activeElement).addClass(directionalClassName) - $(nextElement).addClass(directionalClassName) - - $(activeElement) - .one(Bootstrap.TRANSITION_END, function () { - $(nextElement) - .removeClass(directionalClassName) - .removeClass(direction) - - $(nextElement).addClass(Carousel._ClassName.ACTIVE) - - $(activeElement) - .removeClass(Carousel._ClassName.ACTIVE) - .removeClass(direction) - .removeClass(directionalClassName) - - this._isSliding = false - - setTimeout(function () { - $(this._element).trigger(slidEvent) - }.bind(this), 0) - }.bind(this)) - .emulateTransitionEnd(Carousel._TRANSITION_DURATION) - - } else { - $(activeElement).removeClass(Carousel._ClassName.ACTIVE) - $(nextElement).addClass(Carousel._ClassName.ACTIVE) - - this._isSliding = false - $(this._element).trigger(slidEvent) + $.fn.carousel.noConflict = function () { + $.fn.carousel = old + return this } - if (isCycling) { - this['cycle']() - } -} + // CAROUSEL DATA-API + // ================= -/** - * ------------------------------------------------------------------------ - * jQuery Interface + noConflict implementaiton - * ------------------------------------------------------------------------ - */ + var clickHandler = function (e) { + var href + var $this = $(this) + var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 + if (!$target.hasClass('carousel')) return + var options = $.extend({}, $target.data(), $this.data()) + var slideIndex = $this.attr('data-slide-to') + if (slideIndex) options.interval = false -/** - * @const - * @type {Function} - */ -$.fn[Carousel._NAME] = Carousel._jQueryInterface - - -/** - * @const - * @type {Function} - */ -$.fn[Carousel._NAME]['Constructor'] = Carousel - - -/** - * @const - * @type {Function} - */ -$.fn[Carousel._NAME]['noConflict'] = function () { - $.fn[Carousel._NAME] = Carousel._JQUERY_NO_CONFLICT - return this -} + Plugin.call($target, options) + if (slideIndex) { + $target.data('bs.carousel').to(slideIndex) + } -/** - * ------------------------------------------------------------------------ - * Data Api implementation - * ------------------------------------------------------------------------ - */ + e.preventDefault() + } -$(document) - .on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', Carousel._dataApiClickHandler) + $(document) + .on('click.bs.carousel.data-api', '[data-slide]', clickHandler) + .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler) -$(window).on('load', function () { - $('[data-ride="carousel"]').each(function () { - var $carousel = $(this) - Carousel._jQueryInterface.call($carousel, /** @type {Object} */ ($carousel.data())) + $(window).on('load', function () { + $('[data-ride="carousel"]').each(function () { + var $carousel = $(this) + Plugin.call($carousel, $carousel.data()) + }) }) -}) + +}(jQuery); diff --git a/js/collapse.js b/js/collapse.js index 156163e3f..954513c5e 100644 --- a/js/collapse.js +++ b/js/collapse.js @@ -1,455 +1,211 @@ -/** ======================================================================= - * Bootstrap: collapse.js v4.0.0 +/* ======================================================================== + * Bootstrap: collapse.js v3.3.4 * http://getbootstrap.com/javascript/#collapse * ======================================================================== * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== - * @fileoverview - Bootstrap's collapse plugin. Flexible support for - * collapsible components like accordions and navigation. - * - * Public Methods & Properties: - * - * + $.carousel - * + $.carousel.noConflict - * + $.carousel.Constructor - * + $.carousel.Constructor.VERSION - * + $.carousel.Constructor.Defaults - * + $.carousel.Constructor.Defaults.toggle - * + $.carousel.Constructor.Defaults.trigger - * + $.carousel.Constructor.Defaults.parent - * + $.carousel.Constructor.prototype.toggle - * + $.carousel.Constructor.prototype.show - * + $.carousel.Constructor.prototype.hide - * - * ======================================================================== - */ + * ======================================================================== */ -'use strict'; ++function ($) { + 'use strict'; -/** - * Our collapse class. - * @param {Element!} element - * @param {Object=} opt_config - * @constructor - */ -var Collapse = function (element, opt_config) { + // COLLAPSE PUBLIC CLASS DEFINITION + // ================================ - /** @private {Element} */ - this._element = element + var Collapse = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, Collapse.DEFAULTS, options) + this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' + + '[data-toggle="collapse"][data-target="#' + element.id + '"]') + this.transitioning = null - /** @private {Object} */ - this._config = $.extend({}, Collapse['Defaults'], opt_config) + if (this.options.parent) { + this.$parent = this.getParent() + } else { + this.addAriaAndCollapsedClass(this.$element, this.$trigger) + } - /** @private {Element} */ - this._trigger = typeof this._config['trigger'] == 'string' ? - $(this._config['trigger'])[0] : this._config['trigger'] + if (this.options.toggle) this.toggle() + } - /** @private {boolean} */ - this._isTransitioning = false + Collapse.VERSION = '3.3.4' - /** @private {?Element} */ - this._parent = this._config['parent'] ? this._getParent() : null + Collapse.TRANSITION_DURATION = 350 - if (!this._config['parent']) { - this._addAriaAndCollapsedClass(this._element, this._trigger) + Collapse.DEFAULTS = { + toggle: true } - if (this._config['toggle']) { - this['toggle']() + Collapse.prototype.dimension = function () { + var hasWidth = this.$element.hasClass('width') + return hasWidth ? 'width' : 'height' } -} - - -/** - * @const - * @type {string} - */ -Collapse['VERSION'] = '4.0.0' - - -/** - * @const - * @type {Object} - */ -Collapse['Defaults'] = { - 'toggle' : true, - 'trigger' : '[data-toggle="collapse"]', - 'parent' : null -} - - -/** - * @const - * @type {string} - * @private - */ -Collapse._NAME = 'collapse' - - -/** - * @const - * @type {string} - * @private - */ -Collapse._DATA_KEY = 'bs.collapse' - - -/** - * @const - * @type {number} - * @private - */ -Collapse._TRANSITION_DURATION = 600 - - -/** - * @const - * @type {Function} - * @private - */ -Collapse._JQUERY_NO_CONFLICT = $.fn[Collapse._NAME] - - -/** - * @const - * @enum {string} - * @private - */ -Collapse._Event = { - SHOW : 'show.bs.collapse', - SHOWN : 'shown.bs.collapse', - HIDE : 'hide.bs.collapse', - HIDDEN : 'hidden.bs.collapse' -} - - -/** - * @const - * @enum {string} - * @private - */ -Collapse._ClassName = { - IN : 'in', - COLLAPSE : 'collapse', - COLLAPSING : 'collapsing', - COLLAPSED : 'collapsed' -} - - -/** - * @const - * @enum {string} - * @private - */ -Collapse._Dimension = { - WIDTH : 'width', - HEIGHT : 'height' -} - - -/** - * @const - * @enum {string} - * @private - */ -Collapse._Selector = { - ACTIVES : '.panel > .in, .panel > .collapsing' -} - - -/** - * Provides the jQuery Interface for the alert component. - * @param {Object|string=} opt_config - * @this {jQuery} - * @return {jQuery} - * @private - */ -Collapse._jQueryInterface = function (opt_config) { - return this.each(function () { - var $this = $(this) - var data = $this.data(Collapse._DATA_KEY) - var config = $.extend({}, Collapse['Defaults'], $this.data(), typeof opt_config == 'object' && opt_config) - - if (!data && config['toggle'] && opt_config == 'show') { - config['toggle'] = false - } + Collapse.prototype.show = function () { + if (this.transitioning || this.$element.hasClass('in')) return - if (!data) { - data = new Collapse(this, config) - $this.data(Collapse._DATA_KEY, data) - } + var activesData + var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing') - if (typeof opt_config == 'string') { - data[opt_config]() + if (actives && actives.length) { + activesData = actives.data('bs.collapse') + if (activesData && activesData.transitioning) return } - }) -} + var startEvent = $.Event('show.bs.collapse') + this.$element.trigger(startEvent) + if (startEvent.isDefaultPrevented()) return -/** - * Function for getting target element from element - * @return {Element} - * @private - */ -Collapse._getTargetFromElement = function (element) { - var selector = Bootstrap.getSelectorFromElement(element) - - return selector ? $(selector)[0] : null -} - + if (actives && actives.length) { + Plugin.call(actives, 'hide') + activesData || actives.data('bs.collapse', null) + } -/** - * Toggles the collapse element based on the presence of the 'in' class - */ -Collapse.prototype['toggle'] = function () { - if ($(this._element).hasClass(Collapse._ClassName.IN)) { - this['hide']() - } else { - this['show']() - } -} + var dimension = this.dimension() + this.$element + .removeClass('collapse') + .addClass('collapsing')[dimension](0) + .attr('aria-expanded', true) -/** - * Show's the collapsing element - */ -Collapse.prototype['show'] = function () { - if (this._isTransitioning || $(this._element).hasClass(Collapse._ClassName.IN)) { - return - } + this.$trigger + .removeClass('collapsed') + .attr('aria-expanded', true) - var activesData, actives + this.transitioning = 1 - if (this._parent) { - actives = $.makeArray($(Collapse._Selector.ACTIVES)) - if (!actives.length) { - actives = null + var complete = function () { + this.$element + .removeClass('collapsing') + .addClass('collapse in')[dimension]('') + this.transitioning = 0 + this.$element + .trigger('shown.bs.collapse') } - } - if (actives) { - activesData = $(actives).data(Collapse._DATA_KEY) - if (activesData && activesData._isTransitioning) { - return - } - } + if (!$.support.transition) return complete.call(this) - var startEvent = $.Event(Collapse._Event.SHOW) - $(this._element).trigger(startEvent) - if (startEvent.isDefaultPrevented()) { - return - } + var scrollSize = $.camelCase(['scroll', dimension].join('-')) - if (actives) { - Collapse._jQueryInterface.call($(actives), 'hide') - if (!activesData) { - $(actives).data(Collapse._DATA_KEY, null) - } + this.$element + .one('bsTransitionEnd', $.proxy(complete, this)) + .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]) } - var dimension = this._getDimension() + Collapse.prototype.hide = function () { + if (this.transitioning || !this.$element.hasClass('in')) return - $(this._element) - .removeClass(Collapse._ClassName.COLLAPSE) - .addClass(Collapse._ClassName.COLLAPSING) + var startEvent = $.Event('hide.bs.collapse') + this.$element.trigger(startEvent) + if (startEvent.isDefaultPrevented()) return - this._element.style[dimension] = 0 - this._element.setAttribute('aria-expanded', true) + var dimension = this.dimension() - if (this._trigger) { - $(this._trigger).removeClass(Collapse._ClassName.COLLAPSED) - this._trigger.setAttribute('aria-expanded', true) - } + this.$element[dimension](this.$element[dimension]())[0].offsetHeight - this['setTransitioning'](true) + this.$element + .addClass('collapsing') + .removeClass('collapse in') + .attr('aria-expanded', false) - var complete = function () { - $(this._element) - .removeClass(Collapse._ClassName.COLLAPSING) - .addClass(Collapse._ClassName.COLLAPSE) - .addClass(Collapse._ClassName.IN) + this.$trigger + .addClass('collapsed') + .attr('aria-expanded', false) - this._element.style[dimension] = '' + this.transitioning = 1 - this['setTransitioning'](false) + var complete = function () { + this.transitioning = 0 + this.$element + .removeClass('collapsing') + .addClass('collapse') + .trigger('hidden.bs.collapse') + } - $(this._element).trigger(Collapse._Event.SHOWN) - }.bind(this) + if (!$.support.transition) return complete.call(this) - if (!Bootstrap.transition) { - complete() - return + this.$element + [dimension](0) + .one('bsTransitionEnd', $.proxy(complete, this)) + .emulateTransitionEnd(Collapse.TRANSITION_DURATION) } - var scrollSize = 'scroll' + (dimension[0].toUpperCase() + dimension.slice(1)) - - $(this._element) - .one(Bootstrap.TRANSITION_END, complete) - .emulateTransitionEnd(Collapse._TRANSITION_DURATION) - - this._element.style[dimension] = this._element[scrollSize] + 'px' -} - - -/** - * Hides's the collapsing element - */ -Collapse.prototype['hide'] = function () { - if (this._isTransitioning || !$(this._element).hasClass(Collapse._ClassName.IN)) { - return + Collapse.prototype.toggle = function () { + this[this.$element.hasClass('in') ? 'hide' : 'show']() } - var startEvent = $.Event(Collapse._Event.HIDE) - $(this._element).trigger(startEvent) - if (startEvent.isDefaultPrevented()) return - - var dimension = this._getDimension() - var offsetDimension = dimension === Collapse._Dimension.WIDTH ? - 'offsetWidth' : 'offsetHeight' - - this._element.style[dimension] = this._element[offsetDimension] + 'px' - - Bootstrap.reflow(this._element) - - $(this._element) - .addClass(Collapse._ClassName.COLLAPSING) - .removeClass(Collapse._ClassName.COLLAPSE) - .removeClass(Collapse._ClassName.IN) - - this._element.setAttribute('aria-expanded', false) - - if (this._trigger) { - $(this._trigger).addClass(Collapse._ClassName.COLLAPSED) - this._trigger.setAttribute('aria-expanded', false) + Collapse.prototype.getParent = function () { + return $(this.options.parent) + .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') + .each($.proxy(function (i, element) { + var $element = $(element) + this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element) + }, this)) + .end() } - this['setTransitioning'](true) - - var complete = function () { - this['setTransitioning'](false) - $(this._element) - .removeClass(Collapse._ClassName.COLLAPSING) - .addClass(Collapse._ClassName.COLLAPSE) - .trigger(Collapse._Event.HIDDEN) - - }.bind(this) + Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) { + var isOpen = $element.hasClass('in') - this._element.style[dimension] = 0 - - if (!Bootstrap.transition) { - return complete() + $element.attr('aria-expanded', isOpen) + $trigger + .toggleClass('collapsed', !isOpen) + .attr('aria-expanded', isOpen) } - $(this._element) - .one(Bootstrap.TRANSITION_END, complete) - .emulateTransitionEnd(Collapse._TRANSITION_DURATION) -} - - + function getTargetFromTrigger($trigger) { + var href + var target = $trigger.attr('data-target') + || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 -/** - * @param {boolean} isTransitioning - */ -Collapse.prototype['setTransitioning'] = function (isTransitioning) { - this._isTransitioning = isTransitioning -} - - -/** - * Returns the collapsing dimension - * @return {string} - * @private - */ -Collapse.prototype._getDimension = function () { - var hasWidth = $(this._element).hasClass(Collapse._Dimension.WIDTH) - return hasWidth ? Collapse._Dimension.WIDTH : Collapse._Dimension.HEIGHT -} - - -/** - * Returns the parent element - * @return {Element} - * @private - */ -Collapse.prototype._getParent = function () { - var selector = '[data-toggle="collapse"][data-parent="' + this._config['parent'] + '"]' - var parent = $(this._config['parent'])[0] - var elements = /** @type {Array.} */ ($.makeArray($(parent).find(selector))) - - for (var i = 0; i < elements.length; i++) { - this._addAriaAndCollapsedClass(Collapse._getTargetFromElement(elements[i]), elements[i]) + return $(target) } - return parent -} + // COLLAPSE PLUGIN DEFINITION + // ========================== -/** - * Returns the parent element - * @param {Element} element - * @param {Element} trigger - * @private - */ -Collapse.prototype._addAriaAndCollapsedClass = function (element, trigger) { - if (element) { - var isOpen = $(element).hasClass(Collapse._ClassName.IN) - element.setAttribute('aria-expanded', isOpen) + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.collapse') + var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) - if (trigger) { - trigger.setAttribute('aria-expanded', isOpen) - $(trigger).toggleClass(Collapse._ClassName.COLLAPSED, !isOpen) - } + if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false + if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) + if (typeof option == 'string') data[option]() + }) } -} + var old = $.fn.collapse + $.fn.collapse = Plugin + $.fn.collapse.Constructor = Collapse -/** - * ------------------------------------------------------------------------ - * jQuery Interface + noConflict implementaiton - * ------------------------------------------------------------------------ - */ -/** - * @const - * @type {Function} - */ -$.fn[Collapse._NAME] = Collapse._jQueryInterface - - -/** - * @const - * @type {Function} - */ -$.fn[Collapse._NAME]['Constructor'] = Collapse + // COLLAPSE NO CONFLICT + // ==================== + $.fn.collapse.noConflict = function () { + $.fn.collapse = old + return this + } -/** - * @const - * @type {Function} - */ -$.fn[Collapse._NAME]['noConflict'] = function () { - $.fn[Collapse._NAME] = Collapse._JQUERY_NO_CONFLICT - return this -} + // COLLAPSE DATA-API + // ================= -/** - * ------------------------------------------------------------------------ - * Data Api implementation - * ------------------------------------------------------------------------ - */ + $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { + var $this = $(this) -$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (event) { - event.preventDefault() + if (!$this.attr('data-target')) e.preventDefault() - var target = Collapse._getTargetFromElement(this) + var $target = getTargetFromTrigger($this) + var data = $target.data('bs.collapse') + var option = data ? 'toggle' : $this.data() - var data = $(target).data(Collapse._DATA_KEY) - var config = data ? 'toggle' : $.extend({}, $(this).data(), { trigger: this }) + Plugin.call($target, option) + }) - Collapse._jQueryInterface.call($(target), config) -}) +}(jQuery); diff --git a/js/dropdown.js b/js/dropdown.js index 4599d5ba9..8fd86a025 100644 --- a/js/dropdown.js +++ b/js/dropdown.js @@ -1,322 +1,165 @@ -/** ======================================================================= - * Bootstrap: dropdown.js v4.0.0 - * http://getbootstrap.com/javascript/#dropdown +/* ======================================================================== + * Bootstrap: dropdown.js v3.3.4 + * http://getbootstrap.com/javascript/#dropdowns * ======================================================================== * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== - * @fileoverview - Add dropdown menus to nearly anything with this simple - * plugin, including the navbar, tabs, and pills. - * - * Public Methods & Properties: - * - * + $.dropdown - * + $.dropdown.noConflict - * + $.dropdown.Constructor - * + $.dropdown.Constructor.VERSION - * + $.dropdown.Constructor.prototype.toggle - * - * ======================================================================== - */ - -'use strict'; - - -/** - * Our dropdown class. - * @param {Element!} element - * @constructor - */ -var Dropdown = function (element) { - $(element).on('click.bs.dropdown', this['toggle']) -} - - -/** - * @const - * @type {string} - */ -Dropdown['VERSION'] = '4.0.0' - - -/** - * @const - * @type {string} - * @private - */ -Dropdown._NAME = 'dropdown' - - -/** - * @const - * @type {string} - * @private - */ -Dropdown._DATA_KEY = 'bs.dropdown' - - -/** - * @const - * @type {Function} - * @private - */ -Dropdown._JQUERY_NO_CONFLICT = $.fn[Dropdown._NAME] - - -/** - * @const - * @enum {string} - * @private - */ -Dropdown._Event = { - HIDE : 'hide.bs.dropdown', - HIDDEN : 'hidden.bs.dropdown', - SHOW : 'show.bs.dropdown', - SHOWN : 'shown.bs.dropdown' -} - - -/** - * @const - * @enum {string} - * @private - */ -Dropdown._ClassName = { - BACKDROP : 'dropdown-backdrop', - DISABLED : 'disabled', - OPEN : 'open' -} - - -/** - * @const - * @enum {string} - * @private - */ -Dropdown._Selector = { - BACKDROP : '.dropdown-backdrop', - DATA_TOGGLE : '[data-toggle="dropdown"]', - FORM_CHILD : '.dropdown form', - ROLE_MENU : '[role="menu"]', - ROLE_LISTBOX : '[role="listbox"]', - NAVBAR_NAV : '.navbar-nav', - VISIBLE_ITEMS : '[role="menu"] li:not(.divider) a, [role="listbox"] li:not(.divider) a' -} - - -/** - * Provides the jQuery Interface for the alert component. - * @param {string=} opt_config - * @this {jQuery} - * @return {jQuery} - * @private - */ -Dropdown._jQueryInterface = function (opt_config) { - return this.each(function () { - var data = $(this).data(Dropdown._DATA_KEY) - - if (!data) { - $(this).data(Dropdown._DATA_KEY, (data = new Dropdown(this))) - } + * ======================================================================== */ - if (typeof opt_config === 'string') { - data[opt_config].call(this) - } - }) -} ++function ($) { + 'use strict'; -/** - * @param {Event=} opt_event - * @private - */ -Dropdown._clearMenus = function (opt_event) { - if (opt_event && opt_event.which == 3) { - return - } + // DROPDOWN CLASS DEFINITION + // ========================= - var backdrop = $(Dropdown._Selector.BACKDROP)[0] - if (backdrop) { - backdrop.parentNode.removeChild(backdrop) + var backdrop = '.dropdown-backdrop' + var toggle = '[data-toggle="dropdown"]' + var Dropdown = function (element) { + $(element).on('click.bs.dropdown', this.toggle) } - var toggles = /** @type {Array.} */ ($.makeArray($(Dropdown._Selector.DATA_TOGGLE))) - - for (var i = 0; i < toggles.length; i++) { - var parent = Dropdown._getParentFromElement(toggles[i]) - var relatedTarget = { 'relatedTarget': toggles[i] } + Dropdown.VERSION = '3.3.4' - if (!$(parent).hasClass(Dropdown._ClassName.OPEN)) { - continue - } + function getParent($this) { + var selector = $this.attr('data-target') - var hideEvent = $.Event(Dropdown._Event.HIDE, relatedTarget) - $(parent).trigger(hideEvent) - if (hideEvent.isDefaultPrevented()) { - continue + if (!selector) { + selector = $this.attr('href') + selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 } - toggles[i].setAttribute('aria-expanded', 'false') + var $parent = selector && $(selector) - $(parent) - .removeClass(Dropdown._ClassName.OPEN) - .trigger(Dropdown._Event.HIDDEN, relatedTarget) + return $parent && $parent.length ? $parent : $this.parent() } -} + function clearMenus(e) { + if (e && e.which === 3) return + $(backdrop).remove() + $(toggle).each(function () { + var $this = $(this) + var $parent = getParent($this) + var relatedTarget = { relatedTarget: this } -/** - * @param {Element} element - * @return {Element} - * @private - */ -Dropdown._getParentFromElement = function (element) { - var selector = Bootstrap.getSelectorFromElement(element) + if (!$parent.hasClass('open')) return - if (selector) { - var parent = $(selector)[0] - } + if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return - return /** @type {Element} */ (parent || element.parentNode) -} + $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) + if (e.isDefaultPrevented()) return -/** - * @param {Event} event - * @this {Element} - * @private - */ -Dropdown._dataApiKeydownHandler = function (event) { - if (!/(38|40|27|32)/.test(event.which) || /input|textarea/i.test(event.target.tagName)) { - return + $this.attr('aria-expanded', 'false') + $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget) + }) } - event.preventDefault() - event.stopPropagation() + Dropdown.prototype.toggle = function (e) { + var $this = $(this) - if (this.disabled || $(this).hasClass(Dropdown._ClassName.DISABLED)) { - return - } + if ($this.is('.disabled, :disabled')) return - var parent = Dropdown._getParentFromElement(this) - var isActive = $(parent).hasClass(Dropdown._ClassName.OPEN) + var $parent = getParent($this) + var isActive = $parent.hasClass('open') - if ((!isActive && event.which != 27) || (isActive && event.which == 27)) { - if (event.which == 27) { - var toggle = $(parent).find(Dropdown._Selector.DATA_TOGGLE)[0] - $(toggle).trigger('focus') - } - $(this).trigger('click') - return - } + clearMenus() - var items = $.makeArray($(Dropdown._Selector.VISIBLE_ITEMS)) + if (!isActive) { + if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { + // if mobile we use a backdrop because click events don't delegate + $(document.createElement('div')) + .addClass('dropdown-backdrop') + .insertAfter($(this)) + .on('click', clearMenus) + } - items = items.filter(function (item) { - return item.offsetWidth || item.offsetHeight - }) + var relatedTarget = { relatedTarget: this } + $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget)) - if (!items.length) { - return - } + if (e.isDefaultPrevented()) return - var index = items.indexOf(event.target) + $this + .trigger('focus') + .attr('aria-expanded', 'true') - if (event.which == 38 && index > 0) index-- // up - if (event.which == 40 && index < items.length - 1) index++ // down - if (!~index) index = 0 + $parent + .toggleClass('open') + .trigger('shown.bs.dropdown', relatedTarget) + } - items[index].focus() -} + return false + } + Dropdown.prototype.keydown = function (e) { + if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return -/** - * Toggles the dropdown - * @this {Element} - * @return {boolean|undefined} - */ -Dropdown.prototype['toggle'] = function () { - if (this.disabled || $(this).hasClass(Dropdown._ClassName.DISABLED)) { - return - } + var $this = $(this) - var parent = Dropdown._getParentFromElement(this) - var isActive = $(parent).hasClass(Dropdown._ClassName.OPEN) + e.preventDefault() + e.stopPropagation() - Dropdown._clearMenus() + if ($this.is('.disabled, :disabled')) return - if (isActive) { - return false - } + var $parent = getParent($this) + var isActive = $parent.hasClass('open') - if ('ontouchstart' in document.documentElement && !$(parent).closest(Dropdown._Selector.NAVBAR_NAV).length) { - // if mobile we use a backdrop because click events don't delegate - var dropdown = document.createElement('div') - dropdown.className = Dropdown._ClassName.BACKDROP - this.parentNode.insertBefore(this, dropdown) - $(dropdown).on('click', Dropdown._clearMenus) - } + if (!isActive && e.which != 27 || isActive && e.which == 27) { + if (e.which == 27) $parent.find(toggle).trigger('focus') + return $this.trigger('click') + } - var relatedTarget = { 'relatedTarget': this } - var showEvent = $.Event(Dropdown._Event.SHOW, relatedTarget) + var desc = ' li:not(.disabled):visible a' + var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc) - $(parent).trigger(showEvent) + if (!$items.length) return - if (showEvent.isDefaultPrevented()) { - return - } + var index = $items.index(e.target) + + if (e.which == 38 && index > 0) index-- // up + if (e.which == 40 && index < $items.length - 1) index++ // down + if (!~index) index = 0 - this.focus() - this.setAttribute('aria-expanded', 'true') + $items.eq(index).trigger('focus') + } - $(parent).toggleClass(Dropdown._ClassName.OPEN) - $(parent).trigger(Dropdown._Event.SHOWN, relatedTarget) + // DROPDOWN PLUGIN DEFINITION + // ========================== - return false -} + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.dropdown') + if (!data) $this.data('bs.dropdown', (data = new Dropdown(this))) + if (typeof option == 'string') data[option].call($this) + }) + } -/** - * ------------------------------------------------------------------------ - * jQuery Interface + noConflict implementaiton - * ------------------------------------------------------------------------ - */ + var old = $.fn.dropdown -/** - * @const - * @type {Function} - */ -$.fn[Dropdown._NAME] = Dropdown._jQueryInterface + $.fn.dropdown = Plugin + $.fn.dropdown.Constructor = Dropdown -/** - * @const - * @type {Function} - */ -$.fn[Dropdown._NAME]['Constructor'] = Dropdown + // DROPDOWN NO CONFLICT + // ==================== + $.fn.dropdown.noConflict = function () { + $.fn.dropdown = old + return this + } -/** - * @const - * @type {Function} - */ -$.fn[Dropdown._NAME]['noConflict'] = function () { - $.fn[Dropdown._NAME] = Dropdown._JQUERY_NO_CONFLICT - return this -} + // APPLY TO STANDARD DROPDOWN ELEMENTS + // =================================== -/** - * ------------------------------------------------------------------------ - * Data Api implementation - * ------------------------------------------------------------------------ - */ + $(document) + .on('click.bs.dropdown.data-api', clearMenus) + .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) + .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) + .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) + .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown) -$(document) - .on('click.bs.dropdown.data-api', Dropdown._clearMenus) - .on('click.bs.dropdown.data-api', Dropdown._Selector.FORM_CHILD, function (e) { e.stopPropagation() }) - .on('click.bs.dropdown.data-api', Dropdown._Selector.DATA_TOGGLE, Dropdown.prototype['toggle']) - .on('keydown.bs.dropdown.data-api', Dropdown._Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler) - .on('keydown.bs.dropdown.data-api', Dropdown._Selector.ROLE_MENU, Dropdown._dataApiKeydownHandler) - .on('keydown.bs.dropdown.data-api', Dropdown._Selector.ROLE_LISTBOX, Dropdown._dataApiKeydownHandler) +}(jQuery); diff --git a/js/externs/bootstrap.js b/js/externs/bootstrap.js deleted file mode 100644 index b4c2e36c2..000000000 --- a/js/externs/bootstrap.js +++ /dev/null @@ -1,6 +0,0 @@ -jQuery.event.prototype.handleObj = function () {} -jQuery.event.prototype.handleObj.handler = function () {} -$.event.special = function () {} -$.event.trueHover = true -$.offset = {} -$.offset.setOffset = function (a,b,c) {} diff --git a/js/externs/jQuery.js b/js/externs/jQuery.js deleted file mode 100644 index f9b80c497..000000000 --- a/js/externs/jQuery.js +++ /dev/null @@ -1,2159 +0,0 @@ -/* - * Copyright 2011 The Closure Compiler Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Externs for jQuery 1.9.1 - * - * Note that some functions use different return types depending on the number - * of parameters passed in. In these cases, you may need to annotate the type - * of the result in your code, so the JSCompiler understands which type you're - * expecting. For example: - * var elt = /** @type {Element} * / (foo.get(0)); - * - * @see http://api.jquery.com/ - * @externs - */ - -/** - * @typedef {(Window|Document|Element|Array.|string|jQuery| - * NodeList)} - */ -var jQuerySelector; - -/** @typedef {function(...)|Array.} */ -var jQueryCallback; - -/** @typedef { - { - accepts: (Object.|undefined), - async: (?boolean|undefined), - beforeSend: (function(jQuery.jqXHR, (jQueryAjaxSettings|Object.))|undefined), - cache: (?boolean|undefined), - complete: (function(jQuery.jqXHR, string)|undefined), - contents: (Object.|undefined), - contentType: (?string|undefined), - context: (Object.|jQueryAjaxSettings|undefined), - converters: (Object.|undefined), - crossDomain: (?boolean|undefined), - data: (Object.|?string|Array.|undefined), - dataFilter: (function(string, string):?|undefined), - dataType: (?string|undefined), - error: (function(jQuery.jqXHR, string, string)|undefined), - global: (?boolean|undefined), - headers: (Object.|undefined), - ifModified: (?boolean|undefined), - isLocal: (?boolean|undefined), - jsonp: (?string|undefined), - jsonpCallback: (?string|function()|undefined), - mimeType: (?string|undefined), - password: (?string|undefined), - processData: (?boolean|undefined), - scriptCharset: (?string|undefined), - statusCode: (Object.|undefined), - success: (function(?, string, jQuery.jqXHR)|undefined), - timeout: (?number|undefined), - traditional: (?boolean|undefined), - type: (?string|undefined), - url: (?string|undefined), - username: (?string|undefined), - xhr: (function():(ActiveXObject|XMLHttpRequest)|undefined), - xhrFields: (Object.|undefined) - }} */ -var jQueryAjaxSettings; - -/** - * @constructor - * @param {(jQuerySelector|Element|Object|Array.|jQuery|string| - * function())=} arg1 - * @param {(Element|jQuery|Document| - * Object.)=} arg2 - * @return {!jQuery} - */ -function jQuery(arg1, arg2) {} - -/** - * @constructor - * @extends {jQuery} - * @param {(jQuerySelector|Element|Object|Array.|jQuery|string| - * function())=} arg1 - * @param {(Element|jQuery|Document| - * Object.)=} arg2 - * @return {!jQuery} - */ -function $(arg1, arg2) {} - -/** - * @param {(jQuerySelector|Array.|string|jQuery)} arg1 - * @param {Element=} context - * @return {!jQuery} - * @nosideeffects - */ -jQuery.prototype.add = function(arg1, context) {}; - -/** - * @param {(jQuerySelector|Array.|string|jQuery)=} arg1 - * @return {!jQuery} - * @nosideeffects - */ -jQuery.prototype.addBack = function(arg1) {}; - -/** - * @param {(string|function(number,String))} arg1 - * @return {!jQuery} - */ -jQuery.prototype.addClass = function(arg1) {}; - -/** - * @param {(string|Element|jQuery|function(number))} arg1 - * @param {(string|Element|Array.|jQuery)=} content - * @return {!jQuery} - */ -jQuery.prototype.after = function(arg1, content) {}; - -/** - * @param {(string|jQueryAjaxSettings|Object.)} arg1 - * @param {(jQueryAjaxSettings|Object.)=} settings - * @return {jQuery.jqXHR} - */ -jQuery.ajax = function(arg1, settings) {}; - -/** - * @param {(string|jQueryAjaxSettings|Object.)} arg1 - * @param {(jQueryAjaxSettings|Object.)=} settings - * @return {jQuery.jqXHR} - */ -$.ajax = function(arg1, settings) {}; - -/** - * @param {function(!jQuery.event,XMLHttpRequest,(jQueryAjaxSettings|Object.))} handler - * @return {!jQuery} - */ -jQuery.prototype.ajaxComplete = function(handler) {}; - -/** - * @param {function(!jQuery.event,jQuery.jqXHR,(jQueryAjaxSettings|Object.),*)} handler - * @return {!jQuery} - */ -jQuery.prototype.ajaxError = function(handler) {}; - -/** - * @param {(string|function((jQueryAjaxSettings|Object.),(jQueryAjaxSettings|Object.),jQuery.jqXHR))} dataTypes - * @param {function((jQueryAjaxSettings|Object.),(jQueryAjaxSettings|Object.),jQuery.jqXHR)=} handler - */ -jQuery.ajaxPrefilter = function(dataTypes, handler) {}; - -/** - * @param {(string|function((jQueryAjaxSettings|Object.),(jQueryAjaxSettings|Object.),jQuery.jqXHR))} dataTypes - * @param {function((jQueryAjaxSettings|Object.),(jQueryAjaxSettings|Object.),jQuery.jqXHR)=} handler - */ -$.ajaxPrefilter = function(dataTypes, handler) {}; - -/** - * @param {function(!jQuery.event,jQuery.jqXHR,(jQueryAjaxSettings|Object.))} handler - * @return {!jQuery} - */ -jQuery.prototype.ajaxSend = function(handler) {}; - -/** @const {jQueryAjaxSettings|Object.} */ -jQuery.ajaxSettings; - -/** @const {jQueryAjaxSettings|Object.} */ -$.ajaxSettings = {}; - -/** @type {Object.} */ -jQuery.ajaxSettings.flatOptions = {}; - -/** @type {Object.} */ -$.ajaxSettings.flatOptions = {}; - -/** @type {boolean} */ -jQuery.ajaxSettings.processData; - -/** @type {boolean} */ -$.ajaxSettings.processData; - -/** @type {Object.} */ -jQuery.ajaxSettings.responseFields = {}; - -/** @type {Object.} */ -$.ajaxSettings.responseFields = {}; - -/** @param {jQueryAjaxSettings|Object.} options */ -jQuery.ajaxSetup = function(options) {}; - -/** @param {jQueryAjaxSettings|Object.} options */ -$.ajaxSetup = function(options) {}; - -/** - * @param {function()} handler - * @return {!jQuery} - */ -jQuery.prototype.ajaxStart = function(handler) {}; - -/** - * @param {function()} handler - * @return {!jQuery} - */ -jQuery.prototype.ajaxStop = function(handler) {}; - -/** - * @param {function(!jQuery.event,XMLHttpRequest,(jQueryAjaxSettings|Object.), ?)} handler - * @return {!jQuery} - */ -jQuery.prototype.ajaxSuccess = function(handler) {}; - -/** - * @deprecated Please use .addBack(selector) instead. - * @return {!jQuery} - * @nosideeffects - */ -jQuery.prototype.andSelf = function() {}; - -/** - * @param {Object.} properties - * @param {(string|number|function()|Object.)=} arg2 - * @param {(string|function())=} easing - * @param {function()=} complete - * @return {!jQuery} - */ -jQuery.prototype.animate = function(properties, arg2, easing, complete) {}; - -/** - * @param {(string|Element|Array.|jQuery|function(number,string))} arg1 - * @param {...(string|Element|Array.|jQuery)} content - * @return {!jQuery} - */ -jQuery.prototype.append = function(arg1, content) {}; - -/** - * @param {(jQuerySelector|Element|jQuery)} target - * @return {!jQuery} - */ -jQuery.prototype.appendTo = function(target) {}; - -/** - * @param {(string|Object.)} arg1 - * @param {(string|number|boolean|function(number,string))=} arg2 - * @return {(string|!jQuery)} - */ -jQuery.prototype.attr = function(arg1, arg2) {}; - -/** - * @param {(string|Element|jQuery|function())} arg1 - * @param {(string|Element|Array.|jQuery)=} content - * @return {!jQuery} - */ -jQuery.prototype.before = function(arg1, content) {}; - -/** - * @param {(string|Object.)} arg1 - * @param {(Object.|function(!jQuery.event=)|boolean)=} eventData - * @param {(function(!jQuery.event=)|boolean)=} arg3 - * @return {!jQuery} - */ -jQuery.prototype.bind = function(arg1, eventData, arg3) {}; - -/** - * @param {(function(!jQuery.event=)|Object.)=} arg1 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.blur = function(arg1, handler) {}; - -/** - * @constructor - * @private - */ -jQuery.callbacks = function () {}; - -/** - * @param {string=} flags - * @return {jQuery.callbacks} - */ -jQuery.Callbacks = function (flags) {}; - -/** @param {function()} callbacks */ -jQuery.callbacks.prototype.add = function(callbacks) {}; - -/** @return {undefined} */ -jQuery.callbacks.prototype.disable = function() {}; - -/** @return {undefined} */ -jQuery.callbacks.prototype.empty = function() {}; - -/** @param {...*} var_args */ -jQuery.callbacks.prototype.fire = function(var_args) {}; - -/** @return {boolean} */ -jQuery.callbacks.prototype.fired = function() {}; - -/** @param {...*} var_args */ -jQuery.callbacks.prototype.fireWith = function(var_args) {}; - -/** - * @param {function()} callback - * @return {boolean} - * @nosideeffects - */ -jQuery.callbacks.prototype.has = function(callback) {}; - -/** @return {undefined} */ -jQuery.callbacks.prototype.lock = function() {}; - -/** @return {boolean} */ -jQuery.callbacks.prototype.locked = function() {}; - -/** @param {function()} callbacks */ -jQuery.callbacks.prototype.remove = function(callbacks) {}; - -/** - * @param {(function(!jQuery.event=)|Object.)=} arg1 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.change = function(arg1, handler) {}; - -/** - * @param {jQuerySelector=} selector - * @return {!jQuery} - * @nosideeffects - */ -jQuery.prototype.children = function(selector) {}; - -/** - * @param {string=} queueName - * @return {!jQuery} - */ -jQuery.prototype.clearQueue = function(queueName) {}; - -/** - * @param {(function(!jQuery.event=)|Object.)=} arg1 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.click = function(arg1, handler) {}; - -/** - * @param {boolean=} withDataAndEvents - * @param {boolean=} deepWithDataAndEvents - * @return {!jQuery} - * @suppress {checkTypes} see https://code.google.com/p/closure-compiler/issues/detail?id=583 - */ -jQuery.prototype.clone = function(withDataAndEvents, deepWithDataAndEvents) {}; - -/** - * @param {(jQuerySelector|jQuery|Element|string)} arg1 - * @param {Element=} context - * @return {!jQuery} - * @nosideeffects - */ -jQuery.prototype.closest = function(arg1, context) {}; - -/** - * @param {Element} container - * @param {Element} contained - * @return {boolean} - */ -jQuery.contains = function(container, contained) {}; - -/** - * @param {Element} container - * @param {Element} contained - * @return {boolean} - */ -$.contains = function(container, contained) {}; - -/** - * @return {!jQuery} - * @nosideeffects - */ -jQuery.prototype.contents = function() {}; - -/** @type {Element|Document} */ -jQuery.prototype.context; - -/** - * @param {(string|Object.)} arg1 - * @param {(string|number|function(number,*))=} arg2 - * @return {(string|!jQuery)} - */ -jQuery.prototype.css = function(arg1, arg2) {}; - -/** @type {Object.} */ -jQuery.cssHooks; - -/** @type {Object.} */ -$.cssHooks; - -/** - * @param {Element} elem - * @param {string=} key - * @param {*=} value - * @return {*} - */ -jQuery.data = function(elem, key, value) {}; - -/** - * @param {(string|Object.)=} arg1 - * @param {*=} value - * @return {*} - */ -jQuery.prototype.data = function(arg1, value) {}; - -/** - * @param {Element} elem - * @param {string=} key - * @param {*=} value - * @return {*} - */ -$.data = function(elem, key, value) {}; - -/** - * @param {(function(!jQuery.event=)|Object.)=} arg1 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.dblclick = function(arg1, handler) {}; - -/** - * @constructor - * @implements {jQuery.Promise} - * @param {function()=} opt_fn - * @see http://api.jquery.com/category/deferred-object/ - */ -jQuery.deferred = function(opt_fn) {}; - -/** - * @constructor - * @extends {jQuery.deferred} - * @param {function()=} opt_fn - * @return {jQuery.Deferred} - */ -jQuery.Deferred = function(opt_fn) {}; - -/** - * @constructor - * @extends {jQuery.deferred} - * @param {function()=} opt_fn - * @see http://api.jquery.com/category/deferred-object/ - */ -$.deferred = function(opt_fn) {}; - -/** - * @constructor - * @extends {jQuery.deferred} - * @param {function()=} opt_fn - * @return {jQuery.deferred} - */ -$.Deferred = function(opt_fn) {}; - -/** - * @override - * @param {jQueryCallback} alwaysCallbacks - * @param {jQueryCallback=} alwaysCallbacks2 - * @return {jQuery.deferred} - */ -jQuery.deferred.prototype.always - = function(alwaysCallbacks, alwaysCallbacks2) {}; - -/** - * @override - * @param {jQueryCallback} doneCallbacks - * @param {jQueryCallback=} doneCallbacks2 - * @return {jQuery.deferred} - */ -jQuery.deferred.prototype.done = function(doneCallbacks, doneCallbacks2) {}; - -/** - * @override - * @param {jQueryCallback} failCallbacks - * @param {jQueryCallback=} failCallbacks2 - * @return {jQuery.deferred} - */ -jQuery.deferred.prototype.fail = function(failCallbacks, failCallbacks2) {}; - -/** - * @param {...*} var_args - * @return {jQuery.deferred} - */ -jQuery.deferred.prototype.notify = function(var_args) {}; - -/** - * @param {Object} context - * @param {...*} var_args - * @return {jQuery.deferred} - */ -jQuery.deferred.prototype.notifyWith = function(context, var_args) {}; - -/** - * @deprecated Please use deferred.then() instead. - * @override - * @param {function()=} doneFilter - * @param {function()=} failFilter - * @param {function()=} progressFilter - * @return {jQuery.Promise} - */ -jQuery.deferred.prototype.pipe = - function(doneFilter, failFilter, progressFilter) {}; - -/** - * @param {jQueryCallback} progressCallbacks - * @return {jQuery.deferred} - */ -jQuery.deferred.prototype.progress = function(progressCallbacks) {}; - -/** - * @param {Object=} target - * @return {jQuery.Promise} - */ -jQuery.deferred.prototype.promise = function(target) {}; - -/** - * @param {...*} var_args - * @return {jQuery.deferred} - */ -jQuery.deferred.prototype.reject = function(var_args) {}; - -/** - * @param {Object} context - * @param {Array.<*>=} args - * @return {jQuery.deferred} - */ -jQuery.deferred.prototype.rejectWith = function(context, args) {}; - -/** - * @param {...*} var_args - * @return {jQuery.deferred} - */ -jQuery.deferred.prototype.resolve = function(var_args) {}; - -/** - * @param {Object} context - * @param {Array.<*>=} args - * @return {jQuery.deferred} - */ -jQuery.deferred.prototype.resolveWith = function(context, args) {}; - -/** @return {string} */ -jQuery.deferred.prototype.state = function() {}; - -/** - * @override - * @param {jQueryCallback} doneCallbacks - * @param {jQueryCallback=} failCallbacks - * @param {jQueryCallback=} progressCallbacks - * @return {jQuery.deferred} - */ -jQuery.deferred.prototype.then - = function(doneCallbacks, failCallbacks, progressCallbacks) {}; - -/** - * @param {number} duration - * @param {string=} queueName - * @return {!jQuery} - */ -jQuery.prototype.delay = function(duration, queueName) {}; - -/** - * @param {string} selector - * @param {(string|Object.)} arg2 - * @param {(function(!jQuery.event=)|Object.)=} arg3 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.delegate = function(selector, arg2, arg3, handler) {}; - -/** - * @param {Element} elem - * @param {string=} queueName - */ -jQuery.dequeue = function(elem, queueName) {}; - -/** - * @param {string=} queueName - * @return {!jQuery} - */ -jQuery.prototype.dequeue = function(queueName) {}; - -/** - * @param {Element} elem - * @param {string=} queueName - */ -$.dequeue = function(elem, queueName) {}; - -/** - * @param {jQuerySelector=} selector - * @return {!jQuery} - */ -jQuery.prototype.detach = function(selector) {}; - -/** - * @param {Object} collection - * @param {function((number|string),?)} callback - * @return {Object} - */ -jQuery.each = function(collection, callback) {}; - -/** - * @param {function(number,Element)} fnc - * @return {!jQuery} - */ -jQuery.prototype.each = function(fnc) {}; - -/** - * @param {Object} collection - * @param {function((number|string),?)} callback - * @return {Object} - */ -$.each = function(collection, callback) {}; - -/** @return {!jQuery} */ -jQuery.prototype.empty = function() {}; - -/** - * @return {!jQuery} - * @nosideeffects - */ -jQuery.prototype.end = function() {}; - -/** - * @param {number} arg1 - * @return {!jQuery} - */ -jQuery.prototype.eq = function(arg1) {}; - -/** @param {string} message */ -jQuery.error = function(message) {}; - -/** - * @deprecated Please use .on( "error", handler ) instead. - * @param {(function(!jQuery.event=)|Object.)} arg1 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.error = function(arg1, handler) {}; - -/** @param {string} message */ -$.error = function(message) {}; - -/** - * @constructor - * @param {string} eventType - */ -jQuery.event = function(eventType) {}; - -/** - * @constructor - * @extends {jQuery.event} - * @param {string} eventType - * @param {Object=} properties - * @return {jQuery.Event} - */ -jQuery.Event = function(eventType, properties) {}; - -/** - * @constructor - * @extends {jQuery.event} - * @param {string} eventType - */ -$.event = function(eventType) {}; - -/** - * @constructor - * @extends {jQuery.event} - * @param {string} eventType - * @param {Object=} properties - * @return {$.Event} - */ -$.Event = function(eventType, properties) {}; - -/** @type {Element} */ -jQuery.event.prototype.currentTarget; - -/** @type {Object.} */ -jQuery.event.prototype.data; - -/** @type {Element} */ -jQuery.event.prototype.delegateTarget; - -/** - * @return {boolean} - * @nosideeffects - */ -jQuery.event.prototype.isDefaultPrevented = function() {}; - -/** - * @return {boolean} - * @nosideeffects - */ -jQuery.event.prototype.isImmediatePropagationStopped = function() {}; - -/** - * @return {boolean} - * @nosideeffects - */ -jQuery.event.prototype.isPropagationStopped = function() {}; - -/** @type {string} */ -jQuery.event.prototype.namespace; - -/** @type {Event} */ -jQuery.event.prototype.originalEvent; - -/** @type {number} */ -jQuery.event.prototype.pageX; - -/** @type {number} */ -jQuery.event.prototype.pageY; - -/** @return {undefined} */ -jQuery.event.prototype.preventDefault = function() {}; - -/** @type {Object.} */ -jQuery.event.prototype.props; - -/** @type {Element} */ -jQuery.event.prototype.relatedTarget; - -/** @type {*} */ -jQuery.event.prototype.result; - -/** @return {undefined} */ -jQuery.event.prototype.stopImmediatePropagation = function() {}; - -/** @return {undefined} */ -jQuery.event.prototype.stopPropagation = function() {}; - -/** @type {Element} */ -jQuery.event.prototype.target; - -/** @type {number} */ -jQuery.event.prototype.timeStamp; - -/** @type {string} */ -jQuery.event.prototype.type; - -/** @type {number} */ -jQuery.event.prototype.which; - -/** - * @param {(Object|boolean)} arg1 - * @param {...*} var_args - * @return {Object} - */ -jQuery.extend = function(arg1, var_args) {}; - -/** - * @param {(Object|boolean)} arg1 - * @param {...*} var_args - * @return {Object} - */ -jQuery.prototype.extend = function(arg1, var_args) {}; - -/** - * @param {(Object|boolean)} arg1 - * @param {...*} var_args - * @return {Object} - */ -$.extend = function(arg1, var_args) {}; - -/** - * @param {(string|number|function())=} duration - * @param {(function()|string)=} arg2 - * @param {function()=} callback - * @return {!jQuery} - */ -jQuery.prototype.fadeIn = function(duration, arg2, callback) {}; - -/** - * @param {(string|number|function())=} duration - * @param {(function()|string)=} arg2 - * @param {function()=} callback - * @return {!jQuery} - */ -jQuery.prototype.fadeOut = function(duration, arg2, callback) {}; - -/** - * @param {(string|number)} duration - * @param {number} opacity - * @param {(function()|string)=} arg3 - * @param {function()=} callback - * @return {!jQuery} - */ -jQuery.prototype.fadeTo = function(duration, opacity, arg3, callback) {}; - -/** - * @param {(string|number|function())=} duration - * @param {(string|function())=} easing - * @param {function()=} callback - * @return {!jQuery} - */ -jQuery.prototype.fadeToggle = function(duration, easing, callback) {}; - -/** - * @param {(jQuerySelector|function(number)|Element|jQuery)} arg1 - * @return {!jQuery} - */ -jQuery.prototype.filter = function(arg1) {}; - -/** - * @param {(jQuerySelector|jQuery|Element)} arg1 - * @return {!jQuery} - * @nosideeffects - */ -jQuery.prototype.find = function(arg1) {}; - -/** @return {!jQuery} */ -jQuery.prototype.first = function() {}; - -/** @see http://docs.jquery.com/Plugins/Authoring */ -jQuery.fn = jQuery.prototype; - -/** @see http://docs.jquery.com/Plugins/Authoring */ -$.fn = $.prototype; - -/** - * @param {(function(!jQuery.event=)|Object.)=} arg1 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.focus = function(arg1, handler) {}; - -/** - * @param {(function(!jQuery.event=)|Object.)} arg1 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.focusin = function(arg1, handler) {}; - -/** - * @param {(function(!jQuery.event=)|Object.)} arg1 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.focusout = function(arg1, handler) {}; - -/** @const */ -jQuery.fx = {}; - -/** @const */ -$.fx = {}; - -/** @type {number} */ -jQuery.fx.interval; - -/** @type {number} */ -$.fx.interval; - -/** @type {boolean} */ -jQuery.fx.off; - -/** @type {boolean} */ -$.fx.off; - -/** - * @param {string} url - * @param {(Object.|string| - * function(string,string,jQuery.jqXHR))=} data - * @param {(function(string,string,jQuery.jqXHR)|string)=} success - * @param {string=} dataType - * @return {jQuery.jqXHR} - */ -jQuery.get = function(url, data, success, dataType) {}; - -/** - * @param {number=} index - * @return {(Element|Array.)} - * @nosideeffects - */ -jQuery.prototype.get = function(index) {}; - -/** - * @param {string} url - * @param {(Object.|string| - * function(string,string,jQuery.jqXHR))=} data - * @param {(function(string,string,jQuery.jqXHR)|string)=} success - * @param {string=} dataType - * @return {jQuery.jqXHR} - */ -$.get = function(url, data, success, dataType) {}; - -/** - * @param {string} url - * @param {(Object.| - * function(Object.,string,jQuery.jqXHR))=} data - * @param {function(Object.,string,jQuery.jqXHR)=} success - * @return {jQuery.jqXHR} - * @see http://api.jquery.com/jquery.getjson/#jQuery-getJSON-url-data-success - */ -jQuery.getJSON = function(url, data, success) {}; - -/** - * @param {string} url - * @param {(Object.| - * function(Object.,string,jQuery.jqXHR))=} data - * @param {function(Object.,string,jQuery.jqXHR)=} success - * @return {jQuery.jqXHR} - * @see http://api.jquery.com/jquery.getjson/#jQuery-getJSON-url-data-success - */ -$.getJSON = function(url, data, success) {}; - -/** - * @param {string} url - * @param {function(Node,string,jQuery.jqXHR)=} success - * @return {jQuery.jqXHR} - */ -jQuery.getScript = function(url, success) {}; - -/** - * @param {string} url - * @param {function(Node,string,jQuery.jqXHR)=} success - * @return {jQuery.jqXHR} - */ -$.getScript = function(url, success) {}; - -/** @param {string} code */ -jQuery.globalEval = function(code) {}; - -/** @param {string} code */ -$.globalEval = function(code) {}; - -/** - * @param {Array.<*>} arr - * @param {function(*,number)} fnc - * @param {boolean=} invert - * @return {Array.<*>} - */ -jQuery.grep = function(arr, fnc, invert) {}; - -/** - * @param {Array.<*>} arr - * @param {function(*,number)} fnc - * @param {boolean=} invert - * @return {Array.<*>} - */ -$.grep = function(arr, fnc, invert) {}; - -/** - * @param {(string|Element)} arg1 - * @return {!jQuery} - * @nosideeffects - */ -jQuery.prototype.has = function(arg1) {}; - -/** - * @param {string} className - * @return {boolean} - * @nosideeffects - */ -jQuery.prototype.hasClass = function(className) {}; - -/** - * @param {Element} elem - * @return {boolean} - * @nosideeffects - */ -jQuery.hasData = function(elem) {}; - -/** - * @param {Element} elem - * @return {boolean} - * @nosideeffects - */ -$.hasData = function(elem) {}; - -/** - * @param {(string|number|function(number,number))=} arg1 - * @return {(number|!jQuery)} - */ -jQuery.prototype.height = function(arg1) {}; - -/** - * @param {(string|number|function())=} duration - * @param {(function()|string)=} arg2 - * @param {function()=} callback - * @return {!jQuery} - */ -jQuery.prototype.hide = function(duration, arg2, callback) {}; - -/** @param {boolean} hold */ -jQuery.holdReady = function(hold) {}; - -/** @param {boolean} hold */ -$.holdReady = function(hold) {}; - -/** - * @param {function(!jQuery.event=)} arg1 - * @param {function(!jQuery.event=)=} handlerOut - * @return {!jQuery} - */ -jQuery.prototype.hover = function(arg1, handlerOut) {}; - -/** - * @param {(string|function(number,string))=} arg1 - * @return {(string|!jQuery)} - */ -jQuery.prototype.html = function(arg1) {}; - -/** - * @param {*} value - * @param {Array.<*>} arr - * @param {number=} fromIndex - * @return {number} - * @nosideeffects - */ -jQuery.inArray = function(value, arr, fromIndex) {}; - -/** - * @param {*} value - * @param {Array.<*>} arr - * @param {number=} fromIndex - * @return {number} - * @nosideeffects - */ -$.inArray = function(value, arr, fromIndex) {}; - -/** - * @param {(jQuerySelector|Element|jQuery)=} arg1 - * @return {number} - */ -jQuery.prototype.index = function(arg1) {}; - -/** - * @return {number} - * @nosideeffects - */ -jQuery.prototype.innerHeight = function() {}; - -/** - * @return {number} - * @nosideeffects - */ -jQuery.prototype.innerWidth = function() {}; - -/** - * @param {(jQuerySelector|Element|jQuery)} target - * @return {!jQuery} - */ -jQuery.prototype.insertAfter = function(target) {}; - -/** - * @param {(jQuerySelector|Element|jQuery)} target - * @return {!jQuery} - */ -jQuery.prototype.insertBefore = function(target) {}; - -/** - * @param {(jQuerySelector|function(number)|jQuery|Element)} arg1 - * @return {boolean} - */ -jQuery.prototype.is = function(arg1) {}; - -/** - * @param {*} obj - * @return {boolean} - * @nosideeffects - */ -jQuery.isArray = function(obj) {}; - -/** - * @param {*} obj - * @return {boolean} - * @nosideeffects - */ -$.isArray = function(obj) {}; - -/** - * @param {Object} obj - * @return {boolean} - * @nosideeffects - */ -jQuery.isEmptyObject = function(obj) {}; - -/** - * @param {Object} obj - * @return {boolean} - * @nosideeffects - */ -$.isEmptyObject = function(obj) {}; - -/** - * @param {*} obj - * @return {boolean} - * @nosideeffects - */ -jQuery.isFunction = function(obj) {}; - -/** - * @param {*} obj - * @return {boolean} - * @nosideeffects - */ -$.isFunction = function(obj) {}; - -/** - * @param {*} value - * @return {boolean} - * @nosideeffects - */ -jQuery.isNumeric = function(value) {}; - -/** - * @param {*} value - * @return {boolean} - * @nosideeffects - */ -$.isNumeric = function(value) {}; - -/** - * @param {*} obj - * @return {boolean} - * @nosideeffects - */ -jQuery.isPlainObject = function(obj) {}; - -/** - * @param {*} obj - * @return {boolean} - * @nosideeffects - */ -$.isPlainObject = function(obj) {}; - -/** - * @param {*} obj - * @return {boolean} - * @nosideeffects - */ -jQuery.isWindow = function(obj) {}; - -/** - * @param {*} obj - * @return {boolean} - * @nosideeffects - */ -$.isWindow = function(obj) {}; - -/** - * @param {Element} node - * @return {boolean} - * @nosideeffects - */ -jQuery.isXMLDoc = function(node) {}; - -/** - * @param {Element} node - * @return {boolean} - * @nosideeffects - */ -$.isXMLDoc = function(node) {}; - -/** @type {string} */ -jQuery.prototype.jquery; - -/** - * @constructor - * @extends {XMLHttpRequest} - * @implements {jQuery.Promise} - * @private - * @see http://api.jquery.com/jQuery.ajax/#jqXHR - */ -jQuery.jqXHR = function () {}; - -/** - * @override - * @param {jQueryCallback} alwaysCallbacks - * @param {jQueryCallback=} alwaysCallbacks2 - * @return {jQuery.jqXHR} - */ -jQuery.jqXHR.prototype.always = - function(alwaysCallbacks, alwaysCallbacks2) {}; - -/** - * @deprecated - * @param {function()} callback - * @return {jQuery.jqXHR} -*/ -jQuery.jqXHR.prototype.complete = function (callback) {}; - -/** - * @override - * @param {jQueryCallback} doneCallbacks - * @return {jQuery.jqXHR} - */ -jQuery.jqXHR.prototype.done = function(doneCallbacks) {}; - -/** - * @deprecated - * @param {function()} callback - * @return {jQuery.jqXHR} -*/ -jQuery.jqXHR.prototype.error = function (callback) {}; - -/** - * @override - * @param {jQueryCallback} failCallbacks - * @return {jQuery.jqXHR} - */ -jQuery.jqXHR.prototype.fail = function(failCallbacks) {}; - -/** - * @deprecated - * @override - */ -jQuery.jqXHR.prototype.onreadystatechange = function (callback) {}; - -/** - * @override - * @param {function()=} doneFilter - * @param {function()=} failFilter - * @param {function()=} progressFilter - * @return {jQuery.jqXHR} - */ -jQuery.jqXHR.prototype.pipe = - function(doneFilter, failFilter, progressFilter) {}; - -/** - * @deprecated - * @param {function()} callback - * @return {jQuery.jqXHR} -*/ -jQuery.jqXHR.prototype.success = function (callback) {}; - -/** - * @override - * @param {jQueryCallback} doneCallbacks - * @param {jQueryCallback=} failCallbacks - * @param {jQueryCallback=} progressCallbacks - * @return {jQuery.jqXHR} - */ -jQuery.jqXHR.prototype.then = - function(doneCallbacks, failCallbacks, progressCallbacks) {}; - -/** - * @param {(function(!jQuery.event=)|Object.)=} arg1 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.keydown = function(arg1, handler) {}; - -/** - * @param {(function(!jQuery.event=)|Object.)=} arg1 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.keypress = function(arg1, handler) {}; - -/** - * @param {(function(!jQuery.event=)|Object.)=} arg1 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.keyup = function(arg1, handler) {}; - -/** @return {!jQuery} */ -jQuery.prototype.last = function() {}; - -/** @type {number} */ -jQuery.prototype.length; - -/** - * @deprecated Please avoid the document loading Event invocation of - * .load() and use .on( "load", handler ) instead. (The AJAX - * module invocation signature is OK.) - * @param {(function(!jQuery.event=)|Object.|string)} arg1 - * @param {(function(!jQuery.event=)|Object.|string)=} arg2 - * @param {function(string,string,XMLHttpRequest)=} complete - * @return {!jQuery} - */ -jQuery.prototype.load = function(arg1, arg2, complete) {}; - -/** - * @param {*} obj - * @return {Array.<*>} - */ -jQuery.makeArray = function(obj) {}; - -/** - * @param {*} obj - * @return {Array.<*>} - */ -$.makeArray = function(obj) {}; - -/** - * @param {(Array.<*>|Object.)} arg1 - * @param {(function(*,number)|function(*,(string|number)))} callback - * @return {Array.<*>} - */ -jQuery.map = function(arg1, callback) {}; - -/** - * @param {function(number,Element)} callback - * @return {!jQuery} - */ -jQuery.prototype.map = function(callback) {}; - -/** - * @param {(Array.<*>|Object.)} arg1 - * @param {(function(*,number)|function(*,(string|number)))} callback - * @return {Array.<*>} - */ -$.map = function(arg1, callback) {}; - -/** - * @param {Array.<*>} first - * @param {Array.<*>} second - * @return {Array.<*>} - */ -jQuery.merge = function(first, second) {}; - -/** - * @param {Array.<*>} first - * @param {Array.<*>} second - * @return {Array.<*>} - */ -$.merge = function(first, second) {}; - -/** - * @param {(function(!jQuery.event=)|Object.)=} arg1 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.mousedown = function(arg1, handler) {}; - -/** - * @param {(function(!jQuery.event=)|Object.)=} arg1 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.mouseenter = function(arg1, handler) {}; - -/** - * @param {(function(!jQuery.event=)|Object.)=} arg1 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.mouseleave = function(arg1, handler) {}; - -/** - * @param {(function(!jQuery.event=)|Object.)=} arg1 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.mousemove = function(arg1, handler) {}; - -/** - * @param {(function(!jQuery.event=)|Object.)=} arg1 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.mouseout = function(arg1, handler) {}; - -/** - * @param {(function(!jQuery.event=)|Object.)=} arg1 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.mouseover = function(arg1, handler) {}; - -/** - * @param {(function(!jQuery.event=)|Object.)=} arg1 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.mouseup = function(arg1, handler) {}; - -/** - * @param {jQuerySelector=} selector - * @return {!jQuery} - * @nosideeffects - */ -jQuery.prototype.next = function(selector) {}; - -/** - * @param {string=} selector - * @return {!jQuery} - * @nosideeffects - */ -jQuery.prototype.nextAll = function(selector) {}; - -/** - * @param {(jQuerySelector|Element)=} arg1 - * @param {jQuerySelector=} filter - * @return {!jQuery} - * @nosideeffects - */ -jQuery.prototype.nextUntil = function(arg1, filter) {}; - -/** - * @param {boolean=} removeAll - * @return {Object} - */ -jQuery.noConflict = function(removeAll) {}; - -/** - * @param {boolean=} removeAll - * @return {Object} - */ -$.noConflict = function(removeAll) {}; - -/** - * @return {function()} - * @nosideeffects - */ -jQuery.noop = function() {}; - -/** - * @return {function()} - * @nosideeffects - */ -$.noop = function() {}; - -/** - * @param {(jQuerySelector|Array.|function(number)|jQuery)} arg1 - * @return {!jQuery} - */ -jQuery.prototype.not = function(arg1) {}; - -/** - * @return {number} - * @nosideeffects - */ -jQuery.now = function() {}; - -/** - * @return {number} - * @nosideeffects - */ -$.now = function() {}; - -/** - * @param {(string|Object.)=} arg1 - * @param {(string|function(!jQuery.event=))=} selector - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.off = function(arg1, selector, handler) {}; - -/** - * @param {({left:number,top:number}| - * function(number,{top:number,left:number}))=} arg1 - * @return {({left:number,top:number}|!jQuery)} - */ -jQuery.prototype.offset = function(arg1) {}; - -/** - * @return {!jQuery} - * @nosideeffects - */ -jQuery.prototype.offsetParent = function() {}; - -/** - * @param {(string|Object.)} arg1 - * @param {*=} selector - * @param {*=} data - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.on = function(arg1, selector, data, handler) {}; - -/** - * @param {(string|Object.)} arg1 - * @param {*=} arg2 - * @param {*=} arg3 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.one = function(arg1, arg2, arg3, handler) {}; - -/** - * @param {boolean=} includeMargin - * @return {number} - * @nosideeffects - */ -jQuery.prototype.outerHeight = function(includeMargin) {}; - -/** - * @param {boolean=} includeMargin - * @return {number} - * @nosideeffects - */ -jQuery.prototype.outerWidth = function(includeMargin) {}; - -/** - * @param {(Object.|Array.>)} obj - * @param {boolean=} traditional - * @return {string} - */ -jQuery.param = function(obj, traditional) {}; - -/** - * @param {(Object.|Array.>)} obj - * @param {boolean=} traditional - * @return {string} - */ -$.param = function(obj, traditional) {}; - -/** - * @param {jQuerySelector=} selector - * @return {!jQuery} - * @nosideeffects - */ -jQuery.prototype.parent = function(selector) {}; - -/** - * @param {jQuerySelector=} selector - * @return {!jQuery} - * @nosideeffects - */ -jQuery.prototype.parents = function(selector) {}; - -/** - * @param {(jQuerySelector|Element)=} arg1 - * @param {jQuerySelector=} filter - * @return {!jQuery} - * @nosideeffects - */ -jQuery.prototype.parentsUntil = function(arg1, filter) {}; - -/** - * @param {string} data - * @param {(Element|boolean)=} context - * @param {boolean=} keepScripts - * @return {Array.} - */ -jQuery.parseHTML = function(data, context, keepScripts) {}; - -/** - * @param {string} data - * @param {(Element|boolean)=} context - * @param {boolean=} keepScripts - * @return {Array.} - */ -$.parseHTML = function(data, context, keepScripts) {}; - -/** - * @param {string} json - * @return {string|number|Object.|Array.|boolean} - */ -jQuery.parseJSON = function(json) {}; - -/** - * @param {string} json - * @return {Object.} - */ -$.parseJSON = function(json) {}; - -/** - * @param {string} data - * @return {Document} - */ -jQuery.parseXML = function(data) {}; - -/** - * @param {string} data - * @return {Document} - */ -$.parseXML = function(data) {}; - -/** - * @return {{left:number,top:number}} - * @nosideeffects - */ -jQuery.prototype.position = function() {}; - -/** - * @param {string} url - * @param {(Object.|string| - * function(string,string,jQuery.jqXHR))=} data - * @param {(function(string,string,jQuery.jqXHR)|string)=} success - * @param {string=} dataType - * @return {jQuery.jqXHR} - */ -jQuery.post = function(url, data, success, dataType) {}; - -/** - * @param {string} url - * @param {(Object.|string| - * function(string,string,jQuery.jqXHR))=} data - * @param {(function(string,string,jQuery.jqXHR)|string)=} success - * @param {string=} dataType - * @return {jQuery.jqXHR} - */ -$.post = function(url, data, success, dataType) {}; - -/** - * @param {(string|Element|jQuery|function(number,string))} arg1 - * @param {(string|Element|jQuery)=} content - * @return {!jQuery} - */ -jQuery.prototype.prepend = function(arg1, content) {}; - -/** - * @param {(jQuerySelector|Element|jQuery)} target - * @return {!jQuery} - */ -jQuery.prototype.prependTo = function(target) {}; - -/** - * @param {jQuerySelector=} selector - * @return {!jQuery} - * @nosideeffects - */ -jQuery.prototype.prev = function(selector) {}; - -/** - * @param {jQuerySelector=} selector - * @return {!jQuery} - * @nosideeffects - */ -jQuery.prototype.prevAll = function(selector) {}; - -/** - * @param {(jQuerySelector|Element)=} arg1 - * @param {jQuerySelector=} filter - * @return {!jQuery} - * @nosideeffects - */ -jQuery.prototype.prevUntil = function(arg1, filter) {}; - -/** - * @param {(string|Object)=} type - * @param {Object=} target - * @return {jQuery.Promise} - */ -jQuery.prototype.promise = function(type, target) {}; - -/** - * @interface - * @private - * @see http://api.jquery.com/Types/#Promise - */ -jQuery.Promise = function () {}; - -/** - * @param {jQueryCallback} alwaysCallbacks - * @param {jQueryCallback=} alwaysCallbacks2 - * @return {jQuery.Promise} - */ -jQuery.Promise.prototype.always = - function(alwaysCallbacks, alwaysCallbacks2) {}; - -/** - * @param {jQueryCallback} doneCallbacks - * @return {jQuery.Promise} - */ -jQuery.Promise.prototype.done = function(doneCallbacks) {}; - -/** - * @param {jQueryCallback} failCallbacks - * @return {jQuery.Promise} - */ -jQuery.Promise.prototype.fail = function(failCallbacks) {}; - -/** - * @param {function()=} doneFilter - * @param {function()=} failFilter - * @param {function()=} progressFilter - * @return {jQuery.Promise} - */ -jQuery.Promise.prototype.pipe = - function(doneFilter, failFilter, progressFilter) {}; - -/** - * @param {jQueryCallback} doneCallbacks - * @param {jQueryCallback=} failCallbacks - * @param {jQueryCallback=} progressCallbacks - * @return {jQuery.Promise} - */ -jQuery.Promise.prototype.then = - function(doneCallbacks, failCallbacks, progressCallbacks) {}; - -/** - * @param {(string|Object.)} arg1 - * @param {(string|number|boolean|function(number,String))=} arg2 - * @return {(string|boolean|!jQuery)} - */ -jQuery.prototype.prop = function(arg1, arg2) {}; - -/** - * @param {...*} var_args - * @return {function()} - */ -jQuery.proxy = function(var_args) {}; - -/** - * @param {...*} var_args - * @return {function()} - */ -$.proxy = function(var_args) {}; - -/** - * @param {Array.} elements - * @param {string=} name - * @param {Array.<*>=} args - * @return {!jQuery} - */ -jQuery.prototype.pushStack = function(elements, name, args) {}; - -/** - * @param {(string|Array.|function(function()))=} queueName - * @param {(Array.|function(function()))=} arg2 - * @return {(Array.|!jQuery)} - */ -jQuery.prototype.queue = function(queueName, arg2) {}; - -/** - * @param {Element} elem - * @param {string=} queueName - * @param {(Array.|function())=} arg3 - * @return {(Array.|!jQuery)} - */ -jQuery.queue = function(elem, queueName, arg3) {}; - -/** - * @param {Element} elem - * @param {string=} queueName - * @param {(Array.|function())=} arg3 - * @return {(Array.|!jQuery)} - */ -$.queue = function(elem, queueName, arg3) {}; - -/** - * @param {function()} handler - * @return {!jQuery} - */ -jQuery.prototype.ready = function(handler) {}; - -/** - * @param {string=} selector - * @return {!jQuery} - */ -jQuery.prototype.remove = function(selector) {}; - -/** - * @param {string} attributeName - * @return {!jQuery} - */ -jQuery.prototype.removeAttr = function(attributeName) {}; - -/** - * @param {(string|function(number,string))=} arg1 - * @return {!jQuery} - */ -jQuery.prototype.removeClass = function(arg1) {}; - -/** - * @param {(string|Array.)=} arg1 - * @return {!jQuery} - */ -jQuery.prototype.removeData = function(arg1) {}; - -/** - * @param {Element} elem - * @param {string=} name - * @return {!jQuery} - */ -jQuery.removeData = function(elem, name) {}; - -/** - * @param {Element} elem - * @param {string=} name - * @return {!jQuery} - */ -$.removeData = function(elem, name) {}; - -/** - * @param {string} propertyName - * @return {!jQuery} - */ -jQuery.prototype.removeProp = function(propertyName) {}; - -/** - * @param {jQuerySelector} target - * @return {!jQuery} - */ -jQuery.prototype.replaceAll = function(target) {}; - -/** - * @param {(string|Element|jQuery|function())} arg1 - * @return {!jQuery} - */ -jQuery.prototype.replaceWith = function(arg1) {}; - -/** - * @param {(function(!jQuery.event=)|Object.)=} arg1 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.resize = function(arg1, handler) {}; - -/** - * @param {(function(!jQuery.event=)|Object.)=} arg1 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.scroll = function(arg1, handler) {}; - -/** - * @param {number=} value - * @return {(number|!jQuery)} - */ -jQuery.prototype.scrollLeft = function(value) {}; - -/** - * @param {number=} value - * @return {(number|!jQuery)} - */ -jQuery.prototype.scrollTop = function(value) {}; - -/** - * @param {(function(!jQuery.event=)|Object.)=} arg1 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.select = function(arg1, handler) {}; - -/** - * @return {string} - * @nosideeffects - */ -jQuery.prototype.serialize = function() {}; - -/** - * @return {Array.>} - * @nosideeffects - */ -jQuery.prototype.serializeArray = function() {}; - -/** - * @param {(string|number|function())=} duration - * @param {(function()|string)=} arg2 - * @param {function()=} callback - * @return {!jQuery} - */ -jQuery.prototype.show = function(duration, arg2, callback) {}; - -/** - * @param {jQuerySelector=} selector - * @return {!jQuery} - * @nosideeffects - */ -jQuery.prototype.siblings = function(selector) {}; - -/** - * @deprecated Please use the .length property instead. - * @return {number} - * @nosideeffects - */ -jQuery.prototype.size = function() {}; - -/** - * @param {number} start - * @param {number=} end - * @return {!jQuery} - */ -jQuery.prototype.slice = function(start, end) {}; - -/** - * @param {(Object.|string|number)=} optionsOrDuration - * @param {(function()|string)=} completeOrEasing - * @param {function()=} complete - * @return {!jQuery} - */ -jQuery.prototype.slideDown = - function(optionsOrDuration, completeOrEasing, complete) {}; - -/** - * @param {(Object.|string|number)=} optionsOrDuration - * @param {(function()|string)=} completeOrEasing - * @param {function()=} complete - * @return {!jQuery} - */ -jQuery.prototype.slideToggle = - function(optionsOrDuration, completeOrEasing, complete) {}; - -/** - * @param {(Object.|string|number)=} optionsOrDuration - * @param {(function()|string)=} completeOrEasing - * @param {function()=} complete - * @return {!jQuery} - */ -jQuery.prototype.slideUp = - function(optionsOrDuration, completeOrEasing, complete) {}; - -/** - * @param {(boolean|string)=} arg1 - * @param {boolean=} arg2 - * @param {boolean=} jumpToEnd - * @return {!jQuery} - */ -jQuery.prototype.stop = function(arg1, arg2, jumpToEnd) {}; - -/** - * @param {(function(!jQuery.event=)|Object.)=} arg1 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.submit = function(arg1, handler) {}; - -/** @type {Object.} - * @deprecated Please try to use feature detection instead. - */ -jQuery.support; - -/** @type {Object.} - * @deprecated Please try to use feature detection instead. - */ -$.support; - -/** - * @deprecated Please try to use feature detection instead. - * @type {boolean} - */ -jQuery.support.boxModel; - -/** - * @deprecated Please try to use feature detection instead. - * @type {boolean} - */ -$.support.boxModel; - -/** @type {boolean} */ -jQuery.support.changeBubbles; - -/** @type {boolean} */ -$.support.changeBubbles; - -/** @type {boolean} */ -jQuery.support.cors; - -/** @type {boolean} */ -$.support.cors; - -/** @type {boolean} */ -jQuery.support.cssFloat; - -/** @type {boolean} */ -$.support.cssFloat; - -/** @type {boolean} */ -jQuery.support.hrefNormalized; - -/** @type {boolean} */ -$.support.hrefNormalized; - -/** @type {boolean} */ -jQuery.support.htmlSerialize; - -/** @type {boolean} */ -$.support.htmlSerialize; - -/** @type {boolean} */ -jQuery.support.leadingWhitespace; - -/** @type {boolean} */ -$.support.leadingWhitespace; - -/** @type {boolean} */ -jQuery.support.noCloneEvent; - -/** @type {boolean} */ -$.support.noCloneEvent; - -/** @type {boolean} */ -jQuery.support.opacity; - -/** @type {boolean} */ -$.support.opacity; - -/** @type {boolean} */ -jQuery.support.style; - -/** @type {boolean} */ -$.support.style; - -/** @type {boolean} */ -jQuery.support.submitBubbles; - -/** @type {boolean} */ -$.support.submitBubbles; - -/** @type {boolean} */ -jQuery.support.tbody; - -/** @type {boolean} */ -$.support.tbody; - -/** - * @param {(string|function(number,string))=} arg1 - * @return {(string|!jQuery)} - */ -jQuery.prototype.text = function(arg1) {}; - -/** - * @return {Array.} - * @nosideeffects - */ -jQuery.prototype.toArray = function() {}; - -/** - * Refers to the method from the Effects category. There used to be a toggle - * method on the Events category which was removed starting version 1.9. - * @param {(number|string|Object.|boolean)=} arg1 - * @param {(function()|string)=} arg2 - * @param {function()=} arg3 - * @return {!jQuery} - */ -jQuery.prototype.toggle = function(arg1, arg2, arg3) {}; - -/** - * @param {(string|boolean|function(number,string,boolean))=} arg1 - * @param {boolean=} flag - * @return {!jQuery} - */ -jQuery.prototype.toggleClass = function(arg1, flag) {}; - -/** - * @param {(string|jQuery.event)} arg1 - * @param {...*} var_args - * @return {!jQuery} - */ -jQuery.prototype.trigger = function(arg1, var_args) {}; - -/** - * @param {string|jQuery.event} eventType - * @param {Array.<*>=} extraParameters - * @return {*} - */ -jQuery.prototype.triggerHandler = function(eventType, extraParameters) {}; - -/** - * @param {string} str - * @return {string} - * @nosideeffects - */ -jQuery.trim = function(str) {}; - -/** - * @param {string} str - * @return {string} - * @nosideeffects - */ -$.trim = function(str) {}; - -/** - * @param {*} obj - * @return {string} - * @nosideeffects - */ -jQuery.type = function(obj) {}; - -/** - * @param {*} obj - * @return {string} - * @nosideeffects - */ -$.type = function(obj) {}; - -/** - * @param {(string|function(!jQuery.event=)|jQuery.event)=} arg1 - * @param {(function(!jQuery.event=)|boolean)=} arg2 - * @return {!jQuery} - */ -jQuery.prototype.unbind = function(arg1, arg2) {}; - -/** - * @param {string=} arg1 - * @param {(string|Object.)=} arg2 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.undelegate = function(arg1, arg2, handler) {}; - -/** - * @param {Array.} arr - * @return {Array.} - */ -jQuery.unique = function(arr) {}; - -/** - * @param {Array.} arr - * @return {Array.} - */ -$.unique = function(arr) {}; - -/** - * @deprecated Please use .on( "unload", handler ) instead. - * @param {(function(!jQuery.event=)|Object.)} arg1 - * @param {function(!jQuery.event=)=} handler - * @return {!jQuery} - */ -jQuery.prototype.unload = function(arg1, handler) {}; - -/** @return {!jQuery} */ -jQuery.prototype.unwrap = function() {}; - -/** - * @param {(string|Array.|function(number,*))=} arg1 - * @return {(string|number|Array.|!jQuery)} - */ -jQuery.prototype.val = function(arg1) {}; - -/** - * Note: The official documentation (https://api.jquery.com/jQuery.when/) says - * jQuery.when accepts deferreds, but it actually accepts any type, e.g.: - * - * jQuery.when(jQuery.ready, jQuery.ajax(''), jQuery('#my-element'), 1) - * - * If an argument is not an "observable" (a promise-like object) it is wrapped - * into a promise. - * @param {*} deferred - * @param {...*} deferreds - * @return {jQuery.Promise} - */ -jQuery.when = function(deferred, deferreds) {}; - -/** - * Note: See jQuery.when(). - * @param {*} deferred - * @param {...*} deferreds - * @return {jQuery.Promise} - */ -$.when = function(deferred, deferreds) {}; - -/** - * @param {(string|number|function(number,number))=} arg1 - * @return {(number|!jQuery)} - */ -jQuery.prototype.width = function(arg1) {}; - -/** - * @param {(string|jQuerySelector|Element|jQuery|function(number))} arg1 - * @return {!jQuery} - */ -jQuery.prototype.wrap = function(arg1) {}; - -/** - * @param {(string|jQuerySelector|Element|jQuery)} wrappingElement - * @return {!jQuery} - */ -jQuery.prototype.wrapAll = function(wrappingElement) {}; - -/** - * @param {(string|jQuerySelector|Element|jQuery|function(number))} arg1 - * @return {!jQuery} - */ -jQuery.prototype.wrapInner = function(arg1) {}; diff --git a/js/modal.js b/js/modal.js index fb4cd0329..0426561af 100644 --- a/js/modal.js +++ b/js/modal.js @@ -1,598 +1,337 @@ -/** ======================================================================= - * Bootstrap: modal.js v4.0.0 - * http://getbootstrap.com/javascript/#modal +/* ======================================================================== + * Bootstrap: modal.js v3.3.4 + * http://getbootstrap.com/javascript/#modals * ======================================================================== * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== - * @fileoverview - Bootstrap's modal plugin. Modals are streamlined, but - * flexible, dialog prompts with the minimum required functionality and - * smart defaults. - * - * Public Methods & Properties: - * - * + $.modal - * + $.modal.noConflict - * + $.modal.Constructor - * + $.modal.Constructor.VERSION - * + $.modal.Constructor.Defaults - * + $.modal.Constructor.Defaults.backdrop - * + $.modal.Constructor.Defaults.keyboard - * + $.modal.Constructor.Defaults.show - * + $.modal.Constructor.prototype.toggle - * + $.modal.Constructor.prototype.show - * + $.modal.Constructor.prototype.hide - * - * ======================================================================== - */ - -'use strict'; - - -/** - * Our modal class. - * @param {Element} element - * @param {Object} config - * @constructor - */ -var Modal = function (element, config) { - - /** @private {Object} */ - this._config = config - - /** @private {Element} */ - this._element = element + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // MODAL CLASS DEFINITION + // ====================== + + var Modal = function (element, options) { + this.options = options + this.$body = $(document.body) + this.$element = $(element) + this.$dialog = this.$element.find('.modal-dialog') + this.$backdrop = null + this.isShown = null + this.originalBodyPad = null + this.scrollbarWidth = 0 + this.ignoreBackdropClick = false + + if (this.options.remote) { + this.$element + .find('.modal-content') + .load(this.options.remote, $.proxy(function () { + this.$element.trigger('loaded.bs.modal') + }, this)) + } + } - /** @private {Element} */ - this._backdrop = null + Modal.VERSION = '3.3.4' - /** @private {boolean} */ - this._isShown = false - - /** @private {boolean} */ - this._isBodyOverflowing = false - - /** @private {number} */ - this._scrollbarWidth = 0 + Modal.TRANSITION_DURATION = 300 + Modal.BACKDROP_TRANSITION_DURATION = 150 -} + Modal.DEFAULTS = { + backdrop: true, + keyboard: true, + show: true + } + Modal.prototype.toggle = function (_relatedTarget) { + return this.isShown ? this.hide() : this.show(_relatedTarget) + } -/** - * @const - * @type {string} - */ -Modal['VERSION'] = '4.0.0' - - -/** - * @const - * @type {Object} - */ -Modal['Defaults'] = { - 'backdrop' : true, - 'keyboard' : true, - 'show' : true -} - - -/** - * @const - * @type {string} - * @private - */ -Modal._NAME = 'modal' - - -/** - * @const - * @type {string} - * @private - */ -Modal._DATA_KEY = 'bs.modal' - - -/** - * @const - * @type {number} - * @private - */ -Modal._TRANSITION_DURATION = 300 - - -/** - * @const - * @type {number} - * @private - */ -Modal._BACKDROP_TRANSITION_DURATION = 150 - - -/** - * @const - * @type {Function} - * @private - */ -Modal._JQUERY_NO_CONFLICT = $.fn[Modal._NAME] - - -/** - * @const - * @enum {string} - * @private - */ -Modal._Event = { - HIDE : 'hide.bs.modal', - HIDDEN : 'hidden.bs.modal', - SHOW : 'show.bs.modal', - SHOWN : 'shown.bs.modal' -} - - -/** - * @const - * @enum {string} - * @private - */ -Modal._ClassName = { - BACKDROP : 'modal-backdrop', - OPEN : 'modal-open', - FADE : 'fade', - IN : 'in' -} - - -/** - * @const - * @enum {string} - * @private - */ -Modal._Selector = { - DIALOG : '.modal-dialog', - DATA_TOGGLE : '[data-toggle="modal"]', - DATA_DISMISS : '[data-dismiss="modal"]', - SCROLLBAR_MEASURER : 'modal-scrollbar-measure' -} - - - -/** - * Provides the jQuery Interface for the alert component. - * @param {Object|string=} opt_config - * @param {Element=} opt_relatedTarget - * @this {jQuery} - * @return {jQuery} - * @private - */ -Modal._jQueryInterface = function Plugin(opt_config, opt_relatedTarget) { - return this.each(function () { - var data = $(this).data(Modal._DATA_KEY) - var config = $.extend({}, Modal['Defaults'], $(this).data(), typeof opt_config == 'object' && opt_config) - - if (!data) { - data = new Modal(this, config) - $(this).data(Modal._DATA_KEY, data) - } + Modal.prototype.show = function (_relatedTarget) { + var that = this + var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget }) - if (typeof opt_config == 'string') { - data[opt_config](opt_relatedTarget) + this.$element.trigger(e) - } else if (config['show']) { - data['show'](opt_relatedTarget) - } - }) -} + if (this.isShown || e.isDefaultPrevented()) return + this.isShown = true -/** - * @param {Element} relatedTarget - */ -Modal.prototype['toggle'] = function (relatedTarget) { - return this._isShown ? this['hide']() : this['show'](relatedTarget) -} + this.checkScrollbar() + this.setScrollbar() + this.$body.addClass('modal-open') + this.escape() + this.resize() -/** - * @param {Element} relatedTarget - */ -Modal.prototype['show'] = function (relatedTarget) { - var showEvent = $.Event(Modal._Event.SHOW, { relatedTarget: relatedTarget }) + this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) - $(this._element).trigger(showEvent) + this.$dialog.on('mousedown.dismiss.bs.modal', function () { + that.$element.one('mouseup.dismiss.bs.modal', function (e) { + if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true + }) + }) - if (this._isShown || showEvent.isDefaultPrevented()) { - return - } + this.backdrop(function () { + var transition = $.support.transition && that.$element.hasClass('fade') - this._isShown = true + if (!that.$element.parent().length) { + that.$element.appendTo(that.$body) // don't move modals dom position + } - this._checkScrollbar() - this._setScrollbar() + that.$element + .show() + .scrollTop(0) - $(document.body).addClass(Modal._ClassName.OPEN) + that.adjustDialog() - this._escape() - this._resize() + if (transition) { + that.$element[0].offsetWidth // force reflow + } - $(this._element).on('click.dismiss.bs.modal', Modal._Selector.DATA_DISMISS, this['hide'].bind(this)) + that.$element.addClass('in') - this._showBackdrop(this._showElement.bind(this, relatedTarget)) -} + that.enforceFocus() + var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) -/** - * @param {Event} event - */ -Modal.prototype['hide'] = function (event) { - if (event) { - event.preventDefault() + transition ? + that.$dialog // wait for modal to slide in + .one('bsTransitionEnd', function () { + that.$element.trigger('focus').trigger(e) + }) + .emulateTransitionEnd(Modal.TRANSITION_DURATION) : + that.$element.trigger('focus').trigger(e) + }) } - var hideEvent = $.Event(Modal._Event.HIDE) - - $(this._element).trigger(hideEvent) - - if (!this._isShown || hideEvent.isDefaultPrevented()) { - return - } + Modal.prototype.hide = function (e) { + if (e) e.preventDefault() - this._isShown = false + e = $.Event('hide.bs.modal') - this._escape() - this._resize() + this.$element.trigger(e) - $(document).off('focusin.bs.modal') + if (!this.isShown || e.isDefaultPrevented()) return - $(this._element).removeClass(Modal._ClassName.IN) - this._element.setAttribute('aria-hidden', true) + this.isShown = false - $(this._element).off('click.dismiss.bs.modal') + this.escape() + this.resize() - if (Bootstrap.transition && $(this._element).hasClass(Modal._ClassName.FADE)) { - $(this._element) - .one(Bootstrap.TRANSITION_END, this._hideModal.bind(this)) - .emulateTransitionEnd(Modal._TRANSITION_DURATION) - } else { - this._hideModal() - } -} + $(document).off('focusin.bs.modal') + this.$element + .removeClass('in') + .off('click.dismiss.bs.modal') + .off('mouseup.dismiss.bs.modal') -/** - * @param {Element} relatedTarget - * @private - */ -Modal.prototype._showElement = function (relatedTarget) { - var transition = Bootstrap.transition && $(this._element).hasClass(Modal._ClassName.FADE) + this.$dialog.off('mousedown.dismiss.bs.modal') - if (!this._element.parentNode || this._element.parentNode.nodeType != Node.ELEMENT_NODE) { - document.body.appendChild(this._element) // don't move modals dom position + $.support.transition && this.$element.hasClass('fade') ? + this.$element + .one('bsTransitionEnd', $.proxy(this.hideModal, this)) + .emulateTransitionEnd(Modal.TRANSITION_DURATION) : + this.hideModal() } - this._element.style.display = 'block' - this._element.scrollTop = 0 - - if (this._config['backdrop']) { - this._adjustBackdrop() + Modal.prototype.enforceFocus = function () { + $(document) + .off('focusin.bs.modal') // guard against infinite focus loop + .on('focusin.bs.modal', $.proxy(function (e) { + if (this.$element[0] !== e.target && !this.$element.has(e.target).length) { + this.$element.trigger('focus') + } + }, this)) } - if (transition) { - Bootstrap.reflow(this._element) + Modal.prototype.escape = function () { + if (this.isShown && this.options.keyboard) { + this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) { + e.which == 27 && this.hide() + }, this)) + } else if (!this.isShown) { + this.$element.off('keydown.dismiss.bs.modal') + } } - $(this._element).addClass(Modal._ClassName.IN) - this._element.setAttribute('aria-hidden', false) - - this._enforceFocus() - - var shownEvent = $.Event(Modal._Event.SHOWN, { relatedTarget: relatedTarget }) - - var transitionComplete = function () { - this._element.focus() - $(this._element).trigger(shownEvent) - }.bind(this) - - if (transition) { - var dialog = $(this._element).find(Modal._Selector.DIALOG)[0] - $(dialog) - .one(Bootstrap.TRANSITION_END, transitionComplete) - .emulateTransitionEnd(Modal._TRANSITION_DURATION) - } else { - transitionComplete() + Modal.prototype.resize = function () { + if (this.isShown) { + $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this)) + } else { + $(window).off('resize.bs.modal') + } } -} - - -/** - * @private - */ -Modal.prototype._enforceFocus = function () { - $(document) - .off('focusin.bs.modal') // guard against infinite focus loop - .on('focusin.bs.modal', function (e) { - if (this._element !== e.target && !$(this._element).has(e.target).length) { - this._element.focus() - } - }.bind(this)) -} - - -/** - * @private - */ -Modal.prototype._escape = function () { - if (this._isShown && this._config['keyboard']) { - $(this._element).on('keydown.dismiss.bs.modal', function (event) { - if (event.which === 27) { - this['hide']() - } - }.bind(this)) - - } else if (!this._isShown) { - $(this._element).off('keydown.dismiss.bs.modal') + Modal.prototype.hideModal = function () { + var that = this + this.$element.hide() + this.backdrop(function () { + that.$body.removeClass('modal-open') + that.resetAdjustments() + that.resetScrollbar() + that.$element.trigger('hidden.bs.modal') + }) } -} - -/** - * @private - */ -Modal.prototype._resize = function () { - if (this._isShown) { - $(window).on('resize.bs.modal', this._handleUpdate.bind(this)) - } else { - $(window).off('resize.bs.modal') + Modal.prototype.removeBackdrop = function () { + this.$backdrop && this.$backdrop.remove() + this.$backdrop = null } -} - - -/** - * @private - */ -Modal.prototype._hideModal = function () { - this._element.style.display = 'none' - this._showBackdrop(function () { - $(document.body).removeClass(Modal._ClassName.OPEN) - this._resetAdjustments() - this._resetScrollbar() - $(this._element).trigger(Modal._Event.HIDDEN) - }.bind(this)) -} - - -/** - * @private - */ -Modal.prototype._removeBackdrop = function () { - if (this._backdrop) { - this._backdrop.parentNode.removeChild(this._backdrop) - this._backdrop = null - } -} + Modal.prototype.backdrop = function (callback) { + var that = this + var animate = this.$element.hasClass('fade') ? 'fade' : '' -/** - * @param {Function} callback - * @private - */ -Modal.prototype._showBackdrop = function (callback) { - var animate = $(this._element).hasClass(Modal._ClassName.FADE) ? Modal._ClassName.FADE : '' + if (this.isShown && this.options.backdrop) { + var doAnimate = $.support.transition && animate - if (this._isShown && this._config['backdrop']) { - var doAnimate = Bootstrap.transition && animate + this.$backdrop = $(document.createElement('div')) + .addClass('modal-backdrop ' + animate) + .appendTo(this.$body) - this._backdrop = document.createElement('div') - this._backdrop.className = Modal._ClassName.BACKDROP + this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) { + if (this.ignoreBackdropClick) { + this.ignoreBackdropClick = false + return + } + if (e.target !== e.currentTarget) return + this.options.backdrop == 'static' + ? this.$element[0].focus() + : this.hide() + }, this)) - if (animate) { - $(this._backdrop).addClass(animate) - } + if (doAnimate) this.$backdrop[0].offsetWidth // force reflow - $(this._element).prepend(this._backdrop) + this.$backdrop.addClass('in') - $(this._backdrop).on('click.dismiss.bs.modal', function (event) { - if (event.target !== event.currentTarget) return - this._config['backdrop'] === 'static' - ? this._element.focus() - : this['hide']() - }.bind(this)) + if (!callback) return - if (doAnimate) { - Bootstrap.reflow(this._backdrop) - } + doAnimate ? + this.$backdrop + .one('bsTransitionEnd', callback) + .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : + callback() - $(this._backdrop).addClass(Modal._ClassName.IN) + } else if (!this.isShown && this.$backdrop) { + this.$backdrop.removeClass('in') - if (!callback) { - return - } + var callbackRemove = function () { + that.removeBackdrop() + callback && callback() + } + $.support.transition && this.$element.hasClass('fade') ? + this.$backdrop + .one('bsTransitionEnd', callbackRemove) + .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : + callbackRemove() - if (!doAnimate) { + } else if (callback) { callback() - return } + } - $(this._backdrop) - .one(Bootstrap.TRANSITION_END, callback) - .emulateTransitionEnd(Modal._BACKDROP_TRANSITION_DURATION) + // these following methods are used to handle overflowing modals - } else if (!this._isShown && this._backdrop) { - $(this._backdrop).removeClass(Modal._ClassName.IN) + Modal.prototype.handleUpdate = function () { + this.adjustDialog() + } - var callbackRemove = function () { - this._removeBackdrop() - if (callback) { - callback() - } - }.bind(this) + Modal.prototype.adjustDialog = function () { + var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight - if (Bootstrap.transition && $(this._element).hasClass(Modal._ClassName.FADE)) { - $(this._backdrop) - .one(Bootstrap.TRANSITION_END, callbackRemove) - .emulateTransitionEnd(Modal._BACKDROP_TRANSITION_DURATION) - } else { - callbackRemove() + this.$element.css({ + paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '', + paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : '' + }) + } + + Modal.prototype.resetAdjustments = function () { + this.$element.css({ + paddingLeft: '', + paddingRight: '' + }) + } + + Modal.prototype.checkScrollbar = function () { + var fullWindowWidth = window.innerWidth + if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8 + var documentElementRect = document.documentElement.getBoundingClientRect() + fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left) } + this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth + this.scrollbarWidth = this.measureScrollbar() + } - } else if (callback) { - callback() + Modal.prototype.setScrollbar = function () { + var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) + this.originalBodyPad = document.body.style.paddingRight || '' + if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth) } -} - - -/** - * ------------------------------------------------------------------------ - * the following methods are used to handle overflowing modals - * todo (fat): these should probably be refactored into a - * ------------------------------------------------------------------------ - */ - - -/** - * @private - */ -Modal.prototype._handleUpdate = function () { - if (this._config['backdrop']) this._adjustBackdrop() - this._adjustDialog() -} - -/** - * @private - */ -Modal.prototype._adjustBackdrop = function () { - this._backdrop.style.height = 0 // todo (fat): no clue why we do this - this._backdrop.style.height = this._element.scrollHeight + 'px' -} - - -/** - * @private - */ -Modal.prototype._adjustDialog = function () { - var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight - - if (!this._isBodyOverflowing && isModalOverflowing) { - this._element.style.paddingLeft = this._scrollbarWidth + 'px' + + Modal.prototype.resetScrollbar = function () { + this.$body.css('padding-right', this.originalBodyPad) } - if (this._isBodyOverflowing && !isModalOverflowing) { - this._element.style.paddingRight = this._scrollbarWidth + 'px' + Modal.prototype.measureScrollbar = function () { // thx walsh + var scrollDiv = document.createElement('div') + scrollDiv.className = 'modal-scrollbar-measure' + this.$body.append(scrollDiv) + var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth + this.$body[0].removeChild(scrollDiv) + return scrollbarWidth } -} -/** - * @private - */ -Modal.prototype._resetAdjustments = function () { - this._element.style.paddingLeft = '' - this._element.style.paddingRight = '' -} + // MODAL PLUGIN DEFINITION + // ======================= + function Plugin(option, _relatedTarget) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.modal') + var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) -/** - * @private - */ -Modal.prototype._checkScrollbar = function () { - this._isBodyOverflowing = document.body.scrollHeight > document.documentElement.clientHeight - this._scrollbarWidth = this._getScrollbarWidth() -} + if (!data) $this.data('bs.modal', (data = new Modal(this, options))) + if (typeof option == 'string') data[option](_relatedTarget) + else if (options.show) data.show(_relatedTarget) + }) + } + var old = $.fn.modal -/** - * @private - */ -Modal.prototype._setScrollbar = function () { - var bodyPadding = parseInt(($(document.body).css('padding-right') || 0), 10) + $.fn.modal = Plugin + $.fn.modal.Constructor = Modal - if (this._isBodyOverflowing) { - document.body.style.paddingRight = bodyPadding + this._scrollbarWidth + 'px' - } -} - - -/** - * @private - */ -Modal.prototype._resetScrollbar = function () { - document.body.style.paddingRight = '' -} - - -/** - * @private - */ -Modal.prototype._getScrollbarWidth = function () { // thx walsh - var scrollDiv = document.createElement('div') - scrollDiv.className = Modal._Selector.SCROLLBAR_MEASURER - document.body.appendChild(scrollDiv) - var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth - document.body.removeChild(scrollDiv) - return scrollbarWidth -} - - -/** - * ------------------------------------------------------------------------ - * jQuery Interface + noConflict implementaiton - * ------------------------------------------------------------------------ - */ - -/** - * @const - * @type {Function} - */ -$.fn[Modal._NAME] = Modal._jQueryInterface - - -/** - * @const - * @type {Function} - */ -$.fn[Modal._NAME]['Constructor'] = Modal - - -/** - * @const - * @type {Function} - */ -$.fn[Modal._NAME]['noConflict'] = function () { - $.fn[Modal._NAME] = Modal._JQUERY_NO_CONFLICT - return this -} - - -/** - * ------------------------------------------------------------------------ - * Data Api implementation - * ------------------------------------------------------------------------ - */ - -$(document).on('click.bs.modal.data-api', Modal._Selector.DATA_TOGGLE, function (event) { - var selector = Bootstrap.getSelectorFromElement(this) - - if (selector) { - var target = $(selector)[0] - } - var config = $(target).data(Modal._DATA_KEY) ? 'toggle' : $.extend({}, $(target).data(), $(this).data()) + // MODAL NO CONFLICT + // ================= - if (this.tagName == 'A') { - event.preventDefault() + $.fn.modal.noConflict = function () { + $.fn.modal = old + return this } - var $target = $(target).one(Modal._Event.SHOW, function (showEvent) { - if (showEvent.isDefaultPrevented()) { - return // only register focus restorer if modal will actually get shown - } - $target.one(Modal._Event.HIDDEN, function () { - if ($(this).is(':visible')) { - this.focus() - } - }.bind(this)) - }.bind(this)) + // MODAL DATA-API + // ============== + + $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { + var $this = $(this) + var href = $this.attr('href') + var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7 + var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) + + if ($this.is('a')) e.preventDefault() + + $target.one('show.bs.modal', function (showEvent) { + if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown + $target.one('hidden.bs.modal', function () { + $this.is(':visible') && $this.trigger('focus') + }) + }) + Plugin.call($target, option, this) + }) - Modal._jQueryInterface.call($(target), config, this) -}) +}(jQuery); diff --git a/js/popover.js b/js/popover.js index 566335551..0b0755ee2 100644 --- a/js/popover.js +++ b/js/popover.js @@ -1,283 +1,108 @@ -/** ======================================================================= - * Bootstrap: popover.js v4.0.0 +/* ======================================================================== + * Bootstrap: popover.js v3.3.4 * http://getbootstrap.com/javascript/#popovers * ======================================================================== * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== - * @fileoverview - Bootstrap's popover plugin - extends tooltip. - * - * Public Methods & Properties: - * - * + $.popover - * + $.popover.noConflict - * + $.popover.Constructor - * + $.popover.Constructor.VERSION - * + $.popover.Constructor.Defaults - * + $.popover.Constructor.Defaults.container - * + $.popover.Constructor.Defaults.animation - * + $.popover.Constructor.Defaults.placement - * + $.popover.Constructor.Defaults.selector - * + $.popover.Constructor.Defaults.template - * + $.popover.Constructor.Defaults.trigger - * + $.popover.Constructor.Defaults.title - * + $.popover.Constructor.Defaults.content - * + $.popover.Constructor.Defaults.delay - * + $.popover.Constructor.Defaults.html - * + $.popover.Constructor.Defaults.viewport - * + $.popover.Constructor.Defaults.viewport.selector - * + $.popover.Constructor.Defaults.viewport.padding - * + $.popover.Constructor.prototype.enable - * + $.popover.Constructor.prototype.disable - * + $.popover.Constructor.prototype.destroy - * + $.popover.Constructor.prototype.toggleEnabled - * + $.popover.Constructor.prototype.toggle - * + $.popover.Constructor.prototype.show - * + $.popover.Constructor.prototype.hide - * - * ======================================================================== - */ - - -'use strict'; - - -if (!Tooltip) throw new Error('Popover requires tooltip.js') - - -/** - * Our tooltip class. - * @param {Element!} element - * @param {Object=} opt_config - * @constructor - * @extends {Tooltip} - */ -var Popover = function (element, opt_config) { - Tooltip.apply(this, arguments) -} -Bootstrap.inherits(Popover, Tooltip) - - -/** - * @const - * @type {string} - */ -Popover['VERSION'] = '4.0.0' - - -/** - * @const - * @type {Object} - */ -Popover['Defaults'] = $.extend({}, $.fn['tooltip']['Constructor']['Defaults'], { - 'placement': 'right', - 'trigger': 'click', - 'content': '', - 'template': '' -}) - - -/** - * @const - * @type {string} - * @private - */ -Popover._NAME = 'popover' - - -/** - * @const - * @type {string} - * @private - */ -Popover._DATA_KEY = 'bs.popover' - + * ======================================================================== */ -/** - * @const - * @enum {string} - * @private - */ -Popover._Event = { - HIDE : 'hide.bs.popover', - HIDDEN : 'hidden.bs.popover', - SHOW : 'show.bs.popover', - SHOWN : 'shown.bs.popover' -} ++function ($) { + 'use strict'; -/** - * @const - * @enum {string} - * @private - */ -Popover._ClassName = { - FADE : 'fade', - IN : 'in' -} + // POPOVER PUBLIC CLASS DEFINITION + // =============================== + var Popover = function (element, options) { + this.init('popover', element, options) + } -/** - * @const - * @enum {string} - * @private - */ -Popover._Selector = { - TITLE : '.popover-title', - CONTENT : '.popover-content', - ARROW : '.popover-arrow' -} - - -/** - * @const - * @type {Function} - * @private - */ -Popover._JQUERY_NO_CONFLICT = $.fn[Popover._NAME] - - -/** - * @param {Object|string=} opt_config - * @this {jQuery} - * @return {jQuery} - * @private - */ -Popover._jQueryInterface = function (opt_config) { - return this.each(function () { - var data = $(this).data(Popover._DATA_KEY) - var config = typeof opt_config === 'object' ? opt_config : null - - if (!data && opt_config === 'destroy') { - return - } + if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js') - if (!data) { - data = new Popover(this, config) - $(this).data(Popover._DATA_KEY, data) - } + Popover.VERSION = '3.3.4' - if (typeof opt_config === 'string') { - data[opt_config]() - } + Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, { + placement: 'right', + trigger: 'click', + content: '', + template: '' }) -} - - -/** - * @return {string} - * @protected - */ -Popover.prototype.getName = function () { - return Popover._NAME -} -/** - * @override - */ -Popover.prototype.getDataKey = function () { - return Popover._DATA_KEY -} + // NOTE: POPOVER EXTENDS tooltip.js + // ================================ + Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype) -/** - * @override - */ -Popover.prototype.getEventObject = function () { - return Popover._Event -} + Popover.prototype.constructor = Popover + Popover.prototype.getDefaults = function () { + return Popover.DEFAULTS + } -/** - * @override - */ -Popover.prototype.getArrowElement = function () { - return (this.arrow = this.arrow || $(this.getTipElement()).find(Popover._Selector.ARROW)[0]) -} + Popover.prototype.setContent = function () { + var $tip = this.tip() + var title = this.getTitle() + var content = this.getContent() + $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title) + $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events + this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text' + ](content) -/** - * @override - */ -Popover.prototype.setContent = function () { - var tip = this.getTipElement() - var title = this.getTitle() - var content = this._getContent() - var titleElement = $(tip).find(Popover._Selector.TITLE)[0] + $tip.removeClass('fade top bottom left right in') - if (titleElement) { - titleElement[this.config['html'] ? 'innerHTML' : 'innerText'] = title + // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do + // this manually by checking the contents. + if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide() } - // we use append for html objects to maintain js events - $(tip).find(Popover._Selector.CONTENT).children().detach().end()[ - this.config['html'] ? (typeof content == 'string' ? 'html' : 'append') : 'text' - ](content) - - $(tip) - .removeClass(Popover._ClassName.FADE) - .removeClass(Popover._ClassName.IN) - - for (var direction in Tooltip.Direction) { - $(tip).removeClass(Popover._NAME + '-' + Tooltip.Direction[direction]) + Popover.prototype.hasContent = function () { + return this.getTitle() || this.getContent() } -} - -/** - * @override - */ -Popover.prototype.isWithContent = function () { - return this.getTitle() || this._getContent() -} + Popover.prototype.getContent = function () { + var $e = this.$element + var o = this.options + return $e.attr('data-content') + || (typeof o.content == 'function' ? + o.content.call($e[0]) : + o.content) + } -/** - * @override - */ -Popover.prototype.getTipElement = function () { - return (this.tip = this.tip || $(this.config['template'])[0]) -} + Popover.prototype.arrow = function () { + return (this.$arrow = this.$arrow || this.tip().find('.arrow')) + } -/** - * @private - */ -Popover.prototype._getContent = function () { - return this.element.getAttribute('data-content') - || (typeof this.config['content'] == 'function' ? - this.config['content'].call(this.element) : - this.config['content']) -} + // POPOVER PLUGIN DEFINITION + // ========================= + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.popover') + var options = typeof option == 'object' && option + if (!data && /destroy|hide/.test(option)) return + if (!data) $this.data('bs.popover', (data = new Popover(this, options))) + if (typeof option == 'string') data[option]() + }) + } -/** - * ------------------------------------------------------------------------ - * jQuery Interface + noConflict implementaiton - * ------------------------------------------------------------------------ - */ + var old = $.fn.popover -/** - * @const - * @type {Function} - */ -$.fn[Popover._NAME] = Popover._jQueryInterface + $.fn.popover = Plugin + $.fn.popover.Constructor = Popover -/** - * @const - * @type {Function} - */ -$.fn[Popover._NAME]['Constructor'] = Popover + // POPOVER NO CONFLICT + // =================== + $.fn.popover.noConflict = function () { + $.fn.popover = old + return this + } -/** - * @const - * @type {Function} - */ -$.fn[Popover._NAME]['noConflict'] = function () { - $.fn[Popover._NAME] = Popover._JQUERY_NO_CONFLICT - return this -} +}(jQuery); diff --git a/js/scrollspy.js b/js/scrollspy.js index 150241b54..f860c1aba 100644 --- a/js/scrollspy.js +++ b/js/scrollspy.js @@ -1,346 +1,172 @@ -/** ======================================================================= - * Bootstrap: scrollspy.js v4.0.0 +/* ======================================================================== + * Bootstrap: scrollspy.js v3.3.4 * http://getbootstrap.com/javascript/#scrollspy * ======================================================================== * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== - * @fileoverview - Bootstrap's scrollspy plugin. - * - * Public Methods & Properties: - * - * + $.scrollspy - * + $.scrollspy.noConflict - * + $.scrollspy.Constructor - * + $.scrollspy.Constructor.VERSION - * + $.scrollspy.Constructor.Defaults - * + $.scrollspy.Constructor.Defaults.offset - * + $.scrollspy.Constructor.prototype.refresh - * - * ======================================================================== - */ - -'use strict'; - - -/** - * Our scrollspy class. - * @param {Element!} element - * @param {Object=} opt_config - * @constructor - */ -function ScrollSpy(element, opt_config) { - - /** @private {Element|Window} */ - this._scrollElement = element.tagName == 'BODY' ? window : element - - /** @private {Object} */ - this._config = $.extend({}, ScrollSpy['Defaults'], opt_config) - - /** @private {string} */ - this._selector = (this._config.target || '') + ' .nav li > a' - - /** @private {Array} */ - this._offsets = [] - - /** @private {Array} */ - this._targets = [] - - /** @private {Element} */ - this._activeTarget = null - - /** @private {number} */ - this._scrollHeight = 0 - - $(this._scrollElement).on('scroll.bs.scrollspy', this._process.bind(this)) - - this['refresh']() + * ======================================================================== */ - this._process() -} ++function ($) { + 'use strict'; -/** - * @const - * @type {string} - */ -ScrollSpy['VERSION'] = '4.0.0' + // SCROLLSPY CLASS DEFINITION + // ========================== + function ScrollSpy(element, options) { + this.$body = $(document.body) + this.$scrollElement = $(element).is(document.body) ? $(window) : $(element) + this.options = $.extend({}, ScrollSpy.DEFAULTS, options) + this.selector = (this.options.target || '') + ' .nav li > a' + this.offsets = [] + this.targets = [] + this.activeTarget = null + this.scrollHeight = 0 -/** - * @const - * @type {Object} - */ -ScrollSpy['Defaults'] = { - 'offset': 10 -} - - -/** - * @const - * @type {string} - * @private - */ -ScrollSpy._NAME = 'scrollspy' - - -/** - * @const - * @type {string} - * @private - */ -ScrollSpy._DATA_KEY = 'bs.scrollspy' - - -/** - * @const - * @type {Function} - * @private - */ -ScrollSpy._JQUERY_NO_CONFLICT = $.fn[ScrollSpy._NAME] - - -/** - * @const - * @enum {string} - * @private - */ -ScrollSpy._Event = { - ACTIVATE: 'activate.bs.scrollspy' -} - - -/** - * @const - * @enum {string} - * @private - */ -ScrollSpy._ClassName = { - DROPDOWN_MENU : 'dropdown-menu', - ACTIVE : 'active' -} - - -/** - * @const - * @enum {string} - * @private - */ -ScrollSpy._Selector = { - DATA_SPY : '[data-spy="scroll"]', - ACTIVE : '.active', - LI_DROPDOWN : 'li.dropdown', - LI : 'li' -} - - -/** - * @param {Object=} opt_config - * @this {jQuery} - * @return {jQuery} - * @private - */ -ScrollSpy._jQueryInterface = function (opt_config) { - return this.each(function () { - var data = $(this).data(ScrollSpy._DATA_KEY) - var config = typeof opt_config === 'object' && opt_config || null - - if (!data) { - data = new ScrollSpy(this, config) - $(this).data(ScrollSpy._DATA_KEY, data) - } - - if (typeof opt_config === 'string') { - data[opt_config]() - } - }) -} - + this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this)) + this.refresh() + this.process() + } -/** - * Refresh the scrollspy target cache - */ -ScrollSpy.prototype['refresh'] = function () { - var offsetMethod = 'offset' - var offsetBase = 0 + ScrollSpy.VERSION = '3.3.4' - if (this._scrollElement !== this._scrollElement.window) { - offsetMethod = 'position' - offsetBase = this._getScrollTop() + ScrollSpy.DEFAULTS = { + offset: 10 } - this._offsets = [] - this._targets = [] - - this._scrollHeight = this._getScrollHeight() + ScrollSpy.prototype.getScrollHeight = function () { + return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight) + } - var targets = /** @type {Array.} */ ($.makeArray($(this._selector))) + ScrollSpy.prototype.refresh = function () { + var that = this + var offsetMethod = 'offset' + var offsetBase = 0 - targets - .map(function (element, index) { - var target - var targetSelector = Bootstrap.getSelectorFromElement(element) + this.offsets = [] + this.targets = [] + this.scrollHeight = this.getScrollHeight() - if (targetSelector) { - target = $(targetSelector)[0] - } + if (!$.isWindow(this.$scrollElement[0])) { + offsetMethod = 'position' + offsetBase = this.$scrollElement.scrollTop() + } - if (target && (target.offsetWidth || target.offsetHeight)) { - // todo (fat): remove sketch reliance on jQuery position/offset - return [$(target)[offsetMethod]().top + offsetBase, targetSelector] - } - }) - .filter(function (item) { return item }) - .sort(function (a, b) { return a[0] - b[0] }) - .forEach(function (item, index) { - this._offsets.push(item[0]) - this._targets.push(item[1]) - }.bind(this)) -} - - -/** - * @private - */ -ScrollSpy.prototype._getScrollTop = function () { - return this._scrollElement === window ? - this._scrollElement.scrollY : this._scrollElement.scrollTop -} - - -/** - * @private - */ -ScrollSpy.prototype._getScrollHeight = function () { - return this._scrollElement.scrollHeight - || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight) -} - - -/** - * @private - */ -ScrollSpy.prototype._process = function () { - var scrollTop = this._getScrollTop() + this._config.offset - var scrollHeight = this._getScrollHeight() - var maxScroll = this._config.offset + scrollHeight - this._scrollElement.offsetHeight - - if (this._scrollHeight != scrollHeight) { - this['refresh']() + this.$body + .find(this.selector) + .map(function () { + var $el = $(this) + var href = $el.data('target') || $el.attr('href') + var $href = /^#./.test(href) && $(href) + + return ($href + && $href.length + && $href.is(':visible') + && [[$href[offsetMethod]().top + offsetBase, href]]) || null + }) + .sort(function (a, b) { return a[0] - b[0] }) + .each(function () { + that.offsets.push(this[0]) + that.targets.push(this[1]) + }) } - if (scrollTop >= maxScroll) { - var target = this._targets[this._targets.length - 1] - - if (this._activeTarget != target) { - this._activate(target) + ScrollSpy.prototype.process = function () { + var scrollTop = this.$scrollElement.scrollTop() + this.options.offset + var scrollHeight = this.getScrollHeight() + var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height() + var offsets = this.offsets + var targets = this.targets + var activeTarget = this.activeTarget + var i + + if (this.scrollHeight != scrollHeight) { + this.refresh() } - } - if (this._activeTarget && scrollTop < this._offsets[0]) { - this._activeTarget = null - this._clear() - return - } + if (scrollTop >= maxScroll) { + return activeTarget != (i = targets[targets.length - 1]) && this.activate(i) + } - for (var i = this._offsets.length; i--;) { - var isActiveTarget = this._activeTarget != this._targets[i] - && scrollTop >= this._offsets[i] - && (!this._offsets[i + 1] || scrollTop < this._offsets[i + 1]) + if (activeTarget && scrollTop < offsets[0]) { + this.activeTarget = null + return this.clear() + } - if (isActiveTarget) { - this._activate(this._targets[i]) + for (i = offsets.length; i--;) { + activeTarget != targets[i] + && scrollTop >= offsets[i] + && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1]) + && this.activate(targets[i]) } } -} - -/** - * @param {Element} target - * @private - */ -ScrollSpy.prototype._activate = function (target) { - this._activeTarget = target + ScrollSpy.prototype.activate = function (target) { + this.activeTarget = target - this._clear() + this.clear() - var selector = this._selector - + '[data-target="' + target + '"],' - + this._selector + '[href="' + target + '"]' + var selector = this.selector + + '[data-target="' + target + '"],' + + this.selector + '[href="' + target + '"]' - // todo (fat): this seems horribly wrong… getting all raw li elements up the tree ,_, - var parentListItems = $(selector).parents(ScrollSpy._Selector.LI) + var active = $(selector) + .parents('li') + .addClass('active') - for (var i = parentListItems.length; i--;) { - $(parentListItems[i]).addClass(ScrollSpy._ClassName.ACTIVE) + if (active.parent('.dropdown-menu').length) { + active = active + .closest('li.dropdown') + .addClass('active') + } - var itemParent = parentListItems[i].parentNode + active.trigger('activate.bs.scrollspy') + } - if (itemParent && $(itemParent).hasClass(ScrollSpy._ClassName.DROPDOWN_MENU)) { - var closestDropdown = $(itemParent).closest(ScrollSpy._Selector.LI_DROPDOWN)[0] - $(closestDropdown).addClass(ScrollSpy._ClassName.ACTIVE) - } + ScrollSpy.prototype.clear = function () { + $(this.selector) + .parentsUntil(this.options.target, '.active') + .removeClass('active') } - $(this._scrollElement).trigger(ScrollSpy._Event.ACTIVATE, { - relatedTarget: target - }) -} + // SCROLLSPY PLUGIN DEFINITION + // =========================== -/** - * @private - */ -ScrollSpy.prototype._clear = function () { - var activeParents = $(this._selector).parentsUntil(this._config.target, ScrollSpy._Selector.ACTIVE) + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.scrollspy') + var options = typeof option == 'object' && option - for (var i = activeParents.length; i--;) { - $(activeParents[i]).removeClass(ScrollSpy._ClassName.ACTIVE) + if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options))) + if (typeof option == 'string') data[option]() + }) } -} + var old = $.fn.scrollspy -/** - * ------------------------------------------------------------------------ - * jQuery Interface + noConflict implementaiton - * ------------------------------------------------------------------------ - */ + $.fn.scrollspy = Plugin + $.fn.scrollspy.Constructor = ScrollSpy -/** - * @const - * @type {Function} - */ -$.fn[ScrollSpy._NAME] = ScrollSpy._jQueryInterface + // SCROLLSPY NO CONFLICT + // ===================== -/** - * @const - * @type {Function} - */ -$.fn[ScrollSpy._NAME]['Constructor'] = ScrollSpy - - -/** - * @const - * @type {Function} - */ -$.fn[ScrollSpy._NAME]['noConflict'] = function () { - $.fn[ScrollSpy._NAME] = ScrollSpy._JQUERY_NO_CONFLICT - return this -} + $.fn.scrollspy.noConflict = function () { + $.fn.scrollspy = old + return this + } -/** - * ------------------------------------------------------------------------ - * Data Api implementation - * ------------------------------------------------------------------------ - */ + // SCROLLSPY DATA-API + // ================== -$(window).on('load.bs.scrollspy.data-api', function () { - var scrollSpys = /** @type {Array.} */ ($.makeArray($(ScrollSpy._Selector.DATA_SPY))) + $(window).on('load.bs.scrollspy.data-api', function () { + $('[data-spy="scroll"]').each(function () { + var $spy = $(this) + Plugin.call($spy, $spy.data()) + }) + }) - for (var i = scrollSpys.length; i--;) { - var $spy = $(scrollSpys[i]) - ScrollSpy._jQueryInterface.call($spy, /** @type {Object|null} */ ($spy.data())) - } -}) +}(jQuery); diff --git a/js/tab.js b/js/tab.js index 07897294a..416189e3d 100644 --- a/js/tab.js +++ b/js/tab.js @@ -1,324 +1,155 @@ -/** ======================================================================= - * Bootstrap: tab.js v4.0.0 +/* ======================================================================== + * Bootstrap: tab.js v3.3.4 * http://getbootstrap.com/javascript/#tabs * ======================================================================== * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * ======================================================================== - * @fileoverview - Bootstrap's tab plugin. Tab O_O - * - * Public Methods & Properties: - * - * + $.tab - * + $.tab.noConflict - * + $.tab.Constructor - * + $.tab.Constructor.VERSION - * + $.tab.Constructor.prototype.show - * - * ======================================================================== - */ - - -'use strict'; - -/** - * Our Tab class. - * @param {Element!} element - * @constructor - */ -var Tab = function (element) { - - /** @type {Element} */ - this._element = element - -} - - -/** - * @const - * @type {string} - */ -Tab['VERSION'] = '4.0.0' - - -/** - * @const - * @type {string} - * @private - */ -Tab._NAME = 'tab' - - -/** - * @const - * @type {string} - * @private - */ -Tab._DATA_KEY = 'bs.tab' - - -/** - * @const - * @type {number} - * @private - */ -Tab._TRANSITION_DURATION = 150 - - -/** - * @const - * @enum {string} - * @private - */ -Tab._Event = { - HIDE : 'hide.bs.tab', - HIDDEN : 'hidden.bs.tab', - SHOW : 'show.bs.tab', - SHOWN : 'shown.bs.tab' -} - - -/** - * @const - * @enum {string} - * @private - */ -Tab._ClassName = { - DROPDOWN_MENU : 'dropdown-menu', - ACTIVE : 'active', - FADE : 'fade', - IN : 'in' -} - - -/** - * @const - * @enum {string} - * @private - */ -Tab._Selector = { - A : 'a', - LI : 'li', - LI_DROPDOWN : 'li.dropdown', - UL : 'ul:not(.dropdown-menu)', - FADE_CHILD : ':scope > .fade', - ACTIVE : '.active', - ACTIVE_CHILD : ':scope > .active', - DATA_TOGGLE : '[data-toggle="tab"], [data-toggle="pill"]', - DROPDOWN_ACTIVE_CHILD : ':scope > .dropdown-menu > .active' -} - - -/** - * @param {Object|string=} opt_config - * @this {jQuery} - * @return {jQuery} - * @private - */ -Tab._jQueryInterface = function (opt_config) { - return this.each(function () { - var $this = $(this) - var data = $this.data(Tab._DATA_KEY) - - if (!data) { - data = data = new Tab(this) - $this.data(Tab._DATA_KEY, data) - } + * ======================================================================== */ - if (typeof opt_config === 'string') { - data[opt_config]() - } - }) -} - - -/** - * Show the tab - */ -Tab.prototype['show'] = function () { - if ( this._element.parentNode - && this._element.parentNode.nodeType == Node.ELEMENT_NODE - && $(this._element).parent().hasClass(Tab._ClassName.ACTIVE)) { - return - } - var ulElement = $(this._element).closest(Tab._Selector.UL)[0] - var selector = Bootstrap.getSelectorFromElement(this._element) ++function ($) { + 'use strict'; - if (ulElement) { - var previous = /** @type {Array.} */ ($.makeArray($(ulElement).find(Tab._Selector.ACTIVE))) - previous = previous[previous.length - 1] + // TAB CLASS DEFINITION + // ==================== - if (previous) { - previous = $(previous).find('a')[0] - } + var Tab = function (element) { + // jscs:disable requireDollarBeforejQueryAssignment + this.element = $(element) + // jscs:enable requireDollarBeforejQueryAssignment } - var hideEvent = $.Event(Tab._Event.HIDE, { - relatedTarget: this._element - }) - - var showEvent = $.Event(Tab._Event.SHOW, { - relatedTarget: previous - }) + Tab.VERSION = '3.3.4' - if (previous) { - $(previous).trigger(hideEvent) - } - - $(this._element).trigger(showEvent) + Tab.TRANSITION_DURATION = 150 - if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return + Tab.prototype.show = function () { + var $this = this.element + var $ul = $this.closest('ul:not(.dropdown-menu)') + var selector = $this.data('target') - if (selector) { - var target = $(selector)[0] - } + if (!selector) { + selector = $this.attr('href') + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 + } - this._activate($(this._element).closest(Tab._Selector.LI)[0], ulElement) + if ($this.parent('li').hasClass('active')) return - var complete = function () { - var hiddenEvent = $.Event(Tab._Event.HIDDEN, { - relatedTarget: this._element + var $previous = $ul.find('.active:last a') + var hideEvent = $.Event('hide.bs.tab', { + relatedTarget: $this[0] }) - - var shownEvent = $.Event(Tab._Event.SHOWN, { - relatedTarget: previous + var showEvent = $.Event('show.bs.tab', { + relatedTarget: $previous[0] }) - $(previous).trigger(hiddenEvent) - $(this._element).trigger(shownEvent) - }.bind(this) + $previous.trigger(hideEvent) + $this.trigger(showEvent) - if (target) { - this._activate(target, /** @type {Element} */ (target.parentNode), complete) - } else { - complete() - } -} - - -/** - * @param {Element} element - * @param {Element} container - * @param {Function=} opt_callback - * @private - */ -Tab.prototype._activate = function (element, container, opt_callback) { - var active = $(container).find(Tab._Selector.ACTIVE_CHILD)[0] - var isTransitioning = opt_callback - && Bootstrap.transition - && ((active && $(active).hasClass(Tab._ClassName.FADE)) - || !!$(container).find(Tab._Selector.FADE_CHILD)[0]) - - var complete = this._transitionComplete.bind(this, element, active, isTransitioning, opt_callback) - - if (active && isTransitioning) { - $(active) - .one(Bootstrap.TRANSITION_END, complete) - .emulateTransitionEnd(Tab._TRANSITION_DURATION) - - } else { - complete() - } + if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return - if (active) { - $(active).removeClass(Tab._ClassName.IN) + var $target = $(selector) + + this.activate($this.closest('li'), $ul) + this.activate($target, $target.parent(), function () { + $previous.trigger({ + type: 'hidden.bs.tab', + relatedTarget: $this[0] + }) + $this.trigger({ + type: 'shown.bs.tab', + relatedTarget: $previous[0] + }) + }) } -} - - -/** - * @param {Element} element - * @param {Element} active - * @param {boolean} isTransitioning - * @param {Function=} opt_callback - * @private - */ -Tab.prototype._transitionComplete = function (element, active, isTransitioning, opt_callback) { - if (active) { - $(active).removeClass(Tab._ClassName.ACTIVE) - - var dropdownChild = $(active).find(Tab._Selector.DROPDOWN_ACTIVE_CHILD)[0] - if (dropdownChild) { - $(dropdownChild).removeClass(Tab._ClassName.ACTIVE) - } - var activeToggle = $(active).find(Tab._Selector.DATA_TOGGLE)[0] - if (activeToggle) { - activeToggle.setAttribute('aria-expanded', false) + Tab.prototype.activate = function (element, container, callback) { + var $active = container.find('> .active') + var transition = callback + && $.support.transition + && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length) + + function next() { + $active + .removeClass('active') + .find('> .dropdown-menu > .active') + .removeClass('active') + .end() + .find('[data-toggle="tab"]') + .attr('aria-expanded', false) + + element + .addClass('active') + .find('[data-toggle="tab"]') + .attr('aria-expanded', true) + + if (transition) { + element[0].offsetWidth // reflow for transition + element.addClass('in') + } else { + element.removeClass('fade') + } + + if (element.parent('.dropdown-menu').length) { + element + .closest('li.dropdown') + .addClass('active') + .end() + .find('[data-toggle="tab"]') + .attr('aria-expanded', true) + } + + callback && callback() } - } - $(element).addClass(Tab._ClassName.ACTIVE) + $active.length && transition ? + $active + .one('bsTransitionEnd', next) + .emulateTransitionEnd(Tab.TRANSITION_DURATION) : + next() - var elementToggle = $(element).find(Tab._Selector.DATA_TOGGLE)[0] - if (elementToggle) { - elementToggle.setAttribute('aria-expanded', true) + $active.removeClass('in') } - if (isTransitioning) { - Bootstrap.reflow(element) - $(element).addClass(Tab._ClassName.IN) - } else { - $(element).removeClass(Tab._ClassName.FADE) - } - if (element.parentNode && $(element.parentNode).hasClass(Tab._ClassName.DROPDOWN_MENU)) { - var dropdownElement = $(element).closest(Tab._Selector.LI_DROPDOWN)[0] - if (dropdownElement) { - $(dropdownElement).addClass(Tab._ClassName.ACTIVE) - } + // TAB PLUGIN DEFINITION + // ===================== - elementToggle = $(element).find(Tab._Selector.DATA_TOGGLE)[0] - if (elementToggle) { - elementToggle.setAttribute('aria-expanded', true) - } - } + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.tab') - if (opt_callback) { - opt_callback() + if (!data) $this.data('bs.tab', (data = new Tab(this))) + if (typeof option == 'string') data[option]() + }) } -} - -/** - * ------------------------------------------------------------------------ - * jQuery Interface + noConflict implementaiton - * ------------------------------------------------------------------------ - */ + var old = $.fn.tab -/** - * @const - * @type {Function} - */ -$.fn[Tab._NAME] = Tab._jQueryInterface + $.fn.tab = Plugin + $.fn.tab.Constructor = Tab -/** - * @const - * @type {Function} - */ -$.fn[Tab._NAME]['Constructor'] = Tab + // TAB NO CONFLICT + // =============== - -/** - * @const - * @type {Function} - */ -$.fn[Tab._NAME]['noConflict'] = function () { - $.fn[Tab._NAME] = Tab._JQUERY_NO_CONFLICT - return this -} + $.fn.tab.noConflict = function () { + $.fn.tab = old + return this + } + // TAB DATA-API + // ============ -// TAB DATA-API -// ============ + var clickHandler = function (e) { + e.preventDefault() + Plugin.call($(this), 'show') + } -var clickHandler = function (e) { - e.preventDefault() - Tab._jQueryInterface.call($(this), 'show') -} + $(document) + .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler) + .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler) -$(document) - .on('click.bs.tab.data-api', Tab._Selector.DATA_TOGGLE, clickHandler) +}(jQuery); diff --git a/js/tests/closure.html b/js/tests/closure.html deleted file mode 100644 index 82c65f62b..000000000 --- a/js/tests/closure.html +++ /dev/null @@ -1,83 +0,0 @@ - - - - - Bootstrap Plugin Test Suite - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
- - diff --git a/js/tests/index.html b/js/tests/index.html index d1ec0a7f4..fab2ebc16 100644 --- a/js/tests/index.html +++ b/js/tests/index.html @@ -130,7 +130,7 @@ - + @@ -141,6 +141,7 @@ + @@ -153,6 +154,7 @@ + diff --git a/js/tests/unit/affix.js b/js/tests/unit/affix.js new file mode 100644 index 000000000..3a6918f86 --- /dev/null +++ b/js/tests/unit/affix.js @@ -0,0 +1,107 @@ +$(function () { + 'use strict'; + + QUnit.module('affix plugin') + + QUnit.test('should be defined on jquery object', function (assert) { + assert.expect(1) + assert.ok($(document.body).affix, 'affix method is defined') + }) + + QUnit.module('affix', { + beforeEach: function () { + // Run all tests in noConflict mode -- it's the only way to ensure that the plugin works in noConflict mode + $.fn.bootstrapAffix = $.fn.affix.noConflict() + }, + afterEach: function () { + $.fn.affix = $.fn.bootstrapAffix + delete $.fn.bootstrapAffix + } + }) + + QUnit.test('should provide no conflict', function (assert) { + assert.expect(1) + assert.strictEqual($.fn.affix, undefined, 'affix was set back to undefined (org value)') + }) + + QUnit.test('should return jquery collection containing the element', function (assert) { + assert.expect(2) + var $el = $('
') + var $affix = $el.bootstrapAffix() + assert.ok($affix instanceof $, 'returns jquery collection') + assert.strictEqual($affix[0], $el[0], 'collection contains element') + }) + + QUnit.test('should exit early if element is not visible', function (assert) { + assert.expect(1) + var $affix = $('
').bootstrapAffix() + $affix.data('bs.affix').checkPosition() + assert.ok(!$affix.hasClass('affix'), 'affix class was not added') + }) + + QUnit.test('should trigger affixed event after affix', function (assert) { + assert.expect(2) + var done = assert.async() + + var templateHTML = '
' + + '
    ' + + '
  • Please affix
  • ' + + '
  • And unaffix
  • ' + + '
' + + '
' + + '
' + $(templateHTML).appendTo(document.body) + + $('#affixTarget').bootstrapAffix({ + offset: $('#affixTarget ul').position() + }) + + $('#affixTarget') + .on('affix.bs.affix', function () { + assert.ok(true, 'affix event fired') + }).on('affixed.bs.affix', function () { + assert.ok(true, 'affixed event fired') + $('#affixTarget, #affixAfter').remove() + done() + }) + + setTimeout(function () { + window.scrollTo(0, document.body.scrollHeight) + + setTimeout(function () { + window.scroll(0, 0) + }, 16) // for testing in a browser + }, 0) + }) + + QUnit.test('should affix-top when scrolling up to offset when parent has padding', function (assert) { + assert.expect(1) + var done = assert.async() + + var templateHTML = '
' + + '
' + + '

Testing affix-top class is added

' + + '
' + + '
' + + '
' + $(templateHTML).appendTo(document.body) + + $('#affixTopTarget') + .bootstrapAffix({ + offset: { top: 120, bottom: 0 } + }) + .on('affixed-top.bs.affix', function () { + assert.ok($('#affixTopTarget').hasClass('affix-top'), 'affix-top class applied') + $('#padding-offset').remove() + done() + }) + + setTimeout(function () { + window.scrollTo(0, document.body.scrollHeight) + + setTimeout(function () { + window.scroll(0, 119) + }, 250) + }, 250) + }) +}) diff --git a/js/tests/unit/button.js b/js/tests/unit/button.js index 08b071d65..691796c42 100644 --- a/js/tests/unit/button.js +++ b/js/tests/unit/button.js @@ -1,83 +1,137 @@ $(function () { 'use strict'; - module('button plugin') + QUnit.module('button plugin') - test('should be defined on jquery object', function () { - ok($(document.body).button, 'button method is defined') + QUnit.test('should be defined on jquery object', function (assert) { + assert.expect(1) + assert.ok($(document.body).button, 'button method is defined') }) - module('button', { - setup: function () { + QUnit.module('button', { + beforeEach: function () { // Run all tests in noConflict mode -- it's the only way to ensure that the plugin works in noConflict mode $.fn.bootstrapButton = $.fn.button.noConflict() }, - teardown: function () { + afterEach: function () { $.fn.button = $.fn.bootstrapButton delete $.fn.bootstrapButton } }) - test('should provide no conflict', function () { - strictEqual($.fn.button, undefined, 'button was set back to undefined (org value)') + QUnit.test('should provide no conflict', function (assert) { + assert.expect(1) + assert.strictEqual($.fn.button, undefined, 'button was set back to undefined (org value)') }) - test('should return jquery collection containing the element', function () { + QUnit.test('should return jquery collection containing the element', function (assert) { + assert.expect(2) var $el = $('
') var $button = $el.bootstrapButton() - ok($button instanceof $, 'returns jquery collection') - strictEqual($button[0], $el[0], 'collection contains element') + assert.ok($button instanceof $, 'returns jquery collection') + assert.strictEqual($button[0], $el[0], 'collection contains element') }) - test('should toggle active', function () { + QUnit.test('should return set state to loading', function (assert) { + assert.expect(4) + var $btn = $('') + assert.strictEqual($btn.html(), 'mdo', 'btn text equals mdo') + $btn.bootstrapButton('loading') + var done = assert.async() + setTimeout(function () { + assert.strictEqual($btn.html(), 'fat', 'btn text equals fat') + assert.ok($btn[0].hasAttribute('disabled'), 'btn is disabled') + assert.ok($btn.hasClass('disabled'), 'btn has disabled class') + done() + }, 0) + }) + + QUnit.test('should return reset state', function (assert) { + assert.expect(7) + var $btn = $('') + assert.strictEqual($btn.html(), 'mdo', 'btn text equals mdo') + $btn.bootstrapButton('loading') + var doneOne = assert.async() + setTimeout(function () { + assert.strictEqual($btn.html(), 'fat', 'btn text equals fat') + assert.ok($btn[0].hasAttribute('disabled'), 'btn is disabled') + assert.ok($btn.hasClass('disabled'), 'btn has disabled class') + doneOne() + var doneTwo = assert.async() + $btn.bootstrapButton('reset') + setTimeout(function () { + assert.strictEqual($btn.html(), 'mdo', 'btn text equals mdo') + assert.ok(!$btn[0].hasAttribute('disabled'), 'btn is not disabled') + assert.ok(!$btn.hasClass('disabled'), 'btn does not have disabled class') + doneTwo() + }, 0) + }, 0) + }) + + QUnit.test('should work with an empty string as reset state', function (assert) { + assert.expect(7) + var $btn = $('') - ok(!$btn.hasClass('active'), 'btn does not have active class') + assert.ok(!$btn.hasClass('active'), 'btn does not have active class') $btn.bootstrapButton('toggle') - ok($btn.hasClass('active'), 'btn has class active') + assert.ok($btn.hasClass('active'), 'btn has class active') }) - test('should toggle active when btn children are clicked', function () { + QUnit.test('should toggle active when btn children are clicked', function (assert) { + assert.expect(2) var $btn = $('') var $inner = $('') $btn .append($inner) .appendTo('#qunit-fixture') - ok(!$btn.hasClass('active'), 'btn does not have active class') - $inner.click() - ok($btn.hasClass('active'), 'btn has class active') + assert.ok(!$btn.hasClass('active'), 'btn does not have active class') + $inner.trigger('click') + assert.ok($btn.hasClass('active'), 'btn has class active') }) - test('should toggle aria-pressed', function () { + QUnit.test('should toggle aria-pressed', function (assert) { + assert.expect(2) var $btn = $('') - equal($btn.attr('aria-pressed'), 'false', 'btn aria-pressed state is false') + assert.strictEqual($btn.attr('aria-pressed'), 'false', 'btn aria-pressed state is false') $btn.bootstrapButton('toggle') - equal($btn.attr('aria-pressed'), 'true', 'btn aria-pressed state is true') + assert.strictEqual($btn.attr('aria-pressed'), 'true', 'btn aria-pressed state is true') }) - test('should toggle aria-pressed when btn children are clicked', function () { + QUnit.test('should toggle aria-pressed when btn children are clicked', function (assert) { + assert.expect(2) var $btn = $('') var $inner = $('') $btn .append($inner) .appendTo('#qunit-fixture') - equal($btn.attr('aria-pressed'), 'false', 'btn aria-pressed state is false') - $inner.click() - equal($btn.attr('aria-pressed'), 'true', 'btn aria-pressed state is true') + assert.strictEqual($btn.attr('aria-pressed'), 'false', 'btn aria-pressed state is false') + $inner.trigger('click') + assert.strictEqual($btn.attr('aria-pressed'), 'true', 'btn aria-pressed state is true') }) - test('should toggle active when btn children are clicked within btn-group', function () { - var $btngroup = $('
') - var $btn = $('') - var $inner = $('') - $btngroup - .append($btn.append($inner)) - .appendTo('#qunit-fixture') - ok(!$btn.hasClass('active'), 'btn does not have active class') - $inner.click() - ok($btn.hasClass('active'), 'btn has class active') - }) - - test('should check for closest matching toggle', function () { + QUnit.test('should check for closest matching toggle', function (assert) { + assert.expect(12) var groupHTML = '
' + '