0
0
mirror of https://github.com/twbs/bootstrap.git synced 2024-12-12 00:08:59 +01:00

Merge pull request #57 from twbs/fat-closure

Bootstrap onto closure v2
This commit is contained in:
F A T 2015-02-11 11:36:16 -08:00
commit f483640378
38 changed files with 10739 additions and 4110 deletions

View File

@ -108,33 +108,79 @@ module.exports = function (grunt) {
}, },
bootstrap: { bootstrap: {
src: [ src: [
'js/hover.js', 'js/util.js',
mq4HoverShim.featureDetector.umdGlobal,
'js/transition.js',
'js/alert.js', 'js/alert.js',
'js/button.js', 'js/button.js',
'js/carousel.js', 'js/carousel.js',
'js/collapse.js', 'js/collapse.js',
'js/dropdown.js', 'js/dropdown.js',
'js/modal.js', 'js/modal.js',
'js/scrollspy.js',
'js/tooltip.js', 'js/tooltip.js',
'js/popover.js', 'js/popover.js',
'js/scrollspy.js', 'js/tab.js'
'js/tab.js',
'js/affix.js'
], ],
dest: 'dist/js/<%= pkg.name %>.js' dest: 'dist/js/<%= pkg.name %>.js'
} }
}, },
closureCompiler: {
options: {
compilerFile: require('superstartup-closure-compiler').getPath(),
checkModified: false,
compilerOpts: {
// jscomp_warning: 'reportUnknownTypes', someday - maybe we will get to 100% typed, this helps track those down
compilation_level: 'ADVANCED_OPTIMIZATIONS',
warning_level: 'verbose',
summary_detail_level: 3,
output_wrapper:
'"<%= banner %><%= jqueryCheck %><%= jqueryVersionCheck %>'
+ '(function($){%output%})(jQuery);"',
externs: 'js/externs/*.js'
},
execOpts: {
maxBuffer: 999999 * 1024
},
// [OPTIONAL] Java VM optimization options
// see https://code.google.com/p/closure-compiler/wiki/FAQ#What_are_the_recommended_Java_VM_command-line_options?
// Setting one of these to 'true' is strongly recommended,
// and can reduce compile times by 50-80% depending on compilation size
// and hardware.
// On server-class hardware, such as with Github's Travis hook,
// TieredCompilation should be used; on standard developer hardware,
// d32 may be better. Set as appropriate for your environment.
// Default for both is 'false'; do not set both to 'true'.
d32: false, // will use 'java -client -d32 -jar compiler.jar'
TieredCompilation: false // will use 'java -server -XX:+TieredCompilation -jar compiler.jar'
},
targetName: {
src: [
'js/util.js',
'js/alert.js',
'js/button.js',
'js/carousel.js',
'js/collapse.js',
'js/dropdown.js',
'js/modal.js',
'js/scrollspy.js',
'js/tooltip.js',
'js/popover.js',
'js/tab.js'
],
dest: 'dist/js/<%= pkg.name %>.min.js'
}
},
uglify: { uglify: {
options: { options: {
preserveComments: 'some' preserveComments: 'some'
}, },
core: {
src: '<%= concat.bootstrap.dest %>',
dest: 'dist/js/<%= pkg.name %>.min.js'
},
docsJs: { docsJs: {
src: configBridge.paths.docsJs, src: configBridge.paths.docsJs,
dest: 'docs/assets/js/docs.min.js' dest: 'docs/assets/js/docs.min.js'
@ -388,7 +434,7 @@ module.exports = function (grunt) {
grunt.registerTask('test-js', ['jshint:core', 'jshint:test', 'jshint:grunt', 'jscs:core', 'jscs:test', 'jscs:grunt', 'qunit']); grunt.registerTask('test-js', ['jshint:core', 'jshint:test', 'jshint:grunt', 'jscs:core', 'jscs:test', 'jscs:grunt', 'qunit']);
// JS distribution task. // JS distribution task.
grunt.registerTask('dist-js', ['concat', 'uglify:core', 'commonjs']); grunt.registerTask('dist-js', ['concat', 'closureCompiler', 'commonjs']);
grunt.registerTask('test-scss', ['scsslint:scss']); grunt.registerTask('test-scss', ['scsslint:scss']);

5903
dist/js/bootstrap.js vendored
View File

@ -15,1590 +15,3750 @@ if (typeof jQuery === 'undefined') {
} }
}(jQuery); }(jQuery);
/* ======================================================================== /** =======================================================================
* Bootstrap: transition.js v3.3.2 * Bootstrap: util.js v4.0.0
* http://getbootstrap.com/javascript/#transitions
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
// ============================================================
function transitionEnd() {
var el = document.createElement('bootstrap')
var transEndEventNames = {
WebkitTransition : 'webkitTransitionEnd',
MozTransition : 'transitionend',
OTransition : 'oTransitionEnd otransitionend',
transition : 'transitionend'
}
for (var name in transEndEventNames) {
if (el.style[name] !== undefined) {
return { end: transEndEventNames[name] }
}
}
return false // explicit for ie8 ( ._.)
}
// http://blog.alexmaccaw.com/css-transitions
$.fn.emulateTransitionEnd = function (duration) {
var called = false
var $el = this
$(this).one('bsTransitionEnd', function () { called = true })
var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
setTimeout(callback, duration)
return this
}
$(function () {
$.support.transition = transitionEnd()
if (!$.support.transition) return
$.event.special.bsTransitionEnd = {
bindType: $.support.transition.end,
delegateType: $.support.transition.end,
handle: function (e) {
if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
}
}
})
}(jQuery);
/* ========================================================================
* Bootstrap: alert.js v3.3.2
* http://getbootstrap.com/javascript/#alerts * http://getbootstrap.com/javascript/#alerts
* ======================================================================== * ========================================================================
* Copyright 2011-2015 Twitter, Inc. * Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */ * ========================================================================
* @fileoverview - Bootstrap's private util helper. Adds private util
* helpers for things like accesibility and transitions. These methods are
* shared across all bootstrap plugins.
* ========================================================================
*/
+function ($) {
'use strict'; 'use strict';
// ALERT CLASS DEFINITION
// ======================
var dismiss = '[data-dismiss="alert"]' /**
var Alert = function (el) { * @type {Object}
$(el).on('click', dismiss, this.close) */
var Bootstrap = {}
/**
* @const
* @type {string}
*/
Bootstrap.TRANSITION_END = 'bsTransitionEnd'
/**
* @const
* @type {Object}
*/
Bootstrap.TransitionEndEvent = {
'WebkitTransition' : 'webkitTransitionEnd',
'MozTransition' : 'transitionend',
'OTransition' : 'oTransitionEnd otransitionend',
'transition' : 'transitionend'
} }
Alert.VERSION = '3.3.2'
Alert.TRANSITION_DURATION = 150 /**
* @param {Function} childConstructor
* @param {Function} parentConstructor
*/
Bootstrap.inherits = function(childConstructor, parentConstructor) {
/** @constructor */
function tempConstructor() {}
tempConstructor.prototype = parentConstructor.prototype
childConstructor.prototype = new tempConstructor()
/** @override */
childConstructor.prototype.constructor = childConstructor
}
Alert.prototype.close = function (e) {
var $this = $(this) /**
var selector = $this.attr('data-target') * @param {Element} element
* @return {string|null}
*/
Bootstrap.getSelectorFromElement = function (element) {
var selector = element.getAttribute('data-target')
if (!selector) { if (!selector) {
selector = $this.attr('href') selector = element.getAttribute('href') || ''
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 selector = /^#[a-z]/i.test(selector) ? selector : null
} }
var $parent = $(selector) return selector
if (e) e.preventDefault()
if (!$parent.length) {
$parent = $this.closest('.alert')
}
$parent.trigger(e = $.Event('close.bs.alert'))
if (e.isDefaultPrevented()) return
$parent.removeClass('in')
function removeElement() {
// detach from parent, fire event then clean up data
$parent.detach().trigger('closed.bs.alert').remove()
}
$.support.transition && $parent.hasClass('fade') ?
$parent
.one('bsTransitionEnd', removeElement)
.emulateTransitionEnd(Alert.TRANSITION_DURATION) :
removeElement()
} }
// ALERT PLUGIN DEFINITION /**
// ======================= * @param {string} prefix
* @return {string}
*/
Bootstrap.getUID = function (prefix) {
do prefix += ~~(Math.random() * 1000000)
while (document.getElementById(prefix))
return prefix
}
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.alert')
if (!data) $this.data('bs.alert', (data = new Alert(this))) /**
if (typeof option == 'string') data[option].call($this) * @return {Object}
*/
Bootstrap.getSpecialTransitionEndEvent = function () {
return {
bindType: Bootstrap.transition.end,
delegateType: Bootstrap.transition.end,
handle: /** @param {jQuery.Event} event */ (function (event) {
if ($(event.target).is(this)) {
return event.handleObj.handler.apply(this, arguments)
}
}) })
} }
}
var old = $.fn.alert
$.fn.alert = Plugin
$.fn.alert.Constructor = Alert
// ALERT NO CONFLICT /**
// ================= * @param {Element} element
*/
Bootstrap.reflow = function (element) {
new Function('bs',"return bs")(element.offsetHeight)
}
/**
* @return {Object|boolean}
*/
Bootstrap.transitionEndTest = function () {
if (window['QUnit']) {
return false
}
var el = document.createElement('bootstrap')
for (var name in Bootstrap.TransitionEndEvent) {
if (el.style[name] !== undefined) {
return { end: Bootstrap.TransitionEndEvent[name] }
}
}
return false
}
/**
* @param {number} duration
* @this {Element}
* @return {Object}
*/
Bootstrap.transitionEndEmulator = function (duration) {
var called = false
$(this).one(Bootstrap.TRANSITION_END, function () {
called = true
})
var callback = function () {
if (!called) {
$(this).trigger(Bootstrap.transition.end)
}
}.bind(this)
setTimeout(callback, duration)
$.fn.alert.noConflict = function () {
$.fn.alert = old
return this return this
} }
// ALERT DATA-API /**
// ============== * ------------------------------------------------------------------------
* jQuery Interface
* ------------------------------------------------------------------------
*/
$(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) $.fn.emulateTransitionEnd = Bootstrap.transitionEndEmulator
}(jQuery); $(function () {
Bootstrap.transition = Bootstrap.transitionEndTest()
/* ======================================================================== if (!Bootstrap.transition) {
* Bootstrap: button.js v3.3.2 return
}
$.event.special[Bootstrap.TRANSITION_END] = Bootstrap.getSpecialTransitionEndEvent()
})
$(document).on('mq4hsChange', function (e) {
$(document.documentElement).toggleClass('bs-true-hover', e.trueHover)
})
/*!
* mq4-hover-shim v0.1.0
* https://github.com/twbs/mq4-hover-shim
* Copyright (c) 2014-2015 Christopher Rebert
* Licensed under the MIT License (https://github.com/twbs/mq4-hover-shim/blob/master/LICENSE).
*/
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.mq4HoverShim=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
"use strict";
var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { "default": obj }; };
/**
* Does this UA's primary pointer support true hovering
* OR does the UA at least not try to quirkily emulate hovering,
* such that :hover CSS styles are appropriate?
* Essentially tries to shim the `@media (hover: hover)` CSS media query feature.
* @public
* @returns {boolean}
* @since 0.0.1
*/
exports.supportsTrueHover = supportsTrueHover;
/*eslint-env browser */
/*eslint no-var:2*/
/* jshint browser: true, esnext: true */
/* jshint -W080 */
/**
* @module mq4HoverShim
* @requires jquery
*/
var $ = (function () {
try {
var jQuery = _interopRequireWildcard(require("jquery"));
return jQuery;
} catch (importErr) {
var globaljQuery = window.$ || window.jQuery || window.Zepto;
if (!globaljQuery) {
throw new Error("mq4HoverShim needs jQuery (or similar)");
}
return globaljQuery;
}
})();
/** @type {boolean|undefined} */
var canTrulyHover = undefined;
/**
* @private
* @fires mq4HoverShim#mq4hsChange
*/
function triggerEvent() {
$(document).trigger($.Event("mq4hsChange", { bubbles: false, trueHover: canTrulyHover }));
}
// IIFE so we can use `return`s to avoid deeply-nested if-s
(function () {
if (!window.matchMedia) {
// Opera Mini, IE<=9, Android<=2.3, ancient, or obscure; per http://caniuse.com/#feat=matchmedia
// Opera Mini, Android, and IE Mobile don't support true hovering, so they're what we'll check for.
// Other browsers are either:
// (a) obscure
// (b) touch-based but old enough not to attempt to emulate hovering
// (c) old desktop browsers that do support true hovering
// Explanation of this UA regex:
// IE Mobile <9 seems to always have "Windows CE", "Windows Phone", or "IEMobile" in its UA string.
// IE Mobile 9 in desktop view doesn't include "IEMobile" or "Windows Phone" in the UA string,
// but it instead includes "XBLWP7" and/or "ZuneWP7".
canTrulyHover = !/Opera Mini|Android|IEMobile|Windows (Phone|CE)|(XBL|Zune)WP7/.test(navigator.userAgent);
// Since there won't be any event handlers to fire our events, do the one-and-only firing of it here and now.
triggerEvent();
return;
}
// CSSWG Media Queries Level 4 draft
// http://drafts.csswg.org/mediaqueries/#hover
var HOVER_NONE = "(hover: none),(-moz-hover: none),(-ms-hover: none),(-webkit-hover: none)";
var HOVER_ON_DEMAND = "(hover: on-demand),(-moz-hover: on-demand),(-ms-hover: on-demand),(-webkit-hover: on-demand)";
var HOVER_HOVER = "(hover: hover),(-moz-hover: hover),(-ms-hover: hover),(-webkit-hover: hover)";
if (window.matchMedia("" + HOVER_NONE + "," + HOVER_ON_DEMAND + "," + HOVER_HOVER).matches) {
// Browser understands the `hover` media feature
var hoverCallback = function (mql) {
var doesMatch = mql.matches;
if (doesMatch !== canTrulyHover) {
canTrulyHover = doesMatch;
triggerEvent();
}
};
var atHoverQuery = window.matchMedia(HOVER_HOVER);
atHoverQuery.addListener(hoverCallback);
hoverCallback(atHoverQuery);
return;
}
// Check for touch support instead.
// Touch generally implies that hovering is merely emulated,
// which doesn't count as true hovering support for our purposes
// due to the quirkiness of the emulation (e.g. :hover being sticky).
// W3C Pointer Events PR, 16 December 2014
// http://www.w3.org/TR/2014/PR-pointerevents-20141216/
// Prefixed in IE10, per http://caniuse.com/#feat=pointer
if (window.PointerEvent || window.MSPointerEvent) {
// Browser supports Pointer Events
// Browser supports touch if it has touch points
/* jshint -W018 */
canTrulyHover = !((window.navigator.maxTouchPoints || window.navigator.msMaxTouchPoints) > 0);
/* jshint +W018 */
triggerEvent();
return;
}
// Mozilla's -moz-touch-enabled
// https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Media_queries#-moz-touch-enabled
var touchEnabledQuery = window.matchMedia("(touch-enabled),(-moz-touch-enabled),(-ms-touch-enabled),(-webkit-touch-enabled)");
if (touchEnabledQuery.matches) {
canTrulyHover = false;
triggerEvent();
return;
}
// W3C Touch Events REC, 10 October 2013
// http://www.w3.org/TR/2013/REC-touch-events-20131010/
if ("ontouchstart" in window) {
canTrulyHover = false;
triggerEvent();
return;
}
// UA's pointer is non-touch and thus likely either supports true hovering or at least does not try to emulate it.
canTrulyHover = true;
triggerEvent();
})();function supportsTrueHover() {
return canTrulyHover;
}
exports.__esModule = true;
},{"jquery":undefined}]},{},[1])(1)
});
/** =======================================================================
* Bootstrap: alert.js v4.0.0
* 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]
/**
* @const
* @enum {string}
* @private
*/
Alert._Event = {
CLOSE : 'close.bs.alert',
CLOSED : 'closed.bs.alert'
}
/**
* @const
* @enum {string}
* @private
*/
Alert._ClassName = {
ALERT : 'alert',
FADE : 'fade',
IN : 'in'
}
/**
* 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)
if (!data) {
data = new Alert(this)
$this.data(Alert._DATA_KEY, data)
}
if (opt_config === 'close') {
data[opt_config](this)
}
})
}
/**
* Close the alert component
* @param {Alert} alertInstance
* @return {Function}
* @private
*/
Alert._handleDismiss = function (alertInstance) {
return function (event) {
if (event) {
event.preventDefault()
}
alertInstance['close'](this)
}
}
/**
* Close the alert component
* @param {Element} element
*/
Alert.prototype['close'] = function (element) {
var rootElement = this._getRootElement(element)
var customEvent = this._triggerCloseEvent(rootElement)
if (customEvent.isDefaultPrevented()) return
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]
}
if (!parent) {
parent = $(element).closest('.' + Alert._ClassName.ALERT)[0]
}
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
}
/**
* 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
}
$(element)
.one(Bootstrap.TRANSITION_END, this._destroyElement.bind(this, element))
.emulateTransitionEnd(Alert._TRANSITION_DURATION)
}
/**
* clean up any lingering jquery data and kill element
* @private
*/
Alert.prototype._destroyElement = function (element) {
$(element)
.detach()
.trigger(Alert._Event.CLOSED)
.remove()
}
/**
* ------------------------------------------------------------------------
* jQuery Interface + noConflict implementaiton
* ------------------------------------------------------------------------
*/
/**
* @const
* @type {Function}
*/
$.fn[Alert._NAME] = Alert._jQueryInterface
/**
* @const
* @type {Function}
*/
$.fn[Alert._NAME]['Constructor'] = Alert
/**
* @return {Function}
*/
$.fn[Alert._NAME]['noConflict'] = function () {
$.fn[Alert._NAME] = Alert._JQUERY_NO_CONFLICT
return Alert._jQueryInterface
}
/**
* ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/
$(document).on('click.bs.alert.data-api', Alert._DISMISS_SELECTOR, Alert._handleDismiss(new Alert))
/** =======================================================================
* Bootstrap: button.js v4.0.0
* http://getbootstrap.com/javascript/#buttons * http://getbootstrap.com/javascript/#buttons
* ======================================================================== * ========================================================================
* Copyright 2011-2015 Twitter, Inc. * Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * 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
*
* ========================================================================
*/
+function ($) {
'use strict'; 'use strict';
// BUTTON PUBLIC CLASS DEFINITION
// ==============================
var Button = function (element, options) { /**
this.$element = $(element) * Our Button class.
this.options = $.extend({}, Button.DEFAULTS, options) * @param {Element!} element
this.isLoading = false * @constructor
} */
var Button = function (element) {
Button.VERSION = '3.3.2' /** @private {Element} */
this._element = element
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 = 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)
}
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') && this.$element.hasClass('active')) changed = false
else $parent.find('.active').removeClass('active')
}
if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
} else {
this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
}
if (changed) this.$element.toggleClass('active')
} }
// BUTTON PLUGIN DEFINITION /**
// ======================== * @const
* @type {string}
*/
Button['VERSION'] = '4.0.0'
function Plugin(option) {
/**
* @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 () { return this.each(function () {
var $this = $(this) var data = $(this).data(Button._DATA_KEY)
var data = $this.data('bs.button')
var options = typeof option == 'object' && option
if (!data) $this.data('bs.button', (data = new Button(this, options))) if (!data) {
data = new Button(this)
$(this).data(Button._DATA_KEY, data)
}
if (option == 'toggle') data.toggle() if (opt_config === 'toggle') {
else if (option) data.setState(option) data[opt_config]()
}
}) })
} }
var old = $.fn.button
$.fn.button = Plugin /**
$.fn.button.Constructor = Button * 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)
}
}
}
if (triggerChangeEvent) {
input.checked = !$(this._element).hasClass(Button._ClassName.ACTIVE)
$(this._element).trigger('change')
}
}
} else {
this._element.setAttribute('aria-pressed', !$(this._element).hasClass(Button._ClassName.ACTIVE))
}
if (triggerChangeEvent) {
$(this._element).toggleClass(Button._ClassName.ACTIVE)
}
}
// BUTTON NO CONFLICT /**
// ================== * ------------------------------------------------------------------------
* jQuery Interface + noConflict implementaiton
* ------------------------------------------------------------------------
*/
$.fn.button.noConflict = function () { /**
$.fn.button = old * @const
* @type {Function}
*/
$.fn[Button._NAME] = Button._jQueryInterface
/**
* @const
* @type {Function}
*/
$.fn[Button._NAME]['Constructor'] = Button
/**
* @const
* @type {Function}
*/
$.fn[Button._NAME]['noConflict'] = function () {
$.fn[Button._NAME] = Button._JQUERY_NO_CONFLICT
return this return this
} }
// BUTTON DATA-API /**
// =============== * ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/
$(document) $(document)
.on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { .on('click.bs.button.data-api', Button._Selector.DATA_TOGGLE_CARROT, function (event) {
var $btn = $(e.target) event.preventDefault()
if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
Plugin.call($btn, 'toggle') var button = event.target
e.preventDefault()
if (!$(button).hasClass(Button._ClassName.BUTTON)) {
button = $(button).closest(Button._Selector.BUTTON)
}
Button._jQueryInterface.call($(button), 'toggle')
}) })
.on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) { .on('focus.bs.button.data-api blur.bs.button.data-api', Button._Selector.DATA_TOGGLE_CARROT, function (event) {
$(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type)) var button = $(event.target).closest(Button._Selector.BUTTON)[0]
$(button).toggleClass(Button._ClassName.FOCUS, /^focus(in)?$/.test(event.type))
}) })
}(jQuery); /** =======================================================================
* Bootstrap: carousel.js v4.0.0
/* ========================================================================
* Bootstrap: carousel.js v3.3.2
* http://getbootstrap.com/javascript/#carousel * http://getbootstrap.com/javascript/#carousel
* ======================================================================== * ========================================================================
* Copyright 2011-2015 Twitter, Inc. * Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * 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
*
* ========================================================================
*/
+function ($) {
'use strict'; 'use strict';
// CAROUSEL CLASS DEFINITION
// =========================
var Carousel = function (element, options) { /**
this.$element = $(element) * Our carousel class.
this.$indicators = this.$element.find('.carousel-indicators') * @param {Element!} element
this.options = options * @param {Object=} opt_config
this.paused = * @constructor
this.sliding = */
this.interval = var Carousel = function (element, opt_config) {
this.$active =
this.$items = null
this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)) /** @private {Element} */
this._element = $(element)[0]
this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element /** @private {Element} */
.on('mouseenter.bs.carousel', $.proxy(this.pause, this)) this._indicatorsElement = $(this._element).find(Carousel._Selector.INDICATORS)[0]
.on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
}
Carousel.VERSION = '3.3.2' /** @private {?Object} */
this._config = opt_config || null
Carousel.TRANSITION_DURATION = 600 /** @private {boolean} */
this._isPaused = false
Carousel.DEFAULTS = { /** @private {boolean} */
interval: 5000, this._isSliding = false
pause: 'hover',
wrap: true,
keyboard: true
}
Carousel.prototype.keydown = function (e) { /** @private {?number} */
if (/input|textarea/i.test(e.target.tagName)) return this._interval = null
switch (e.which) {
case 37: this.prev(); break
case 39: this.next(); break
default: return
}
e.preventDefault() /** @private {?Element} */
} this._activeElement = null
Carousel.prototype.cycle = function (e) { /** @private {?Array} */
e || (this.paused = false) this._items = null
this.interval && clearInterval(this.interval) this._addEventListeners()
this.options.interval
&& !this.paused
&& (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
return this
}
Carousel.prototype.getItemIndex = function (item) {
this.$items = item.parent().children('.carousel-item')
return this.$items.index(item || this.$active)
}
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)
}
Carousel.prototype.to = function (pos) {
var that = this
var activeIndex = this.getItemIndex(this.$active = this.$element.find('.carousel-item.active'))
if (pos > (this.$items.length - 1) || pos < 0) return
if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
if (activeIndex == pos) return this.pause().cycle()
return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
}
Carousel.prototype.pause = function (e) {
e || (this.paused = true)
if (this.$element.find('.next, .prev').length && $.support.transition) {
this.$element.trigger($.support.transition.end)
this.cycle(true)
}
this.interval = clearInterval(this.interval)
return this
}
Carousel.prototype.next = function () {
if (this.sliding) return
return this.slide('next')
}
Carousel.prototype.prev = function () {
if (this.sliding) return
return this.slide('prev')
}
Carousel.prototype.slide = function (type, next) {
var $active = this.$element.find('.carousel-item.active')
var $next = next || this.getItemForDirection(type, $active)
var isCycling = this.interval
var direction = type == 'next' ? 'left' : 'right'
var that = this
if ($next.hasClass('active')) return (this.sliding = false)
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
isCycling && this.pause()
if (this.$indicators.length) {
this.$indicators.find('.active').removeClass('active')
var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
$nextIndicator && $nextIndicator.addClass('active')
}
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)
}
isCycling && this.cycle()
return this
} }
// CAROUSEL PLUGIN DEFINITION /**
// ========================== * @const
* @type {string}
*/
Carousel['VERSION'] = '4.0.0'
function Plugin(option) {
/**
* @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 () { return this.each(function () {
var $this = $(this) var data = $(this).data(Carousel._DATA_KEY)
var data = $this.data('bs.carousel') var config = $.extend({}, Carousel['Defaults'], $(this).data(), typeof opt_config == 'object' && opt_config)
var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) var action = typeof opt_config == 'string' ? opt_config : config.slide
var action = typeof option == 'string' ? option : options.slide
if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) if (!data) {
if (typeof option == 'number') data.to(option) data = new Carousel(this, config)
else if (action) data[action]() $(this).data(Carousel._DATA_KEY, data)
else if (options.interval) data.pause().cycle() }
if (typeof opt_config == 'number') {
data.to(opt_config)
} else if (action) {
data[action]()
} else if (config.interval) {
data['pause']()
data['cycle']()
}
}) })
} }
var old = $.fn.carousel
$.fn.carousel = Plugin /**
$.fn.carousel.Constructor = Carousel * Click handler for data api
* @param {Event} event
* @this {Element}
* @private
*/
Carousel._dataApiClickHandler = function (event) {
var selector = Bootstrap.getSelectorFromElement(this)
if (!selector) {
// CAROUSEL NO CONFLICT return
// ====================
$.fn.carousel.noConflict = function () {
$.fn.carousel = old
return this
} }
var target = $(selector)[0]
// CAROUSEL DATA-API if (!target || !$(target).hasClass(Carousel._ClassName.CAROUSEL)) {
// ================= return
}
var clickHandler = function (e) { var config = $.extend({}, $(target).data(), $(this).data())
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
Plugin.call($target, options) var slideIndex = this.getAttribute('data-slide-to')
if (slideIndex) {
config.interval = false
}
Carousel._jQueryInterface.call($(target), config)
if (slideIndex) { if (slideIndex) {
$target.data('bs.carousel').to(slideIndex) $(target).data(Carousel._DATA_KEY).to(slideIndex)
} }
e.preventDefault() event.preventDefault()
} }
/**
* Advance the carousel to the next slide
*/
Carousel.prototype['next'] = function () {
if (!this._isSliding) {
this._slide(Carousel._Direction.NEXT)
}
}
/**
* Return the carousel to the previous slide
*/
Carousel.prototype['prev'] = function () {
if (!this._isSliding) {
this._slide(Carousel._Direction.PREVIOUS)
}
}
/**
* Pause the carousel cycle
* @param {Event=} opt_event
*/
Carousel.prototype['pause'] = function (opt_event) {
if (!opt_event) {
this._isPaused = true
}
if ($(this._element).find(Carousel._Selector.NEXT_PREV)[0] && Bootstrap.transition) {
$(this._element).trigger(Bootstrap.transition.end)
this['cycle'](true)
}
clearInterval(this._interval)
this._interval = null
}
/**
* Cycle to the next carousel item
* @param {Event|boolean=} opt_event
*/
Carousel.prototype['cycle'] = function (opt_event) {
if (!opt_event) {
this._isPaused = false
}
if (this._interval) {
clearInterval(this._interval)
this._interval = null
}
if (this._config['interval'] && !this._isPaused) {
this._interval = setInterval(this['next'].bind(this), this._config['interval'])
}
}
/**
* @return {Object}
*/
Carousel.prototype['getConfig'] = function () {
return this._config
}
/**
* 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]
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
}
if (activeIndex == index) {
this['pause']()
this['cycle']()
return
}
var direction = index > activeIndex ?
Carousel._Direction.NEXT :
Carousel._Direction.PREVIOUS
this._slide(direction, this._items[index])
}
/**
* 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))
}
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))
}
}
/**
* 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
}
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]
}
/**
* 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)
return slideEvent
}
/**
* 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)
var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)]
if (nextIndicator) {
$(nextIndicator).addClass(Carousel._ClassName.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 directionalClassName = direction == Carousel._Direction.NEXT ?
Carousel._ClassName.LEFT :
Carousel._ClassName.RIGHT
if (nextElement && $(nextElement).hasClass(Carousel._ClassName.ACTIVE)) {
this._isSliding = false
return
}
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
}
this._isSliding = true
if (isCycling) {
this['pause']()
}
this._setActiveIndicatorElement(nextElement)
var slidEvent = $.Event(Carousel._Event.SLID, { relatedTarget: nextElement, direction: directionalClassName })
if (Bootstrap.transition && $(this._element).hasClass(Carousel._ClassName.SLIDE)) {
$(nextElement).addClass(direction)
Bootstrap.reflow(nextElement)
$(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)
}
if (isCycling) {
this['cycle']()
}
}
/**
* ------------------------------------------------------------------------
* jQuery Interface + noConflict implementaiton
* ------------------------------------------------------------------------
*/
/**
* @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
}
/**
* ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/
$(document) $(document)
.on('click.bs.carousel.data-api', '[data-slide]', clickHandler) .on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', Carousel._dataApiClickHandler)
.on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
$(window).on('load', function () { $(window).on('load', function () {
$('[data-ride="carousel"]').each(function () { $('[data-ride="carousel"]').each(function () {
var $carousel = $(this) var $carousel = $(this)
Plugin.call($carousel, $carousel.data()) Carousel._jQueryInterface.call($carousel, /** @type {Object} */ ($carousel.data()))
}) })
}) })
}(jQuery); /** =======================================================================
* Bootstrap: collapse.js v4.0.0
/* ========================================================================
* Bootstrap: collapse.js v3.3.2
* http://getbootstrap.com/javascript/#collapse * http://getbootstrap.com/javascript/#collapse
* ======================================================================== * ========================================================================
* Copyright 2011-2015 Twitter, Inc. * Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * 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
*
* ========================================================================
*/
+function ($) {
'use strict'; 'use strict';
// COLLAPSE PUBLIC CLASS DEFINITION
// ================================
var Collapse = function (element, options) { /**
this.$element = $(element) * Our collapse class.
this.options = $.extend({}, Collapse.DEFAULTS, options) * @param {Element!} element
this.$trigger = $(this.options.trigger).filter('[href="#' + element.id + '"], [data-target="#' + element.id + '"]') * @param {Object=} opt_config
this.transitioning = null * @constructor
*/
var Collapse = function (element, opt_config) {
if (this.options.parent) { /** @private {Element} */
this.$parent = this.getParent() this._element = element
} else {
this.addAriaAndCollapsedClass(this.$element, this.$trigger) /** @private {Object} */
this._config = $.extend({}, Collapse['Defaults'], opt_config)
/** @private {Element} */
this._trigger = typeof this._config['trigger'] == 'string' ?
$(this._config['trigger'])[0] : this._config['trigger']
/** @private {boolean} */
this._isTransitioning = false
/** @private {?Element} */
this._parent = this._config['parent'] ? this._getParent() : null
if (!this._config['parent']) {
this._addAriaAndCollapsedClass(this._element, this._trigger)
} }
if (this.options.toggle) this.toggle() if (this._config['toggle']) {
this['toggle']()
} }
Collapse.VERSION = '3.3.2'
Collapse.TRANSITION_DURATION = 350
Collapse.DEFAULTS = {
toggle: true,
trigger: '[data-toggle="collapse"]'
}
Collapse.prototype.dimension = function () {
var hasWidth = this.$element.hasClass('width')
return hasWidth ? 'width' : 'height'
}
Collapse.prototype.show = function () {
if (this.transitioning || this.$element.hasClass('in')) return
var activesData
var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
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
if (actives && actives.length) {
Plugin.call(actives, 'hide')
activesData || actives.data('bs.collapse', null)
}
var dimension = this.dimension()
this.$element
.removeClass('collapse')
.addClass('collapsing')[dimension](0)
.attr('aria-expanded', true)
this.$trigger
.removeClass('collapsed')
.attr('aria-expanded', true)
this.transitioning = 1
var complete = function () {
this.$element
.removeClass('collapsing')
.addClass('collapse in')[dimension]('')
this.transitioning = 0
this.$element
.trigger('shown.bs.collapse')
}
if (!$.support.transition) return complete.call(this)
var scrollSize = $.camelCase(['scroll', dimension].join('-'))
this.$element
.one('bsTransitionEnd', $.proxy(complete, this))
.emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
}
Collapse.prototype.hide = function () {
if (this.transitioning || !this.$element.hasClass('in')) return
var startEvent = $.Event('hide.bs.collapse')
this.$element.trigger(startEvent)
if (startEvent.isDefaultPrevented()) return
var dimension = this.dimension()
this.$element[dimension](this.$element[dimension]())[0].offsetHeight
this.$element
.addClass('collapsing')
.removeClass('collapse in')
.attr('aria-expanded', false)
this.$trigger
.addClass('collapsed')
.attr('aria-expanded', false)
this.transitioning = 1
var complete = function () {
this.transitioning = 0
this.$element
.removeClass('collapsing')
.addClass('collapse')
.trigger('hidden.bs.collapse')
}
if (!$.support.transition) return complete.call(this)
this.$element
[dimension](0)
.one('bsTransitionEnd', $.proxy(complete, this))
.emulateTransitionEnd(Collapse.TRANSITION_DURATION)
}
Collapse.prototype.toggle = function () {
this[this.$element.hasClass('in') ? 'hide' : 'show']()
}
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()
}
Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
var isOpen = $element.hasClass('in')
$element.attr('aria-expanded', isOpen)
$trigger
.toggleClass('collapsed', !isOpen)
.attr('aria-expanded', isOpen)
}
function getTargetFromTrigger($trigger) {
var href
var target = $trigger.attr('data-target')
|| (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
return $(target)
} }
// COLLAPSE PLUGIN DEFINITION /**
// ========================== * @const
* @type {string}
*/
Collapse['VERSION'] = '4.0.0'
function Plugin(option) {
/**
* @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 () { return this.each(function () {
var $this = $(this) var $this = $(this)
var data = $this.data('bs.collapse') var data = $this.data(Collapse._DATA_KEY)
var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) var config = $.extend({}, Collapse['Defaults'], $this.data(), typeof opt_config == 'object' && opt_config)
if (!data && options.toggle && option == 'show') options.toggle = false if (!data && config['toggle'] && opt_config == 'show') {
if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) config['toggle'] = false
if (typeof option == 'string') data[option]() }
if (!data) {
data = new Collapse(this, config)
$this.data(Collapse._DATA_KEY, data)
}
if (typeof opt_config == 'string') {
data[opt_config]()
}
}) })
} }
var old = $.fn.collapse
$.fn.collapse = Plugin /**
$.fn.collapse.Constructor = Collapse * Function for getting target element from element
* @return {Element}
* @private
*/
Collapse._getTargetFromElement = function (element) {
var selector = Bootstrap.getSelectorFromElement(element)
return selector ? $(selector)[0] : null
}
// COLLAPSE NO CONFLICT /**
// ==================== * 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']()
}
}
$.fn.collapse.noConflict = function () {
$.fn.collapse = old /**
* Show's the collapsing element
*/
Collapse.prototype['show'] = function () {
if (this._isTransitioning || $(this._element).hasClass(Collapse._ClassName.IN)) {
return
}
var activesData, actives
if (this._parent) {
actives = $.makeArray($(Collapse._Selector.ACTIVES))
if (!actives.length) {
actives = null
}
}
if (actives) {
activesData = $(actives).data(Collapse._DATA_KEY)
if (activesData && activesData._isTransitioning) {
return
}
}
var startEvent = $.Event(Collapse._Event.SHOW)
$(this._element).trigger(startEvent)
if (startEvent.isDefaultPrevented()) {
return
}
if (actives) {
Collapse._jQueryInterface.call($(actives), 'hide')
if (!activesData) {
$(actives).data(Collapse._DATA_KEY, null)
}
}
var dimension = this._getDimension()
$(this._element)
.removeClass(Collapse._ClassName.COLLAPSE)
.addClass(Collapse._ClassName.COLLAPSING)
this._element.style[dimension] = 0
this._element.setAttribute('aria-expanded', true)
if (this._trigger) {
$(this._trigger).removeClass(Collapse._ClassName.COLLAPSED)
this._trigger.setAttribute('aria-expanded', true)
}
this['setTransitioning'](true)
var complete = function () {
$(this._element)
.removeClass(Collapse._ClassName.COLLAPSING)
.addClass(Collapse._ClassName.COLLAPSE)
.addClass(Collapse._ClassName.IN)
this._element.style[dimension] = ''
this['setTransitioning'](false)
$(this._element).trigger(Collapse._Event.SHOWN)
}.bind(this)
if (!Bootstrap.transition) {
complete()
return
}
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
}
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)
}
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)
this._element.style[dimension] = 0
if (!Bootstrap.transition) {
return complete()
}
$(this._element)
.one(Bootstrap.TRANSITION_END, complete)
.emulateTransitionEnd(Collapse._TRANSITION_DURATION)
}
/**
* @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.<Element>} */ ($.makeArray($(parent).find(selector)))
for (var i = 0; i < elements.length; i++) {
this._addAriaAndCollapsedClass(Collapse._getTargetFromElement(elements[i]), elements[i])
}
return parent
}
/**
* 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)
if (trigger) {
trigger.setAttribute('aria-expanded', isOpen)
$(trigger).toggleClass(Collapse._ClassName.COLLAPSED, !isOpen)
}
}
}
/**
* ------------------------------------------------------------------------
* jQuery Interface + noConflict implementaiton
* ------------------------------------------------------------------------
*/
/**
* @const
* @type {Function}
*/
$.fn[Collapse._NAME] = Collapse._jQueryInterface
/**
* @const
* @type {Function}
*/
$.fn[Collapse._NAME]['Constructor'] = Collapse
/**
* @const
* @type {Function}
*/
$.fn[Collapse._NAME]['noConflict'] = function () {
$.fn[Collapse._NAME] = Collapse._JQUERY_NO_CONFLICT
return this return this
} }
// COLLAPSE DATA-API /**
// ================= * ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/
$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (event) {
var $this = $(this) event.preventDefault()
if (!$this.attr('data-target')) e.preventDefault() var target = Collapse._getTargetFromElement(this)
var $target = getTargetFromTrigger($this) var data = $(target).data(Collapse._DATA_KEY)
var data = $target.data('bs.collapse') var config = data ? 'toggle' : $.extend({}, $(this).data(), { trigger: this })
var option = data ? 'toggle' : $.extend({}, $this.data(), { trigger: this })
Plugin.call($target, option) Collapse._jQueryInterface.call($(target), config)
}) })
}(jQuery); /** =======================================================================
* Bootstrap: dropdown.js v4.0.0
/* ======================================================================== * http://getbootstrap.com/javascript/#dropdown
* Bootstrap: dropdown.js v3.3.2
* http://getbootstrap.com/javascript/#dropdowns
* ======================================================================== * ========================================================================
* Copyright 2011-2015 Twitter, Inc. * Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * 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
*
* ========================================================================
*/
+function ($) {
'use strict'; 'use strict';
// DROPDOWN CLASS DEFINITION
// =========================
var backdrop = '.dropdown-backdrop' /**
var toggle = '[data-toggle="dropdown"]' * Our dropdown class.
* @param {Element!} element
* @constructor
*/
var Dropdown = function (element) { var Dropdown = function (element) {
$(element).on('click.bs.dropdown', this.toggle) $(element).on('click.bs.dropdown', this['toggle'])
} }
Dropdown.VERSION = '3.3.2'
Dropdown.prototype.toggle = function (e) { /**
var $this = $(this) * @const
* @type {string}
*/
Dropdown['VERSION'] = '4.0.0'
if ($this.is('.disabled, :disabled')) return
var $parent = getParent($this) /**
var isActive = $parent.hasClass('open') * @const
* @type {string}
* @private
*/
Dropdown._NAME = 'dropdown'
clearMenus()
if (!isActive) { /**
if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { * @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)
}
})
}
/**
* @param {Event=} opt_event
* @private
*/
Dropdown._clearMenus = function (opt_event) {
if (opt_event && opt_event.which == 3) {
return
}
var backdrop = $(Dropdown._Selector.BACKDROP)[0]
if (backdrop) {
backdrop.parentNode.removeChild(backdrop)
}
var toggles = /** @type {Array.<Element>} */ ($.makeArray($(Dropdown._Selector.DATA_TOGGLE)))
for (var i = 0; i < toggles.length; i++) {
var parent = Dropdown._getParentFromElement(toggles[i])
var relatedTarget = { 'relatedTarget': toggles[i] }
if (!$(parent).hasClass(Dropdown._ClassName.OPEN)) {
continue
}
var hideEvent = $.Event(Dropdown._Event.HIDE, relatedTarget)
$(parent).trigger(hideEvent)
if (hideEvent.isDefaultPrevented()) {
continue
}
toggles[i].setAttribute('aria-expanded', 'false')
$(parent)
.removeClass(Dropdown._ClassName.OPEN)
.trigger(Dropdown._Event.HIDDEN, relatedTarget)
}
}
/**
* @param {Element} element
* @return {Element}
* @private
*/
Dropdown._getParentFromElement = function (element) {
var selector = Bootstrap.getSelectorFromElement(element)
if (selector) {
var parent = $(selector)[0]
}
return /** @type {Element} */ (parent || element.parentNode)
}
/**
* @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
}
event.preventDefault()
event.stopPropagation()
if (this.disabled || $(this).hasClass(Dropdown._ClassName.DISABLED)) {
return
}
var parent = Dropdown._getParentFromElement(this)
var isActive = $(parent).hasClass(Dropdown._ClassName.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
}
var items = $.makeArray($(Dropdown._Selector.VISIBLE_ITEMS))
items = items.filter(function (item) {
return item.offsetWidth || item.offsetHeight
})
if (!items.length) {
return
}
var index = items.indexOf(event.target)
if (event.which == 38 && index > 0) index-- // up
if (event.which == 40 && index < items.length - 1) index++ // down
if (!~index) index = 0
items[index].focus()
}
/**
* Toggles the dropdown
* @this {Element}
* @return {boolean|undefined}
*/
Dropdown.prototype['toggle'] = function () {
if (this.disabled || $(this).hasClass(Dropdown._ClassName.DISABLED)) {
return
}
var parent = Dropdown._getParentFromElement(this)
var isActive = $(parent).hasClass(Dropdown._ClassName.OPEN)
Dropdown._clearMenus()
if (isActive) {
return false
}
if ('ontouchstart' in document.documentElement && !$(parent).closest(Dropdown._Selector.NAVBAR_NAV).length) {
// if mobile we use a backdrop because click events don't delegate // if mobile we use a backdrop because click events don't delegate
$('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus) var dropdown = document.createElement('div')
dropdown.className = Dropdown._ClassName.BACKDROP
this.parentNode.insertBefore(this, dropdown)
$(dropdown).on('click', Dropdown._clearMenus)
} }
var relatedTarget = { relatedTarget: this } var relatedTarget = { 'relatedTarget': this }
$parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget)) var showEvent = $.Event(Dropdown._Event.SHOW, relatedTarget)
if (e.isDefaultPrevented()) return $(parent).trigger(showEvent)
$this if (showEvent.isDefaultPrevented()) {
.trigger('focus') return
.attr('aria-expanded', 'true')
$parent
.toggleClass('open')
.trigger('shown.bs.dropdown', relatedTarget)
} }
this.focus()
this.setAttribute('aria-expanded', 'true')
$(parent).toggleClass(Dropdown._ClassName.OPEN)
$(parent).trigger(Dropdown._Event.SHOWN, relatedTarget)
return false return false
} }
Dropdown.prototype.keydown = function (e) {
if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
var $this = $(this) /**
* ------------------------------------------------------------------------
* jQuery Interface + noConflict implementaiton
* ------------------------------------------------------------------------
*/
e.preventDefault() /**
e.stopPropagation() * @const
* @type {Function}
if ($this.is('.disabled, :disabled')) return */
$.fn[Dropdown._NAME] = Dropdown._jQueryInterface
var $parent = getParent($this)
var isActive = $parent.hasClass('open')
if ((!isActive && e.which != 27) || (isActive && e.which == 27)) {
if (e.which == 27) $parent.find(toggle).trigger('focus')
return $this.trigger('click')
}
var desc = ' li:not(.divider):visible a'
var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc)
if (!$items.length) 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
$items.eq(index).trigger('focus')
}
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 }
if (!$parent.hasClass('open')) return
$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
if (e.isDefaultPrevented()) return
$this.attr('aria-expanded', 'false')
$parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
})
}
function getParent($this) {
var selector = $this.attr('data-target')
if (!selector) {
selector = $this.attr('href')
selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
}
var $parent = selector && $(selector)
return $parent && $parent.length ? $parent : $this.parent()
}
// DROPDOWN PLUGIN DEFINITION /**
// ========================== * @const
* @type {Function}
function Plugin(option) { */
return this.each(function () { $.fn[Dropdown._NAME]['Constructor'] = Dropdown
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)
})
}
var old = $.fn.dropdown
$.fn.dropdown = Plugin
$.fn.dropdown.Constructor = Dropdown
// DROPDOWN NO CONFLICT /**
// ==================== * @const
* @type {Function}
$.fn.dropdown.noConflict = function () { */
$.fn.dropdown = old $.fn[Dropdown._NAME]['noConflict'] = function () {
$.fn[Dropdown._NAME] = Dropdown._JQUERY_NO_CONFLICT
return this return this
} }
// APPLY TO STANDARD DROPDOWN ELEMENTS /**
// =================================== * ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/
$(document) $(document)
.on('click.bs.dropdown.data-api', clearMenus) .on('click.bs.dropdown.data-api', Dropdown._clearMenus)
.on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) .on('click.bs.dropdown.data-api', Dropdown._Selector.FORM_CHILD, function (e) { e.stopPropagation() })
.on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) .on('click.bs.dropdown.data-api', Dropdown._Selector.DATA_TOGGLE, Dropdown.prototype['toggle'])
.on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) .on('keydown.bs.dropdown.data-api', Dropdown._Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler)
.on('keydown.bs.dropdown.data-api', '[role="menu"]', Dropdown.prototype.keydown) .on('keydown.bs.dropdown.data-api', Dropdown._Selector.ROLE_MENU, Dropdown._dataApiKeydownHandler)
.on('keydown.bs.dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown) .on('keydown.bs.dropdown.data-api', Dropdown._Selector.ROLE_LISTBOX, Dropdown._dataApiKeydownHandler)
}(jQuery); /** =======================================================================
* Bootstrap: modal.js v4.0.0
/* ======================================================================== * http://getbootstrap.com/javascript/#modal
* Bootstrap: modal.js v3.3.2
* http://getbootstrap.com/javascript/#modals
* ======================================================================== * ========================================================================
* Copyright 2011-2015 Twitter, Inc. * Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * 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
*
* ========================================================================
*/
+function ($) {
'use strict'; 'use strict';
// MODAL CLASS DEFINITION
// ======================
var Modal = function (element, options) { /**
this.options = options * Our modal class.
this.$body = $(document.body) * @param {Element} element
this.$element = $(element) * @param {Object} config
this.$backdrop = * @constructor
this.isShown = null */
this.scrollbarWidth = 0 var Modal = function (element, config) {
/** @private {Object} */
this._config = config
/** @private {Element} */
this._element = element
/** @private {Element} */
this._backdrop = null
/** @private {boolean} */
this._isShown = false
/** @private {boolean} */
this._isBodyOverflowing = false
/** @private {number} */
this._scrollbarWidth = 0
if (this.options.remote) {
this.$element
.find('.modal-content')
.load(this.options.remote, $.proxy(function () {
this.$element.trigger('loaded.bs.modal')
}, this))
}
} }
Modal.VERSION = '3.3.2'
Modal.TRANSITION_DURATION = 300 /**
Modal.BACKDROP_TRANSITION_DURATION = 150 * @const
* @type {string}
*/
Modal['VERSION'] = '4.0.0'
Modal.DEFAULTS = {
backdrop: true, /**
keyboard: true, * @const
show: true * @type {Object}
*/
Modal['Defaults'] = {
'backdrop' : true,
'keyboard' : true,
'show' : true
} }
Modal.prototype.toggle = function (_relatedTarget) {
return this.isShown ? this.hide() : this.show(_relatedTarget) /**
* @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'
} }
Modal.prototype.show = function (_relatedTarget) {
var that = this
var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
this.$element.trigger(e) /**
* @const
if (this.isShown || e.isDefaultPrevented()) return * @enum {string}
* @private
this.isShown = true */
Modal._ClassName = {
this.checkScrollbar() BACKDROP : 'modal-backdrop',
this.setScrollbar() OPEN : 'modal-open',
this.$body.addClass('modal-open') FADE : 'fade',
IN : 'in'
this.escape()
this.resize()
this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
this.backdrop(function () {
var transition = $.support.transition && that.$element.hasClass('fade')
if (!that.$element.parent().length) {
that.$element.appendTo(that.$body) // don't move modals dom position
} }
that.$element
.show()
.scrollTop(0)
if (that.options.backdrop) that.adjustBackdrop() /**
that.adjustDialog() * @const
* @enum {string}
if (transition) { * @private
that.$element[0].offsetWidth // force reflow */
Modal._Selector = {
DIALOG : '.modal-dialog',
DATA_TOGGLE : '[data-toggle="modal"]',
DATA_DISMISS : '[data-dismiss="modal"]',
SCROLLBAR_MEASURER : 'modal-scrollbar-measure'
} }
that.$element
.addClass('in')
.attr('aria-hidden', false)
that.enforceFocus()
var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) /**
* 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)
transition ? if (!data) {
that.$element.find('.modal-dialog') // wait for modal to slide in data = new Modal(this, config)
.one('bsTransitionEnd', function () { $(this).data(Modal._DATA_KEY, data)
that.$element.trigger('focus').trigger(e) }
})
.emulateTransitionEnd(Modal.TRANSITION_DURATION) : if (typeof opt_config == 'string') {
that.$element.trigger('focus').trigger(e) data[opt_config](opt_relatedTarget)
} else if (config['show']) {
data['show'](opt_relatedTarget)
}
}) })
} }
Modal.prototype.hide = function (e) {
if (e) e.preventDefault()
e = $.Event('hide.bs.modal') /**
* @param {Element} relatedTarget
*/
Modal.prototype['toggle'] = function (relatedTarget) {
return this._isShown ? this['hide']() : this['show'](relatedTarget)
}
this.$element.trigger(e)
if (!this.isShown || e.isDefaultPrevented()) return /**
* @param {Element} relatedTarget
*/
Modal.prototype['show'] = function (relatedTarget) {
var showEvent = $.Event(Modal._Event.SHOW, { relatedTarget: relatedTarget })
this.isShown = false $(this._element).trigger(showEvent)
this.escape() if (this._isShown || showEvent.isDefaultPrevented()) {
this.resize() return
}
this._isShown = true
this._checkScrollbar()
this._setScrollbar()
$(document.body).addClass(Modal._ClassName.OPEN)
this._escape()
this._resize()
$(this._element).on('click.dismiss.bs.modal', Modal._Selector.DATA_DISMISS, this['hide'].bind(this))
this._showBackdrop(this._showElement.bind(this, relatedTarget))
}
/**
* @param {Event} event
*/
Modal.prototype['hide'] = function (event) {
if (event) {
event.preventDefault()
}
var hideEvent = $.Event(Modal._Event.HIDE)
$(this._element).trigger(hideEvent)
if (!this._isShown || hideEvent.isDefaultPrevented()) {
return
}
this._isShown = false
this._escape()
this._resize()
$(document).off('focusin.bs.modal') $(document).off('focusin.bs.modal')
this.$element $(this._element).removeClass(Modal._ClassName.IN)
.removeClass('in') this._element.setAttribute('aria-hidden', true)
.attr('aria-hidden', true)
.off('click.dismiss.bs.modal')
$.support.transition && this.$element.hasClass('fade') ? $(this._element).off('click.dismiss.bs.modal')
this.$element
.one('bsTransitionEnd', $.proxy(this.hideModal, this)) if (Bootstrap.transition && $(this._element).hasClass(Modal._ClassName.FADE)) {
.emulateTransitionEnd(Modal.TRANSITION_DURATION) : $(this._element)
this.hideModal() .one(Bootstrap.TRANSITION_END, this._hideModal.bind(this))
.emulateTransitionEnd(Modal._TRANSITION_DURATION)
} else {
this._hideModal()
}
} }
Modal.prototype.enforceFocus = function () {
/**
* @param {Element} relatedTarget
* @private
*/
Modal.prototype._showElement = function (relatedTarget) {
var transition = Bootstrap.transition && $(this._element).hasClass(Modal._ClassName.FADE)
if (!this._element.parentNode || this._element.parentNode.nodeType != Node.ELEMENT_NODE) {
document.body.appendChild(this._element) // don't move modals dom position
}
this._element.style.display = 'block'
this._element.scrollTop = 0
if (this._config['backdrop']) {
this._adjustBackdrop()
}
if (transition) {
Bootstrap.reflow(this._element)
}
$(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()
}
}
/**
* @private
*/
Modal.prototype._enforceFocus = function () {
$(document) $(document)
.off('focusin.bs.modal') // guard against infinite focus loop .off('focusin.bs.modal') // guard against infinite focus loop
.on('focusin.bs.modal', $.proxy(function (e) { .on('focusin.bs.modal', function (e) {
if (this.$element[0] !== e.target && !this.$element.has(e.target).length) { if (this._element !== e.target && !$(this._element).has(e.target).length) {
this.$element.trigger('focus') this._element.focus()
} }
}, this)) }.bind(this))
} }
Modal.prototype.escape = function () {
if (this.isShown && this.options.keyboard) { /**
this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) { * @private
e.which == 27 && this.hide() */
}, this)) Modal.prototype._escape = function () {
} else if (!this.isShown) { if (this._isShown && this._config['keyboard']) {
this.$element.off('keydown.dismiss.bs.modal') $(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.resize = function () {
if (this.isShown) { /**
$(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this)) * @private
*/
Modal.prototype._resize = function () {
if (this._isShown) {
$(window).on('resize.bs.modal', this._handleUpdate.bind(this))
} else { } else {
$(window).off('resize.bs.modal') $(window).off('resize.bs.modal')
} }
} }
Modal.prototype.hideModal = function () {
var that = this /**
this.$element.hide() * @private
this.backdrop(function () { */
that.$body.removeClass('modal-open') Modal.prototype._hideModal = function () {
that.resetAdjustments() this._element.style.display = 'none'
that.resetScrollbar() this._showBackdrop(function () {
that.$element.trigger('hidden.bs.modal') $(document.body).removeClass(Modal._ClassName.OPEN)
}) this._resetAdjustments()
this._resetScrollbar()
$(this._element).trigger(Modal._Event.HIDDEN)
}.bind(this))
} }
Modal.prototype.removeBackdrop = function () {
this.$backdrop && this.$backdrop.remove() /**
this.$backdrop = null * @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' : ''
if (this.isShown && this.options.backdrop) { /**
var doAnimate = $.support.transition && animate * @param {Function} callback
* @private
*/
Modal.prototype._showBackdrop = function (callback) {
var animate = $(this._element).hasClass(Modal._ClassName.FADE) ? Modal._ClassName.FADE : ''
this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />') if (this._isShown && this._config['backdrop']) {
.prependTo(this.$element) var doAnimate = Bootstrap.transition && animate
.on('click.dismiss.bs.modal', $.proxy(function (e) {
if (e.target !== e.currentTarget) return
this.options.backdrop == 'static'
? this.$element[0].focus.call(this.$element[0])
: this.hide.call(this)
}, this))
if (doAnimate) this.$backdrop[0].offsetWidth // force reflow this._backdrop = document.createElement('div')
this._backdrop.className = Modal._ClassName.BACKDROP
this.$backdrop.addClass('in') if (animate) {
$(this._backdrop).addClass(animate)
}
if (!callback) return $(this._element).prepend(this._backdrop)
doAnimate ? $(this._backdrop).on('click.dismiss.bs.modal', function (event) {
this.$backdrop if (event.target !== event.currentTarget) return
.one('bsTransitionEnd', callback) this._config['backdrop'] === 'static'
.emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : ? this._element.focus()
: this['hide']()
}.bind(this))
if (doAnimate) {
Bootstrap.reflow(this._backdrop)
}
$(this._backdrop).addClass(Modal._ClassName.IN)
if (!callback) {
return
}
if (!doAnimate) {
callback() callback()
return
}
} else if (!this.isShown && this.$backdrop) { $(this._backdrop)
this.$backdrop.removeClass('in') .one(Bootstrap.TRANSITION_END, callback)
.emulateTransitionEnd(Modal._BACKDROP_TRANSITION_DURATION)
} else if (!this._isShown && this._backdrop) {
$(this._backdrop).removeClass(Modal._ClassName.IN)
var callbackRemove = function () { var callbackRemove = function () {
that.removeBackdrop() this._removeBackdrop()
callback && callback() if (callback) {
callback()
} }
$.support.transition && this.$element.hasClass('fade') ? }.bind(this)
this.$backdrop
.one('bsTransitionEnd', callbackRemove) if (Bootstrap.transition && $(this._element).hasClass(Modal._ClassName.FADE)) {
.emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : $(this._backdrop)
.one(Bootstrap.TRANSITION_END, callbackRemove)
.emulateTransitionEnd(Modal._BACKDROP_TRANSITION_DURATION)
} else {
callbackRemove() callbackRemove()
}
} else if (callback) { } else if (callback) {
callback() callback()
} }
} }
// these following methods are used to handle overflowing modals
Modal.prototype.handleUpdate = function () { /**
if (this.options.backdrop) this.adjustBackdrop() * ------------------------------------------------------------------------
this.adjustDialog() * 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()
} }
Modal.prototype.adjustBackdrop = function () { /**
this.$backdrop * @private
.css('height', 0) */
.css('height', this.$element[0].scrollHeight) 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'
} }
Modal.prototype.adjustDialog = function () {
var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
this.$element.css({ /**
paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '', * @private
paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : '' */
}) 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.resetAdjustments = function () { if (this._isBodyOverflowing && !isModalOverflowing) {
this.$element.css({ this._element.style.paddingRight = this._scrollbarWidth + 'px'
paddingLeft: '', }
paddingRight: ''
})
} }
Modal.prototype.checkScrollbar = function () {
this.bodyIsOverflowing = document.body.scrollHeight > document.documentElement.clientHeight /**
this.scrollbarWidth = this.measureScrollbar() * @private
*/
Modal.prototype._resetAdjustments = function () {
this._element.style.paddingLeft = ''
this._element.style.paddingRight = ''
} }
Modal.prototype.setScrollbar = function () {
var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) /**
if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth) * @private
*/
Modal.prototype._checkScrollbar = function () {
this._isBodyOverflowing = document.body.scrollHeight > document.documentElement.clientHeight
this._scrollbarWidth = this._getScrollbarWidth()
} }
Modal.prototype.resetScrollbar = function () {
this.$body.css('padding-right', '') /**
* @private
*/
Modal.prototype._setScrollbar = function () {
var bodyPadding = parseInt(($(document.body).css('padding-right') || 0), 10)
if (this._isBodyOverflowing) {
document.body.style.paddingRight = bodyPadding + this._scrollbarWidth + 'px'
}
} }
Modal.prototype.measureScrollbar = function () { // thx walsh
/**
* @private
*/
Modal.prototype._resetScrollbar = function () {
document.body.style.paddingRight = ''
}
/**
* @private
*/
Modal.prototype._getScrollbarWidth = function () { // thx walsh
var scrollDiv = document.createElement('div') var scrollDiv = document.createElement('div')
scrollDiv.className = 'modal-scrollbar-measure' scrollDiv.className = Modal._Selector.SCROLLBAR_MEASURER
this.$body.append(scrollDiv) document.body.appendChild(scrollDiv)
var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
this.$body[0].removeChild(scrollDiv) document.body.removeChild(scrollDiv)
return scrollbarWidth return scrollbarWidth
} }
// MODAL PLUGIN DEFINITION /**
// ======================= * ------------------------------------------------------------------------
* jQuery Interface + noConflict implementaiton
* ------------------------------------------------------------------------
*/
function Plugin(option, _relatedTarget) { /**
return this.each(function () { * @const
var $this = $(this) * @type {Function}
var data = $this.data('bs.modal') */
var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) $.fn[Modal._NAME] = Modal._jQueryInterface
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
$.fn.modal = Plugin
$.fn.modal.Constructor = Modal
// MODAL NO CONFLICT /**
// ================= * @const
* @type {Function}
*/
$.fn[Modal._NAME]['Constructor'] = Modal
$.fn.modal.noConflict = function () {
$.fn.modal = old /**
* @const
* @type {Function}
*/
$.fn[Modal._NAME]['noConflict'] = function () {
$.fn[Modal._NAME] = Modal._JQUERY_NO_CONFLICT
return this return this
} }
// MODAL DATA-API /**
// ============== * ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/
$(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { $(document).on('click.bs.modal.data-api', Modal._Selector.DATA_TOGGLE, function (event) {
var $this = $(this) var selector = Bootstrap.getSelectorFromElement(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() if (selector) {
var target = $(selector)[0]
}
$target.one('show.bs.modal', function (showEvent) { var config = $(target).data(Modal._DATA_KEY) ? 'toggle' : $.extend({}, $(target).data(), $(this).data())
if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
$target.one('hidden.bs.modal', function () { if (this.tagName == 'A') {
$this.is(':visible') && $this.trigger('focus') event.preventDefault()
}) }
})
Plugin.call($target, option, 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._jQueryInterface.call($(target), config, this)
}) })
}(jQuery); /** =======================================================================
* Bootstrap: scrollspy.js v4.0.0
/* ======================================================================== * http://getbootstrap.com/javascript/#scrollspy
* Bootstrap: tooltip.js v3.3.2
* http://getbootstrap.com/javascript/#tooltip
* Inspired by the original jQuery.tipsy by Jason Frame
* ======================================================================== * ========================================================================
* Copyright 2011-2015 Twitter, Inc. * Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * 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
*
* ========================================================================
*/
+function ($) {
'use strict'; 'use strict';
// TOOLTIP PUBLIC CLASS DEFINITION
// ===============================
var Tooltip = function (element, options) { /**
this.type = * Our scrollspy class.
this.options = * @param {Element!} element
this.enabled = * @param {Object=} opt_config
this.timeout = * @constructor
this.hoverState = */
this.$element = null function ScrollSpy(element, opt_config) {
this.init('tooltip', element, options) /** @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()
} }
Tooltip.VERSION = '3.3.2'
Tooltip.TRANSITION_DURATION = 150 /**
* @const
* @type {string}
*/
ScrollSpy['VERSION'] = '4.0.0'
Tooltip.DEFAULTS = {
animation: true, /**
placement: 'top', * @const
selector: false, * @type {Object}
template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>', */
trigger: 'hover focus', ScrollSpy['Defaults'] = {
title: '', 'offset': 10
delay: 0, }
html: false,
container: false,
viewport: { /**
selector: 'body', * @const
padding: 0 * @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]()
}
})
}
/**
* Refresh the scrollspy target cache
*/
ScrollSpy.prototype['refresh'] = function () {
var offsetMethod = 'offset'
var offsetBase = 0
if (this._scrollElement !== this._scrollElement.window) {
offsetMethod = 'position'
offsetBase = this._getScrollTop()
}
this._offsets = []
this._targets = []
this._scrollHeight = this._getScrollHeight()
var targets = /** @type {Array.<Element>} */ ($.makeArray($(this._selector)))
targets
.map(function (element, index) {
var target
var targetSelector = Bootstrap.getSelectorFromElement(element)
if (targetSelector) {
target = $(targetSelector)[0]
}
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']()
}
if (scrollTop >= maxScroll) {
var target = this._targets[this._targets.length - 1]
if (this._activeTarget != target) {
this._activate(target)
} }
} }
Tooltip.prototype.init = function (type, element, options) { if (this._activeTarget && scrollTop < this._offsets[0]) {
this.enabled = true this._activeTarget = null
this.type = type this._clear()
this.$element = $(element) return
this.options = this.getOptions(options) }
this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
var triggers = this.options.trigger.split(' ') 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])
for (var i = triggers.length; i--;) { if (isActiveTarget) {
var trigger = triggers[i] this._activate(this._targets[i])
}
}
}
/**
* @param {Element} target
* @private
*/
ScrollSpy.prototype._activate = function (target) {
this._activeTarget = target
this._clear()
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)
for (var i = parentListItems.length; i--;) {
$(parentListItems[i]).addClass(ScrollSpy._ClassName.ACTIVE)
var itemParent = parentListItems[i].parentNode
if (itemParent && $(itemParent).hasClass(ScrollSpy._ClassName.DROPDOWN_MENU)) {
var closestDropdown = $(itemParent).closest(ScrollSpy._Selector.LI_DROPDOWN)[0]
$(closestDropdown).addClass(ScrollSpy._ClassName.ACTIVE)
}
}
$(this._scrollElement).trigger(ScrollSpy._Event.ACTIVATE, {
relatedTarget: target
})
}
/**
* @private
*/
ScrollSpy.prototype._clear = function () {
var activeParents = $(this._selector).parentsUntil(this._config.target, ScrollSpy._Selector.ACTIVE)
for (var i = activeParents.length; i--;) {
$(activeParents[i]).removeClass(ScrollSpy._ClassName.ACTIVE)
}
}
/**
* ------------------------------------------------------------------------
* jQuery Interface + noConflict implementaiton
* ------------------------------------------------------------------------
*/
/**
* @const
* @type {Function}
*/
$.fn[ScrollSpy._NAME] = ScrollSpy._jQueryInterface
/**
* @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
}
/**
* ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/
$(window).on('load.bs.scrollspy.data-api', function () {
var scrollSpys = /** @type {Array.<Element>} */ ($.makeArray($(ScrollSpy._Selector.DATA_SPY)))
for (var i = scrollSpys.length; i--;) {
var $spy = $(scrollSpys[i])
ScrollSpy._jQueryInterface.call($spy, /** @type {Object|null} */ ($spy.data()))
}
})
/** =======================================================================
* Bootstrap: tooltip.js v4.0.0
* http://getbootstrap.com/javascript/#tooltip
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ========================================================================
* @fileoverview - Bootstrap's tooltip plugin.
* (Inspired by jQuery.tipsy by Jason Frame)
*
* Public Methods & Properties:
*
* + $.tooltip
* + $.tooltip.noConflict
* + $.tooltip.Constructor
* + $.tooltip.Constructor.VERSION
* + $.tooltip.Constructor.Defaults
* + $.tooltip.Constructor.Defaults.container
* + $.tooltip.Constructor.Defaults.animation
* + $.tooltip.Constructor.Defaults.placement
* + $.tooltip.Constructor.Defaults.selector
* + $.tooltip.Constructor.Defaults.template
* + $.tooltip.Constructor.Defaults.trigger
* + $.tooltip.Constructor.Defaults.title
* + $.tooltip.Constructor.Defaults.delay
* + $.tooltip.Constructor.Defaults.html
* + $.tooltip.Constructor.Defaults.viewport
* + $.tooltip.Constructor.Defaults.viewport.selector
* + $.tooltip.Constructor.Defaults.viewport.padding
* + $.tooltip.Constructor.prototype.enable
* + $.tooltip.Constructor.prototype.disable
* + $.tooltip.Constructor.prototype.destroy
* + $.tooltip.Constructor.prototype.toggleEnabled
* + $.tooltip.Constructor.prototype.toggle
* + $.tooltip.Constructor.prototype.show
* + $.tooltip.Constructor.prototype.hide
*
* ========================================================================
*/
'use strict';
/**
* Our tooltip class.
* @param {Element!} element
* @param {Object=} opt_config
* @constructor
*/
var Tooltip = function (element, opt_config) {
/** @private {boolean} */
this._isEnabled = true
/** @private {number} */
this._timeout = 0
/** @private {string} */
this._hoverState = ''
/** @protected {Element} */
this.element = element
/** @protected {Object} */
this.config = this._getConfig(opt_config)
/** @protected {Element} */
this.tip = null
/** @protected {Element} */
this.arrow = null
if (this.config['viewport']) {
/** @private {Element} */
this._viewport = $(this.config['viewport']['selector'] || this.config['viewport'])[0]
}
this._setListeners()
}
/**
* @const
* @type {string}
*/
Tooltip['VERSION'] = '4.0.0'
/**
* @const
* @type {Object}
*/
Tooltip['Defaults'] = {
'container' : false,
'animation' : true,
'placement' : 'top',
'selector' : false,
'template' : '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
'trigger' : 'hover focus',
'title' : '',
'delay' : 0,
'html' : false,
'viewport': {
'selector': 'body',
'padding' : 0
}
}
/**
* @const
* @enum {string}
* @protected
*/
Tooltip.Direction = {
TOP: 'top',
LEFT: 'left',
RIGHT: 'right',
BOTTOM: 'bottom'
}
/**
* @const
* @type {string}
* @private
*/
Tooltip._NAME = 'tooltip'
/**
* @const
* @type {string}
* @private
*/
Tooltip._DATA_KEY = 'bs.tooltip'
/**
* @const
* @type {number}
* @private
*/
Tooltip._TRANSITION_DURATION = 150
/**
* @const
* @enum {string}
* @private
*/
Tooltip._HoverState = {
IN: 'in',
OUT: 'out'
}
/**
* @const
* @enum {string}
* @private
*/
Tooltip._Event = {
HIDE : 'hide.bs.tooltip',
HIDDEN : 'hidden.bs.tooltip',
SHOW : 'show.bs.tooltip',
SHOWN : 'shown.bs.tooltip'
}
/**
* @const
* @enum {string}
* @private
*/
Tooltip._ClassName = {
FADE : 'fade',
IN : 'in'
}
/**
* @const
* @enum {string}
* @private
*/
Tooltip._Selector = {
TOOLTIP : '.tooltip',
TOOLTIP_INNER : '.tooltip-inner',
TOOLTIP_ARROW : '.tooltip-arrow'
}
/**
* @const
* @type {Function}
* @private
*/
Tooltip._JQUERY_NO_CONFLICT = $.fn[Tooltip._NAME]
/**
* @param {Object=} opt_config
* @this {jQuery}
* @return {jQuery}
* @private
*/
Tooltip._jQueryInterface = function (opt_config) {
return this.each(function () {
var data = $(this).data(Tooltip._DATA_KEY)
var config = typeof opt_config == 'object' ? opt_config : null
if (!data && opt_config == 'destroy') {
return
}
if (!data) {
data = new Tooltip(this, config)
$(this).data(Tooltip._DATA_KEY, data)
}
if (typeof opt_config === 'string') {
data[opt_config]()
}
})
}
/**
* Enable tooltip
*/
Tooltip.prototype['enable'] = function () {
this._isEnabled = true
}
/**
* Disable tooltip
*/
Tooltip.prototype['disable'] = function () {
this._isEnabled = false
}
/**
* Toggle the tooltip enable state
*/
Tooltip.prototype['toggleEnabled'] = function () {
this._isEnabled = !this._isEnabled
}
/**
* Toggle the tooltips display
* @param {Event} opt_event
*/
Tooltip.prototype['toggle'] = function (opt_event) {
var context = this
var dataKey = this.getDataKey()
if (opt_event) {
context = $(opt_event.currentTarget).data(dataKey)
if (!context) {
context = new this.constructor(opt_event.currentTarget, this._getDelegateConfig())
$(opt_event.currentTarget).data(dataKey, context)
}
}
$(context.getTipElement()).hasClass(Tooltip._ClassName.IN) ?
context._leave(null, context) :
context._enter(null, context)
}
/**
* Remove tooltip functionality
*/
Tooltip.prototype['destroy'] = function () {
clearTimeout(this._timeout)
this['hide'](function () {
$(this.element)
.off(Tooltip._Selector.TOOLTIP)
.removeData(this.getDataKey())
}.bind(this))
}
/**
* Show the tooltip
* todo (fat): ~fuck~ this is a big function - refactor out all of positioning logic
* and replace with external lib
*/
Tooltip.prototype['show'] = function () {
var showEvent = $.Event(this.getEventObject().SHOW)
if (this.isWithContent() && this._isEnabled) {
$(this.element).trigger(showEvent)
var isInTheDom = $.contains(this.element.ownerDocument.documentElement, this.element)
if (showEvent.isDefaultPrevented() || !isInTheDom) {
return
}
var tip = this.getTipElement()
var tipId = Bootstrap.getUID(this.getName())
tip.setAttribute('id', tipId)
this.element.setAttribute('aria-describedby', tipId)
this.setContent()
if (this.config['animation']) {
$(tip).addClass(Tooltip._ClassName.FADE)
}
var placement = typeof this.config['placement'] == 'function' ?
this.config['placement'].call(this, tip, this.element) :
this.config['placement']
var autoToken = /\s?auto?\s?/i
var isWithAutoPlacement = autoToken.test(placement)
if (isWithAutoPlacement) {
placement = placement.replace(autoToken, '') || Tooltip.Direction.TOP
}
if (tip.parentNode && tip.parentNode.nodeType == Node.ELEMENT_NODE) {
tip.parentNode.removeChild(tip)
}
tip.style.top = 0
tip.style.left = 0
tip.style.display = 'block'
$(tip).addClass(Tooltip._NAME + '-' + placement)
$(tip).data(this.getDataKey(), this)
if (this.config['container']) {
$(this.config['container'])[0].appendChild(tip)
} else {
this.element.parentNode.insertBefore(tip, this.element.nextSibling)
}
var position = this._getPosition()
var actualWidth = tip.offsetWidth
var actualHeight = tip.offsetHeight
var calculatedPlacement = this._getCalculatedAutoPlacement(isWithAutoPlacement, placement, position, actualWidth, actualHeight)
var calculatedOffset = this._getCalculatedOffset(calculatedPlacement, position, actualWidth, actualHeight)
this._applyCalculatedPlacement(calculatedOffset, calculatedPlacement)
var complete = function () {
var prevHoverState = this.hoverState
$(this.element).trigger(this.getEventObject().SHOWN)
this.hoverState = null
if (prevHoverState == 'out') this._leave(null, this)
}.bind(this)
Bootstrap.transition && $(this._tip).hasClass(Tooltip._ClassName.FADE) ?
$(this._tip)
.one(Bootstrap.TRANSITION_END, complete)
.emulateTransitionEnd(Tooltip._TRANSITION_DURATION) :
complete()
}
}
/**
* Hide the tooltip breh
*/
Tooltip.prototype['hide'] = function (callback) {
var tip = this.getTipElement()
var hideEvent = $.Event(this.getEventObject().HIDE)
var complete = function () {
if (this._hoverState != Tooltip._HoverState.IN) {
tip.parentNode.removeChild(tip)
}
this.element.removeAttribute('aria-describedby')
$(this.element).trigger(this.getEventObject().HIDDEN)
if (callback) {
callback()
}
}.bind(this)
$(this.element).trigger(hideEvent)
if (hideEvent.isDefaultPrevented()) return
$(tip).removeClass(Tooltip._ClassName.IN)
if (Bootstrap.transition && $(this._tip).hasClass(Tooltip._ClassName.FADE)) {
$(tip)
.one(Bootstrap.TRANSITION_END, complete)
.emulateTransitionEnd(Tooltip._TRANSITION_DURATION)
} else {
complete()
}
this._hoverState = ''
}
/**
* @return {string}
*/
Tooltip.prototype['getHoverState'] = function (callback) {
return this._hoverState
}
/**
* @return {string}
* @protected
*/
Tooltip.prototype.getName = function () {
return Tooltip._NAME
}
/**
* @return {string}
* @protected
*/
Tooltip.prototype.getDataKey = function () {
return Tooltip._DATA_KEY
}
/**
* @return {Object}
* @protected
*/
Tooltip.prototype.getEventObject = function () {
return Tooltip._Event
}
/**
* @return {string}
* @protected
*/
Tooltip.prototype.getTitle = function () {
var title = this.element.getAttribute('data-original-title')
if (!title) {
title = typeof this.config['title'] === 'function' ?
this.config['title'].call(this.element) :
this.config['title']
}
return /** @type {string} */ (title)
}
/**
* @return {Element}
* @protected
*/
Tooltip.prototype.getTipElement = function () {
return (this._tip = this._tip || $(this.config['template'])[0])
}
/**
* @return {Element}
* @protected
*/
Tooltip.prototype.getArrowElement = function () {
return (this.arrow = this.arrow || $(this.getTipElement()).find(Tooltip._Selector.TOOLTIP_ARROW)[0])
}
/**
* @return {boolean}
* @protected
*/
Tooltip.prototype.isWithContent = function () {
return !!this.getTitle()
}
/**
* @protected
*/
Tooltip.prototype.setContent = function () {
var tip = this.getTipElement()
var title = this.getTitle()
$(tip).find(Tooltip._Selector.TOOLTIP_INNER)[0][this.config['html'] ? 'innerHTML' : 'innerText'] = title
$(tip)
.removeClass(Tooltip._ClassName.FADE)
.removeClass(Tooltip._ClassName.IN)
for (var direction in Tooltip.Direction) {
$(tip).removeClass(Tooltip._NAME + '-' + direction)
}
}
/**
* @private
*/
Tooltip.prototype._setListeners = function () {
var triggers = this.config['trigger'].split(' ')
triggers.forEach(function (trigger) {
if (trigger == 'click') { if (trigger == 'click') {
this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) $(this.element).on('click.bs.tooltip', this.config['selector'], this['toggle'].bind(this))
} else if (trigger != 'manual') { } else if (trigger != 'manual') {
var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) $(this.element)
this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) .on(eventIn + '.bs.tooltip', this.config['selector'], this._enter.bind(this))
.on(eventOut + '.bs.tooltip', this.config['selector'], this._leave.bind(this))
}
}.bind(this))
if (this.config['selector']) {
this.config = $.extend({}, this.config, { 'trigger': 'manual', 'selector': '' })
} else {
this._fixTitle()
} }
} }
this.options.selector ?
(this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
this.fixTitle()
}
Tooltip.prototype.getDefaults = function () { /**
return Tooltip.DEFAULTS * @param {Object=} opt_config
} * @return {Object}
* @private
*/
Tooltip.prototype._getConfig = function (opt_config) {
var config = $.extend({}, this.constructor['Defaults'], $(this.element).data(), opt_config)
Tooltip.prototype.getOptions = function (options) { if (config['delay'] && typeof config['delay'] == 'number') {
options = $.extend({}, this.getDefaults(), this.$element.data(), options) config['delay'] = {
'show': config['delay'],
if (options.delay && typeof options.delay == 'number') { 'hide': config['delay']
options.delay = {
show: options.delay,
hide: options.delay
} }
} }
return options return config
} }
Tooltip.prototype.getDelegateOptions = function () {
var options = {}
var defaults = this.getDefaults()
this._options && $.each(this._options, function (key, value) { /**
if (defaults[key] != value) options[key] = value * @return {Object}
}) * @private
*/
Tooltip.prototype._getDelegateConfig = function () {
var config = {}
var defaults = this.constructor['Defaults']
return options if (this.config) {
for (var key in this.config) {
var value = this.config[key]
if (defaults[key] != value) config[key] = value
}
} }
Tooltip.prototype.enter = function (obj) { return config
var self = obj instanceof this.constructor ?
obj : $(obj.currentTarget).data('bs.' + this.type)
if (self && self.$tip && self.$tip.is(':visible')) {
self.hoverState = 'in'
return
} }
if (!self) {
self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
$(obj.currentTarget).data('bs.' + this.type, self)
}
clearTimeout(self.timeout)
self.hoverState = 'in' /**
* @param {boolean} isWithAutoPlacement
* @param {string} placement
* @param {Object} position
* @param {number} actualWidth
* @param {number} actualHeight
* @return {string}
* @private
*/
Tooltip.prototype._getCalculatedAutoPlacement = function (isWithAutoPlacement, placement, position, actualWidth, actualHeight) {
if (isWithAutoPlacement) {
var originalPlacement = placement
var container = this.config['container'] ? $(this.config['container'])[0] : this.element.parentNode
var containerDim = this._getPosition(/** @type {Element} */ (container))
if (!self.options.delay || !self.options.delay.show) return self.show() placement = placement == Tooltip.Direction.BOTTOM && position.bottom + actualHeight > containerDim.bottom ? Tooltip.Direction.TOP :
placement == Tooltip.Direction.TOP && position.top - actualHeight < containerDim.top ? Tooltip.Direction.BOTTOM :
self.timeout = setTimeout(function () { placement == Tooltip.Direction.RIGHT && position.right + actualWidth > containerDim.width ? Tooltip.Direction.LEFT :
if (self.hoverState == 'in') self.show() placement == Tooltip.Direction.LEFT && position.left - actualWidth < containerDim.left ? Tooltip.Direction.RIGHT :
}, self.options.delay.show)
}
Tooltip.prototype.leave = function (obj) {
var self = obj instanceof this.constructor ?
obj : $(obj.currentTarget).data('bs.' + this.type)
if (!self) {
self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
$(obj.currentTarget).data('bs.' + this.type, self)
}
clearTimeout(self.timeout)
self.hoverState = 'out'
if (!self.options.delay || !self.options.delay.hide) return self.hide()
self.timeout = setTimeout(function () {
if (self.hoverState == 'out') self.hide()
}, self.options.delay.hide)
}
Tooltip.prototype.show = function () {
var e = $.Event('show.bs.' + this.type)
if (this.hasContent() && this.enabled) {
this.$element.trigger(e)
var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
if (e.isDefaultPrevented() || !inDom) return
var that = this
var $tip = this.tip()
var tipId = this.getUID(this.type)
this.setContent()
$tip.attr('id', tipId)
this.$element.attr('aria-describedby', tipId)
if (this.options.animation) $tip.addClass('fade')
var placement = typeof this.options.placement == 'function' ?
this.options.placement.call(this, $tip[0], this.$element[0]) :
this.options.placement
var autoToken = /\s?auto?\s?/i
var autoPlace = autoToken.test(placement)
if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
$tip
.detach()
.css({ top: 0, left: 0, display: 'block' })
.addClass(this.type + '-' + placement)
.data('bs.' + this.type, this)
this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
var pos = this.getPosition()
var actualWidth = $tip[0].offsetWidth
var actualHeight = $tip[0].offsetHeight
if (autoPlace) {
var origPlacement = placement
var $container = this.options.container ? $(this.options.container) : this.$element.parent()
var containerDim = this.getPosition($container)
placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top' :
placement == 'top' && pos.top - actualHeight < containerDim.top ? 'bottom' :
placement == 'right' && pos.right + actualWidth > containerDim.width ? 'left' :
placement == 'left' && pos.left - actualWidth < containerDim.left ? 'right' :
placement placement
$tip $(this._tip)
.removeClass(this.type + '-' + origPlacement) .removeClass(Tooltip._NAME + '-' + originalPlacement)
.addClass(this.type + '-' + placement) .addClass(Tooltip._NAME + '-' + placement)
} }
var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) return placement
this.applyPlacement(calculatedOffset, placement)
var complete = function () {
var prevHoverState = that.hoverState
that.$element.trigger('shown.bs.' + that.type)
that.hoverState = null
if (prevHoverState == 'out') that.leave(that)
} }
$.support.transition && this.$tip.hasClass('fade') ?
$tip /**
.one('bsTransitionEnd', complete) * @param {string} placement
.emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : * @param {Object} position
complete() * @param {number} actualWidth
} * @param {number} actualHeight
* @return {{left: number, top: number}}
* @private
*/
Tooltip.prototype._getCalculatedOffset = function (placement, position, actualWidth, actualHeight) {
return placement == Tooltip.Direction.BOTTOM ? { top: position.top + position.height, left: position.left + position.width / 2 - actualWidth / 2 } :
placement == Tooltip.Direction.TOP ? { top: position.top - actualHeight, left: position.left + position.width / 2 - actualWidth / 2 } :
placement == Tooltip.Direction.LEFT ? { top: position.top + position.height / 2 - actualHeight / 2, left: position.left - actualWidth } :
/* placement == Tooltip.Direction.RIGHT */ { top: position.top + position.height / 2 - actualHeight / 2, left: position.left + position.width }
} }
Tooltip.prototype.applyPlacement = function (offset, placement) {
var $tip = this.tip()
var width = $tip[0].offsetWidth
var height = $tip[0].offsetHeight
// manually read margins because getBoundingClientRect includes difference /**
var marginTop = parseInt($tip.css('margin-top'), 10) * @param {string} placement
var marginLeft = parseInt($tip.css('margin-left'), 10) * @param {Object} position
* @param {number} actualWidth
// we must check for NaN for IE9 * @param {number} actualHeight
if (isNaN(marginTop)) marginTop = 0 * @return {Object}
if (isNaN(marginLeft)) marginLeft = 0 * @private
*/
offset.top = offset.top + marginTop Tooltip.prototype._getViewportAdjustedDelta = function (placement, position, actualWidth, actualHeight) {
offset.left = offset.left + marginLeft
// $.fn.offset doesn't round pixel values
// so we use setOffset directly with our own function B-0
$.offset.setOffset($tip[0], $.extend({
using: function (props) {
$tip.css({
top: Math.round(props.top),
left: Math.round(props.left)
})
}
}, offset), 0)
$tip.addClass('in')
// check to see if placing tip in new offset caused the tip to resize itself
var actualWidth = $tip[0].offsetWidth
var actualHeight = $tip[0].offsetHeight
if (placement == 'top' && actualHeight != height) {
offset.top = offset.top + height - actualHeight
}
var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
if (delta.left) offset.left += delta.left
else offset.top += delta.top
var isVertical = /top|bottom/.test(placement)
var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
$tip.offset(offset)
this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
}
Tooltip.prototype.replaceArrow = function (delta, dimension, isHorizontal) {
this.arrow()
.css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
.css(isHorizontal ? 'top' : 'left', '')
}
Tooltip.prototype.setContent = function () {
var $tip = this.tip()
var title = this.getTitle()
$tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
$tip.removeClass('fade in tooltip-top tooltip-bottom tooltip-left tooltip-right')
}
Tooltip.prototype.hide = function (callback) {
var that = this
var $tip = this.tip()
var e = $.Event('hide.bs.' + this.type)
function complete() {
if (that.hoverState != 'in') $tip.detach()
that.$element
.removeAttr('aria-describedby')
.trigger('hidden.bs.' + that.type)
callback && callback()
}
this.$element.trigger(e)
if (e.isDefaultPrevented()) return
$tip.removeClass('in')
$.support.transition && this.$tip.hasClass('fade') ?
$tip
.one('bsTransitionEnd', complete)
.emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
complete()
this.hoverState = null
return this
}
Tooltip.prototype.fixTitle = function () {
var $e = this.$element
if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
$e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
}
}
Tooltip.prototype.hasContent = function () {
return this.getTitle()
}
Tooltip.prototype.getPosition = function ($element) {
$element = $element || this.$element
var el = $element[0]
var isBody = el.tagName == 'BODY'
var elRect = el.getBoundingClientRect()
if (elRect.width == null) {
// width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
}
var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
return $.extend({}, elRect, scroll, outerDims, elOffset)
}
Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
/* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
}
Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
var delta = { top: 0, left: 0 } var delta = { top: 0, left: 0 }
if (!this.$viewport) return delta
var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 if (!this._viewport) {
var viewportDimensions = this.getPosition(this.$viewport) return delta
}
var viewportPadding = this.config['viewport'] && this.config['viewport']['padding'] || 0
var viewportDimensions = this._getPosition(this._viewport)
if (placement === Tooltip.Direction.RIGHT || placement === Tooltip.Direction.LEFT) {
var topEdgeOffset = position.top - viewportPadding - viewportDimensions.scroll
var bottomEdgeOffset = position.top + viewportPadding - viewportDimensions.scroll + actualHeight
if (/right|left/.test(placement)) {
var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
if (topEdgeOffset < viewportDimensions.top) { // top overflow if (topEdgeOffset < viewportDimensions.top) { // top overflow
delta.top = viewportDimensions.top - topEdgeOffset delta.top = viewportDimensions.top - topEdgeOffset
} else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
} }
} else { } else {
var leftEdgeOffset = pos.left - viewportPadding var leftEdgeOffset = position.left - viewportPadding
var rightEdgeOffset = pos.left + viewportPadding + actualWidth var rightEdgeOffset = position.left + viewportPadding + actualWidth
if (leftEdgeOffset < viewportDimensions.left) { // left overflow if (leftEdgeOffset < viewportDimensions.left) { // left overflow
delta.left = viewportDimensions.left - leftEdgeOffset delta.left = viewportDimensions.left - leftEdgeOffset
} else if (rightEdgeOffset > viewportDimensions.width) { // right overflow } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
} }
@ -1607,699 +3767,814 @@ if (typeof jQuery === 'undefined') {
return delta return delta
} }
Tooltip.prototype.getTitle = function () {
var title
var $e = this.$element
var o = this.options
title = $e.attr('data-original-title') /**
|| (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) * @param {Element=} opt_element
* @return {Object}
* @private
*/
Tooltip.prototype._getPosition = function (opt_element) {
var element = opt_element || this.element
var isBody = element.tagName == 'BODY'
var rect = element.getBoundingClientRect()
var offset = isBody ? { top: 0, left: 0 } : $(element).offset()
var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : this.element.scrollTop }
var outerDims = isBody ? { width: window.innerWidth, height: window.innerHeight } : null
return title return $.extend({}, rect, scroll, outerDims, offset)
}
Tooltip.prototype.getUID = function (prefix) {
do prefix += ~~(Math.random() * 1000000)
while (document.getElementById(prefix))
return prefix
}
Tooltip.prototype.tip = function () {
return (this.$tip = this.$tip || $(this.options.template))
}
Tooltip.prototype.arrow = function () {
return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
}
Tooltip.prototype.enable = function () {
this.enabled = true
}
Tooltip.prototype.disable = function () {
this.enabled = false
}
Tooltip.prototype.toggleEnabled = function () {
this.enabled = !this.enabled
}
Tooltip.prototype.toggle = function (e) {
var self = this
if (e) {
self = $(e.currentTarget).data('bs.' + this.type)
if (!self) {
self = new this.constructor(e.currentTarget, this.getDelegateOptions())
$(e.currentTarget).data('bs.' + this.type, self)
}
}
self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
}
Tooltip.prototype.destroy = function () {
var that = this
clearTimeout(this.timeout)
this.hide(function () {
that.$element.off('.' + that.type).removeData('bs.' + that.type)
})
} }
// TOOLTIP PLUGIN DEFINITION /**
// ========================= * @param {{left: number, top: number}} offset
* @param {string} placement
* @private
*/
Tooltip.prototype._applyCalculatedPlacement = function (offset, placement) {
var tip = this.getTipElement()
var width = tip.offsetWidth
var height = tip.offsetHeight
function Plugin(option) { // manually read margins because getBoundingClientRect includes difference
return this.each(function () { var marginTop = parseInt(tip.style.marginTop, 10)
var $this = $(this) var marginLeft = parseInt(tip.style.marginLeft, 10)
var data = $this.data('bs.tooltip')
var options = typeof option == 'object' && option
if (!data && option == 'destroy') return // we must check for NaN for ie 8/9
if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) if (isNaN(marginTop)) {
if (typeof option == 'string') data[option]() marginTop = 0
}) }
if (isNaN(marginLeft)) {
marginLeft = 0
} }
var old = $.fn.tooltip offset.top = offset.top + marginTop
offset.left = offset.left + marginLeft
$.fn.tooltip = Plugin // $.fn.offset doesn't round pixel values
$.fn.tooltip.Constructor = Tooltip // so we use setOffset directly with our own function B-0
$.offset.setOffset(tip, $.extend({
using: function (props) {
tip.style.top = Math.round(props.top) + 'px'
tip.style.left = Math.round(props.left) + 'px'
}
}, offset), 0)
$(tip).addClass(Tooltip._ClassName.IN)
// check to see if placing tip in new offset caused the tip to resize itself
var actualWidth = tip.offsetWidth
var actualHeight = tip.offsetHeight
if (placement == Tooltip.Direction.TOP && actualHeight != height) {
offset.top = offset.top + height - actualHeight
}
var delta = this._getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
if (delta.left) {
offset.left += delta.left
} else {
offset.top += delta.top
}
var isVertical = placement === Tooltip.Direction.TOP || placement === Tooltip.Direction.BOTTOM
var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
$(tip).offset(offset)
this._replaceArrow(arrowDelta, tip[arrowOffsetPosition], isVertical)
}
// TOOLTIP NO CONFLICT /**
// =================== * @param {number} delta
* @param {number} dimension
* @param {boolean} isHorizontal
* @private
*/
Tooltip.prototype._replaceArrow = function (delta, dimension, isHorizontal) {
var arrow = this.getArrowElement()
$.fn.tooltip.noConflict = function () { arrow.style[isHorizontal ? 'left' : 'top'] = 50 * (1 - delta / dimension) + '%'
$.fn.tooltip = old arrow.style[isHorizontal ? 'top' : 'left'] = ''
}
/**
* @private
*/
Tooltip.prototype._fixTitle = function () {
if (this.element.getAttribute('title') || typeof this.element.getAttribute('data-original-title') != 'string') {
this.element.setAttribute('data-original-title', this.element.getAttribute('title') || '')
this.element.setAttribute('title', '')
}
}
/**
* @param {Event=} opt_event
* @param {Object=} opt_context
* @private
*/
Tooltip.prototype._enter = function (opt_event, opt_context) {
var dataKey = this.getDataKey()
var context = opt_context || $(opt_event.currentTarget).data(dataKey)
if (context && context._tip && context._tip.offsetWidth) {
context._hoverState = Tooltip._HoverState.IN
return
}
if (!context) {
context = new this.constructor(opt_event.currentTarget, this._getDelegateConfig())
$(opt_event.currentTarget).data(dataKey, context)
}
clearTimeout(context._timeout)
context._hoverState = Tooltip._HoverState.IN
if (!context.config['delay'] || !context.config['delay']['show']) {
context['show']()
return
}
context._timeout = setTimeout(function () {
if (context._hoverState == Tooltip._HoverState.IN) {
context['show']()
}
}, context.config['delay']['show'])
}
/**
* @param {Event=} opt_event
* @param {Object=} opt_context
* @private
*/
Tooltip.prototype._leave = function (opt_event, opt_context) {
var dataKey = this.getDataKey()
var context = opt_context || $(opt_event.currentTarget).data(dataKey)
if (!context) {
context = new this.constructor(opt_event.currentTarget, this._getDelegateConfig())
$(opt_event.currentTarget).data(dataKey, context)
}
clearTimeout(context._timeout)
context._hoverState = Tooltip._HoverState.OUT
if (!context.config['delay'] || !context.config['delay']['hide']) {
context['hide']()
return
}
context._timeout = setTimeout(function () {
if (context._hoverState == Tooltip._HoverState.OUT) {
context['hide']()
}
}, context.config['delay']['hide'])
}
/**
* ------------------------------------------------------------------------
* jQuery Interface + noConflict implementaiton
* ------------------------------------------------------------------------
*/
/**
* @const
* @type {Function}
*/
$.fn[Tooltip._NAME] = Tooltip._jQueryInterface
/**
* @const
* @type {Function}
*/
$.fn[Tooltip._NAME]['Constructor'] = Tooltip
/**
* @const
* @type {Function}
*/
$.fn[Tooltip._NAME]['noConflict'] = function () {
$.fn[Tooltip._NAME] = Tooltip._JQUERY_NO_CONFLICT
return this return this
} }
}(jQuery); /** =======================================================================
* Bootstrap: popover.js v4.0.0
/* ========================================================================
* Bootstrap: popover.js v3.3.2
* http://getbootstrap.com/javascript/#popovers * http://getbootstrap.com/javascript/#popovers
* ======================================================================== * ========================================================================
* Copyright 2011-2015 Twitter, Inc. * Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * 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
*
* ========================================================================
*/
+function ($) {
'use strict'; 'use strict';
// POPOVER PUBLIC CLASS DEFINITION
// ===============================
var Popover = function (element, options) { if (!Tooltip) throw new Error('Popover requires tooltip.js')
this.init('popover', element, options)
/**
* 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)
if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
Popover.VERSION = '3.3.2' /**
* @const
* @type {string}
*/
Popover['VERSION'] = '4.0.0'
Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
placement: 'right', /**
trigger: 'click', * @const
content: '', * @type {Object}
template: '<div class="popover" role="tooltip"><div class="popover-arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>' */
Popover['Defaults'] = $.extend({}, $.fn['tooltip']['Constructor']['Defaults'], {
'placement': 'right',
'trigger': 'click',
'content': '',
'template': '<div class="popover" role="tooltip"><div class="popover-arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
}) })
// NOTE: POPOVER EXTENDS tooltip.js /**
// ================================ * @const
* @type {string}
* @private
*/
Popover._NAME = 'popover'
Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
Popover.prototype.constructor = Popover /**
* @const
* @type {string}
* @private
*/
Popover._DATA_KEY = 'bs.popover'
Popover.prototype.getDefaults = function () {
return Popover.DEFAULTS /**
* @const
* @enum {string}
* @private
*/
Popover._Event = {
HIDE : 'hide.bs.popover',
HIDDEN : 'hidden.bs.popover',
SHOW : 'show.bs.popover',
SHOWN : 'shown.bs.popover'
} }
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 * @const
this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text' * @enum {string}
* @private
*/
Popover._ClassName = {
FADE : 'fade',
IN : 'in'
}
/**
* @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 (!data) {
data = new Popover(this, config)
$(this).data(Popover._DATA_KEY, data)
}
if (typeof opt_config === 'string') {
data[opt_config]()
}
})
}
/**
* @return {string}
* @protected
*/
Popover.prototype.getName = function () {
return Popover._NAME
}
/**
* @override
*/
Popover.prototype.getDataKey = function () {
return Popover._DATA_KEY
}
/**
* @override
*/
Popover.prototype.getEventObject = function () {
return Popover._Event
}
/**
* @override
*/
Popover.prototype.getArrowElement = function () {
return (this.arrow = this.arrow || $(this.getTipElement()).find(Popover._Selector.ARROW)[0])
}
/**
* @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]
if (titleElement) {
titleElement[this.config['html'] ? 'innerHTML' : 'innerText'] = title
}
// 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) ](content)
$tip.removeClass('fade popover-top popover-bottom popover-left popover-right in') $(tip)
.removeClass(Popover._ClassName.FADE)
.removeClass(Popover._ClassName.IN)
// IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do for (var direction in Tooltip.Direction) {
// this manually by checking the contents. $(tip).removeClass(Popover._NAME + '-' + Tooltip.Direction[direction])
if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
} }
Popover.prototype.hasContent = 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)
}
Popover.prototype.arrow = function () {
return (this.$arrow = this.$arrow || this.tip().find('.popover-arrow'))
}
Popover.prototype.tip = function () {
if (!this.$tip) this.$tip = $(this.options.template)
return this.$tip
} }
// POPOVER PLUGIN DEFINITION /**
// ========================= * @override
*/
function Plugin(option) { Popover.prototype.isWithContent = function () {
return this.each(function () { return this.getTitle() || this._getContent()
var $this = $(this)
var data = $this.data('bs.popover')
var options = typeof option == 'object' && option
if (!data && option == 'destroy') return
if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
if (typeof option == 'string') data[option]()
})
} }
var old = $.fn.popover
$.fn.popover = Plugin /**
$.fn.popover.Constructor = Popover * @override
*/
Popover.prototype.getTipElement = function () {
return (this.tip = this.tip || $(this.config['template'])[0])
}
// POPOVER NO CONFLICT /**
// =================== * @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'])
}
$.fn.popover.noConflict = function () {
$.fn.popover = old
/**
* ------------------------------------------------------------------------
* jQuery Interface + noConflict implementaiton
* ------------------------------------------------------------------------
*/
/**
* @const
* @type {Function}
*/
$.fn[Popover._NAME] = Popover._jQueryInterface
/**
* @const
* @type {Function}
*/
$.fn[Popover._NAME]['Constructor'] = Popover
/**
* @const
* @type {Function}
*/
$.fn[Popover._NAME]['noConflict'] = function () {
$.fn[Popover._NAME] = Popover._JQUERY_NO_CONFLICT
return this return this
} }
}(jQuery); /** =======================================================================
* Bootstrap: tab.js v4.0.0
/* ========================================================================
* Bootstrap: scrollspy.js v3.3.2
* http://getbootstrap.com/javascript/#scrollspy
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// SCROLLSPY CLASS DEFINITION
// ==========================
function ScrollSpy(element, options) {
var process = $.proxy(this.process, this)
this.$body = $('body')
this.$scrollElement = $(element).is('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
this.$scrollElement.on('scroll.bs.scrollspy', process)
this.refresh()
this.process()
}
ScrollSpy.VERSION = '3.3.2'
ScrollSpy.DEFAULTS = {
offset: 10
}
ScrollSpy.prototype.getScrollHeight = function () {
return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
}
ScrollSpy.prototype.refresh = function () {
var offsetMethod = 'offset'
var offsetBase = 0
if (!$.isWindow(this.$scrollElement[0])) {
offsetMethod = 'position'
offsetBase = this.$scrollElement.scrollTop()
}
this.offsets = []
this.targets = []
this.scrollHeight = this.getScrollHeight()
var self = this
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 () {
self.offsets.push(this[0])
self.targets.push(this[1])
})
}
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 (scrollTop >= maxScroll) {
return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
}
if (activeTarget && scrollTop < offsets[0]) {
this.activeTarget = null
return this.clear()
}
for (i = offsets.length; i--;) {
activeTarget != targets[i]
&& scrollTop >= offsets[i]
&& (!offsets[i + 1] || scrollTop <= offsets[i + 1])
&& this.activate(targets[i])
}
}
ScrollSpy.prototype.activate = function (target) {
this.activeTarget = target
this.clear()
var selector = this.selector +
'[data-target="' + target + '"],' +
this.selector + '[href="' + target + '"]'
var active = $(selector)
.parents('li')
.addClass('active')
if (active.parent('.dropdown-menu').length) {
active = active
.closest('li.dropdown')
.addClass('active')
}
active.trigger('activate.bs.scrollspy')
}
ScrollSpy.prototype.clear = function () {
$(this.selector)
.parentsUntil(this.options.target, '.active')
.removeClass('active')
}
// SCROLLSPY PLUGIN DEFINITION
// ===========================
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.scrollspy')
var options = typeof option == 'object' && option
if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
if (typeof option == 'string') data[option]()
})
}
var old = $.fn.scrollspy
$.fn.scrollspy = Plugin
$.fn.scrollspy.Constructor = ScrollSpy
// SCROLLSPY NO CONFLICT
// =====================
$.fn.scrollspy.noConflict = function () {
$.fn.scrollspy = old
return this
}
// SCROLLSPY DATA-API
// ==================
$(window).on('load.bs.scrollspy.data-api', function () {
$('[data-spy="scroll"]').each(function () {
var $spy = $(this)
Plugin.call($spy, $spy.data())
})
})
}(jQuery);
/* ========================================================================
* Bootstrap: tab.js v3.3.2
* http://getbootstrap.com/javascript/#tabs * http://getbootstrap.com/javascript/#tabs
* ======================================================================== * ========================================================================
* Copyright 2011-2015 Twitter, Inc. * Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * 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
*
* ========================================================================
*/
+function ($) {
'use strict'; 'use strict';
// TAB CLASS DEFINITION /**
// ==================== * Our Tab class.
* @param {Element!} element
* @constructor
*/
var Tab = function (element) { var Tab = function (element) {
this.element = $(element)
/** @type {Element} */
this._element = element
} }
Tab.VERSION = '3.3.2'
Tab.TRANSITION_DURATION = 150 /**
* @const
* @type {string}
*/
Tab['VERSION'] = '4.0.0'
Tab.prototype.show = function () {
var $this = this.element
var $ul = $this.closest('ul:not(.dropdown-menu)')
var selector = $this.data('target')
if (!selector) { /**
selector = $this.attr('href') * @const
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 * @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'
} }
if ($this.parent('li').hasClass('active')) return
var $previous = $ul.find('.active:last a') /**
var hideEvent = $.Event('hide.bs.tab', { * @const
relatedTarget: $this[0] * @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]()
}
}) })
var showEvent = $.Event('show.bs.tab', { }
relatedTarget: $previous[0]
/**
* 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)
if (ulElement) {
var previous = /** @type {Array.<Element>} */ ($.makeArray($(ulElement).find(Tab._Selector.ACTIVE)))
previous = previous[previous.length - 1]
if (previous) {
previous = $(previous).find('a')[0]
}
}
var hideEvent = $.Event(Tab._Event.HIDE, {
relatedTarget: this._element
}) })
$previous.trigger(hideEvent) var showEvent = $.Event(Tab._Event.SHOW, {
$this.trigger(showEvent) relatedTarget: previous
})
if (previous) {
$(previous).trigger(hideEvent)
}
$(this._element).trigger(showEvent)
if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
var $target = $(selector) if (selector) {
var target = $(selector)[0]
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]
})
})
} }
Tab.prototype.activate = function (element, container, callback) { this._activate($(this._element).closest(Tab._Selector.LI)[0], ulElement)
var $active = container.find('> .active')
var transition = callback
&& $.support.transition
&& (($active.length && $active.hasClass('fade')) || !!container.find('> .fade').length)
function next() { var complete = function () {
$active var hiddenEvent = $.Event(Tab._Event.HIDDEN, {
.removeClass('active') relatedTarget: this._element
.find('> .dropdown-menu > .active') })
.removeClass('active')
.end()
.find('[data-toggle="tab"]')
.attr('aria-expanded', false)
element var shownEvent = $.Event(Tab._Event.SHOWN, {
.addClass('active') relatedTarget: previous
.find('[data-toggle="tab"]') })
.attr('aria-expanded', true)
if (transition) { $(previous).trigger(hiddenEvent)
element[0].offsetWidth // reflow for transition $(this._element).trigger(shownEvent)
element.addClass('in') }.bind(this)
if (target) {
this._activate(target, /** @type {Element} */ (target.parentNode), complete)
} else { } else {
element.removeClass('fade') complete()
} }
if (element.parent('.dropdown-menu')) {
element
.closest('li.dropdown')
.addClass('active')
.end()
.find('[data-toggle="tab"]')
.attr('aria-expanded', true)
}
callback && callback()
}
$active.length && transition ?
$active
.one('bsTransitionEnd', next)
.emulateTransitionEnd(Tab.TRANSITION_DURATION) :
next()
$active.removeClass('in')
} }
// TAB PLUGIN DEFINITION /**
// ===================== * @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])
function Plugin(option) { var complete = this._transitionComplete.bind(this, element, active, isTransitioning, opt_callback)
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.tab')
if (!data) $this.data('bs.tab', (data = new Tab(this))) if (active && isTransitioning) {
if (typeof option == 'string') data[option]() $(active)
}) .one(Bootstrap.TRANSITION_END, complete)
.emulateTransitionEnd(Tab._TRANSITION_DURATION)
} else {
complete()
} }
var old = $.fn.tab if (active) {
$(active).removeClass(Tab._ClassName.IN)
$.fn.tab = Plugin }
$.fn.tab.Constructor = Tab }
// TAB NO CONFLICT /**
// =============== * @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)
$.fn.tab.noConflict = function () { var dropdownChild = $(active).find(Tab._Selector.DROPDOWN_ACTIVE_CHILD)[0]
$.fn.tab = old if (dropdownChild) {
$(dropdownChild).removeClass(Tab._ClassName.ACTIVE)
}
var activeToggle = $(active).find(Tab._Selector.DATA_TOGGLE)[0]
if (activeToggle) {
activeToggle.setAttribute('aria-expanded', false)
}
}
$(element).addClass(Tab._ClassName.ACTIVE)
var elementToggle = $(element).find(Tab._Selector.DATA_TOGGLE)[0]
if (elementToggle) {
elementToggle.setAttribute('aria-expanded', true)
}
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)
}
elementToggle = $(element).find(Tab._Selector.DATA_TOGGLE)[0]
if (elementToggle) {
elementToggle.setAttribute('aria-expanded', true)
}
}
if (opt_callback) {
opt_callback()
}
}
/**
* ------------------------------------------------------------------------
* jQuery Interface + noConflict implementaiton
* ------------------------------------------------------------------------
*/
/**
* @const
* @type {Function}
*/
$.fn[Tab._NAME] = Tab._jQueryInterface
/**
* @const
* @type {Function}
*/
$.fn[Tab._NAME]['Constructor'] = Tab
/**
* @const
* @type {Function}
*/
$.fn[Tab._NAME]['noConflict'] = function () {
$.fn[Tab._NAME] = Tab._JQUERY_NO_CONFLICT
return this return this
} }
// TAB DATA-API // TAB DATA-API
// ============ // ============
var clickHandler = function (e) { var clickHandler = function (e) {
e.preventDefault() e.preventDefault()
Plugin.call($(this), 'show') Tab._jQueryInterface.call($(this), 'show')
} }
$(document) $(document)
.on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler) .on('click.bs.tab.data-api', Tab._Selector.DATA_TOGGLE, clickHandler)
.on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
}(jQuery);
/* ========================================================================
* Bootstrap: affix.js v3.3.2
* 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 =
this.unpin =
this.pinnedOffset = null
this.checkPosition()
}
Affix.VERSION = '3.3.2'
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 = $('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);

File diff suppressed because one or more lines are too long

BIN
dist/js/bootstrap.min.js.gz vendored Normal file

Binary file not shown.

6
dist/js/npm.js vendored
View File

@ -1,13 +1,13 @@
// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.
require('../../js/transition.js') require('../../js/util.js')
require('../../node_modules/mq4-hover-shim/dist/browser/mq4-hover-shim.js')
require('../../js/alert.js') require('../../js/alert.js')
require('../../js/button.js') require('../../js/button.js')
require('../../js/carousel.js') require('../../js/carousel.js')
require('../../js/collapse.js') require('../../js/collapse.js')
require('../../js/dropdown.js') require('../../js/dropdown.js')
require('../../js/modal.js') require('../../js/modal.js')
require('../../js/scrollspy.js')
require('../../js/tooltip.js') require('../../js/tooltip.js')
require('../../js/popover.js') require('../../js/popover.js')
require('../../js/scrollspy.js')
require('../../js/tab.js') require('../../js/tab.js')
require('../../js/affix.js')

View File

@ -1,94 +1,260 @@
/* ======================================================================== /** =======================================================================
* Bootstrap: alert.js v3.3.2 * Bootstrap: alert.js v4.0.0
* http://getbootstrap.com/javascript/#alerts * http://getbootstrap.com/javascript/#alerts
* ======================================================================== * ========================================================================
* Copyright 2011-2015 Twitter, Inc. * Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * 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
*
* ========================================================================
*/
+function ($) {
'use strict'; 'use strict';
// ALERT CLASS DEFINITION
// ======================
var dismiss = '[data-dismiss="alert"]' /**
var Alert = function (el) { * Our Alert class.
$(el).on('click', dismiss, this.close) * @param {Element=} opt_element
* @constructor
*/
var Alert = function (opt_element) {
if (opt_element) {
$(opt_element).on('click', Alert._DISMISS_SELECTOR, Alert._handleDismiss(this))
} }
Alert.VERSION = '3.3.2'
Alert.TRANSITION_DURATION = 150
Alert.prototype.close = function (e) {
var $this = $(this)
var selector = $this.attr('data-target')
if (!selector) {
selector = $this.attr('href')
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
}
var $parent = $(selector)
if (e) e.preventDefault()
if (!$parent.length) {
$parent = $this.closest('.alert')
}
$parent.trigger(e = $.Event('close.bs.alert'))
if (e.isDefaultPrevented()) return
$parent.removeClass('in')
function removeElement() {
// detach from parent, fire event then clean up data
$parent.detach().trigger('closed.bs.alert').remove()
}
$.support.transition && $parent.hasClass('fade') ?
$parent
.one('bsTransitionEnd', removeElement)
.emulateTransitionEnd(Alert.TRANSITION_DURATION) :
removeElement()
} }
// ALERT PLUGIN DEFINITION /**
// ======================= * @const
* @type {string}
*/
Alert['VERSION'] = '4.0.0'
function Plugin(option) {
/**
* @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]
/**
* @const
* @enum {string}
* @private
*/
Alert._Event = {
CLOSE : 'close.bs.alert',
CLOSED : 'closed.bs.alert'
}
/**
* @const
* @enum {string}
* @private
*/
Alert._ClassName = {
ALERT : 'alert',
FADE : 'fade',
IN : 'in'
}
/**
* 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 () { return this.each(function () {
var $this = $(this) var $this = $(this)
var data = $this.data('bs.alert') var data = $this.data(Alert._DATA_KEY)
if (!data) $this.data('bs.alert', (data = new Alert(this))) if (!data) {
if (typeof option == 'string') data[option].call($this) data = new Alert(this)
$this.data(Alert._DATA_KEY, data)
}
if (opt_config === 'close') {
data[opt_config](this)
}
}) })
} }
var old = $.fn.alert
$.fn.alert = Plugin /**
$.fn.alert.Constructor = Alert * Close the alert component
* @param {Alert} alertInstance
* @return {Function}
* @private
*/
Alert._handleDismiss = function (alertInstance) {
return function (event) {
if (event) {
event.preventDefault()
}
alertInstance['close'](this)
// ALERT NO CONFLICT }
// =================
$.fn.alert.noConflict = function () {
$.fn.alert = old
return this
} }
// ALERT DATA-API /**
// ============== * Close the alert component
* @param {Element} element
*/
Alert.prototype['close'] = function (element) {
var rootElement = this._getRootElement(element)
var customEvent = this._triggerCloseEvent(rootElement)
$(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) if (customEvent.isDefaultPrevented()) return
}(jQuery); 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]
}
if (!parent) {
parent = $(element).closest('.' + Alert._ClassName.ALERT)[0]
}
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
}
/**
* 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
}
$(element)
.one(Bootstrap.TRANSITION_END, this._destroyElement.bind(this, element))
.emulateTransitionEnd(Alert._TRANSITION_DURATION)
}
/**
* clean up any lingering jquery data and kill element
* @private
*/
Alert.prototype._destroyElement = function (element) {
$(element)
.detach()
.trigger(Alert._Event.CLOSED)
.remove()
}
/**
* ------------------------------------------------------------------------
* jQuery Interface + noConflict implementaiton
* ------------------------------------------------------------------------
*/
/**
* @const
* @type {Function}
*/
$.fn[Alert._NAME] = Alert._jQueryInterface
/**
* @const
* @type {Function}
*/
$.fn[Alert._NAME]['Constructor'] = Alert
/**
* @return {Function}
*/
$.fn[Alert._NAME]['noConflict'] = function () {
$.fn[Alert._NAME] = Alert._JQUERY_NO_CONFLICT
return Alert._jQueryInterface
}
/**
* ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/
$(document).on('click.bs.alert.data-api', Alert._DISMISS_SELECTOR, Alert._handleDismiss(new Alert))

View File

@ -1,116 +1,207 @@
/* ======================================================================== /** =======================================================================
* Bootstrap: button.js v3.3.2 * Bootstrap: button.js v4.0.0
* http://getbootstrap.com/javascript/#buttons * http://getbootstrap.com/javascript/#buttons
* ======================================================================== * ========================================================================
* Copyright 2011-2015 Twitter, Inc. * Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * 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
*
* ========================================================================
*/
+function ($) {
'use strict'; 'use strict';
// BUTTON PUBLIC CLASS DEFINITION
// ==============================
var Button = function (element, options) { /**
this.$element = $(element) * Our Button class.
this.options = $.extend({}, Button.DEFAULTS, options) * @param {Element!} element
this.isLoading = false * @constructor
} */
var Button = function (element) {
Button.VERSION = '3.3.2' /** @private {Element} */
this._element = element
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 = 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)
}
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') && this.$element.hasClass('active')) changed = false
else $parent.find('.active').removeClass('active')
}
if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
} else {
this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
}
if (changed) this.$element.toggleClass('active')
} }
// BUTTON PLUGIN DEFINITION /**
// ======================== * @const
* @type {string}
*/
Button['VERSION'] = '4.0.0'
function Plugin(option) {
/**
* @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 () { return this.each(function () {
var $this = $(this) var data = $(this).data(Button._DATA_KEY)
var data = $this.data('bs.button')
var options = typeof option == 'object' && option
if (!data) $this.data('bs.button', (data = new Button(this, options))) if (!data) {
data = new Button(this)
$(this).data(Button._DATA_KEY, data)
}
if (option == 'toggle') data.toggle() if (opt_config === 'toggle') {
else if (option) data.setState(option) data[opt_config]()
}
}) })
} }
var old = $.fn.button
$.fn.button = Plugin /**
$.fn.button.Constructor = Button * 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)
}
}
}
if (triggerChangeEvent) {
input.checked = !$(this._element).hasClass(Button._ClassName.ACTIVE)
$(this._element).trigger('change')
}
}
} else {
this._element.setAttribute('aria-pressed', !$(this._element).hasClass(Button._ClassName.ACTIVE))
}
if (triggerChangeEvent) {
$(this._element).toggleClass(Button._ClassName.ACTIVE)
}
}
// BUTTON NO CONFLICT /**
// ================== * ------------------------------------------------------------------------
* jQuery Interface + noConflict implementaiton
* ------------------------------------------------------------------------
*/
$.fn.button.noConflict = function () { /**
$.fn.button = old * @const
* @type {Function}
*/
$.fn[Button._NAME] = Button._jQueryInterface
/**
* @const
* @type {Function}
*/
$.fn[Button._NAME]['Constructor'] = Button
/**
* @const
* @type {Function}
*/
$.fn[Button._NAME]['noConflict'] = function () {
$.fn[Button._NAME] = Button._JQUERY_NO_CONFLICT
return this return this
} }
// BUTTON DATA-API /**
// =============== * ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/
$(document) $(document)
.on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { .on('click.bs.button.data-api', Button._Selector.DATA_TOGGLE_CARROT, function (event) {
var $btn = $(e.target) event.preventDefault()
if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
Plugin.call($btn, 'toggle')
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))
})
}(jQuery); var button = event.target
if (!$(button).hasClass(Button._ClassName.BUTTON)) {
button = $(button).closest(Button._Selector.BUTTON)
}
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))
})

View File

@ -1,237 +1,576 @@
/* ======================================================================== /** =======================================================================
* Bootstrap: carousel.js v3.3.2 * Bootstrap: carousel.js v4.0.0
* http://getbootstrap.com/javascript/#carousel * http://getbootstrap.com/javascript/#carousel
* ======================================================================== * ========================================================================
* Copyright 2011-2015 Twitter, Inc. * Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * 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
*
* ========================================================================
*/
+function ($) {
'use strict'; 'use strict';
// CAROUSEL CLASS DEFINITION
// =========================
var Carousel = function (element, options) { /**
this.$element = $(element) * Our carousel class.
this.$indicators = this.$element.find('.carousel-indicators') * @param {Element!} element
this.options = options * @param {Object=} opt_config
this.paused = * @constructor
this.sliding = */
this.interval = var Carousel = function (element, opt_config) {
this.$active =
this.$items = null
this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)) /** @private {Element} */
this._element = $(element)[0]
this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element /** @private {Element} */
.on('mouseenter.bs.carousel', $.proxy(this.pause, this)) this._indicatorsElement = $(this._element).find(Carousel._Selector.INDICATORS)[0]
.on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
}
Carousel.VERSION = '3.3.2' /** @private {?Object} */
this._config = opt_config || null
Carousel.TRANSITION_DURATION = 600 /** @private {boolean} */
this._isPaused = false
Carousel.DEFAULTS = { /** @private {boolean} */
interval: 5000, this._isSliding = false
pause: 'hover',
wrap: true,
keyboard: true
}
Carousel.prototype.keydown = function (e) { /** @private {?number} */
if (/input|textarea/i.test(e.target.tagName)) return this._interval = null
switch (e.which) {
case 37: this.prev(); break
case 39: this.next(); break
default: return
}
e.preventDefault() /** @private {?Element} */
} this._activeElement = null
Carousel.prototype.cycle = function (e) { /** @private {?Array} */
e || (this.paused = false) this._items = null
this.interval && clearInterval(this.interval) this._addEventListeners()
this.options.interval
&& !this.paused
&& (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
return this
}
Carousel.prototype.getItemIndex = function (item) {
this.$items = item.parent().children('.carousel-item')
return this.$items.index(item || this.$active)
}
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)
}
Carousel.prototype.to = function (pos) {
var that = this
var activeIndex = this.getItemIndex(this.$active = this.$element.find('.carousel-item.active'))
if (pos > (this.$items.length - 1) || pos < 0) return
if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
if (activeIndex == pos) return this.pause().cycle()
return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
}
Carousel.prototype.pause = function (e) {
e || (this.paused = true)
if (this.$element.find('.next, .prev').length && $.support.transition) {
this.$element.trigger($.support.transition.end)
this.cycle(true)
}
this.interval = clearInterval(this.interval)
return this
}
Carousel.prototype.next = function () {
if (this.sliding) return
return this.slide('next')
}
Carousel.prototype.prev = function () {
if (this.sliding) return
return this.slide('prev')
}
Carousel.prototype.slide = function (type, next) {
var $active = this.$element.find('.carousel-item.active')
var $next = next || this.getItemForDirection(type, $active)
var isCycling = this.interval
var direction = type == 'next' ? 'left' : 'right'
var that = this
if ($next.hasClass('active')) return (this.sliding = false)
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
isCycling && this.pause()
if (this.$indicators.length) {
this.$indicators.find('.active').removeClass('active')
var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
$nextIndicator && $nextIndicator.addClass('active')
}
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)
}
isCycling && this.cycle()
return this
} }
// CAROUSEL PLUGIN DEFINITION /**
// ========================== * @const
* @type {string}
*/
Carousel['VERSION'] = '4.0.0'
function Plugin(option) {
/**
* @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 () { return this.each(function () {
var $this = $(this) var data = $(this).data(Carousel._DATA_KEY)
var data = $this.data('bs.carousel') var config = $.extend({}, Carousel['Defaults'], $(this).data(), typeof opt_config == 'object' && opt_config)
var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) var action = typeof opt_config == 'string' ? opt_config : config.slide
var action = typeof option == 'string' ? option : options.slide
if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) if (!data) {
if (typeof option == 'number') data.to(option) data = new Carousel(this, config)
else if (action) data[action]() $(this).data(Carousel._DATA_KEY, data)
else if (options.interval) data.pause().cycle() }
if (typeof opt_config == 'number') {
data.to(opt_config)
} else if (action) {
data[action]()
} else if (config.interval) {
data['pause']()
data['cycle']()
}
}) })
} }
var old = $.fn.carousel
$.fn.carousel = Plugin /**
$.fn.carousel.Constructor = Carousel * Click handler for data api
* @param {Event} event
* @this {Element}
* @private
*/
Carousel._dataApiClickHandler = function (event) {
var selector = Bootstrap.getSelectorFromElement(this)
if (!selector) {
// CAROUSEL NO CONFLICT return
// ====================
$.fn.carousel.noConflict = function () {
$.fn.carousel = old
return this
} }
var target = $(selector)[0]
// CAROUSEL DATA-API if (!target || !$(target).hasClass(Carousel._ClassName.CAROUSEL)) {
// ================= return
}
var clickHandler = function (e) { var config = $.extend({}, $(target).data(), $(this).data())
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
Plugin.call($target, options) var slideIndex = this.getAttribute('data-slide-to')
if (slideIndex) {
config.interval = false
}
Carousel._jQueryInterface.call($(target), config)
if (slideIndex) { if (slideIndex) {
$target.data('bs.carousel').to(slideIndex) $(target).data(Carousel._DATA_KEY).to(slideIndex)
} }
e.preventDefault() event.preventDefault()
} }
/**
* Advance the carousel to the next slide
*/
Carousel.prototype['next'] = function () {
if (!this._isSliding) {
this._slide(Carousel._Direction.NEXT)
}
}
/**
* Return the carousel to the previous slide
*/
Carousel.prototype['prev'] = function () {
if (!this._isSliding) {
this._slide(Carousel._Direction.PREVIOUS)
}
}
/**
* Pause the carousel cycle
* @param {Event=} opt_event
*/
Carousel.prototype['pause'] = function (opt_event) {
if (!opt_event) {
this._isPaused = true
}
if ($(this._element).find(Carousel._Selector.NEXT_PREV)[0] && Bootstrap.transition) {
$(this._element).trigger(Bootstrap.transition.end)
this['cycle'](true)
}
clearInterval(this._interval)
this._interval = null
}
/**
* Cycle to the next carousel item
* @param {Event|boolean=} opt_event
*/
Carousel.prototype['cycle'] = function (opt_event) {
if (!opt_event) {
this._isPaused = false
}
if (this._interval) {
clearInterval(this._interval)
this._interval = null
}
if (this._config['interval'] && !this._isPaused) {
this._interval = setInterval(this['next'].bind(this), this._config['interval'])
}
}
/**
* @return {Object}
*/
Carousel.prototype['getConfig'] = function () {
return this._config
}
/**
* 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]
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
}
if (activeIndex == index) {
this['pause']()
this['cycle']()
return
}
var direction = index > activeIndex ?
Carousel._Direction.NEXT :
Carousel._Direction.PREVIOUS
this._slide(direction, this._items[index])
}
/**
* 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))
}
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))
}
}
/**
* 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
}
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]
}
/**
* 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)
return slideEvent
}
/**
* 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)
var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)]
if (nextIndicator) {
$(nextIndicator).addClass(Carousel._ClassName.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 directionalClassName = direction == Carousel._Direction.NEXT ?
Carousel._ClassName.LEFT :
Carousel._ClassName.RIGHT
if (nextElement && $(nextElement).hasClass(Carousel._ClassName.ACTIVE)) {
this._isSliding = false
return
}
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
}
this._isSliding = true
if (isCycling) {
this['pause']()
}
this._setActiveIndicatorElement(nextElement)
var slidEvent = $.Event(Carousel._Event.SLID, { relatedTarget: nextElement, direction: directionalClassName })
if (Bootstrap.transition && $(this._element).hasClass(Carousel._ClassName.SLIDE)) {
$(nextElement).addClass(direction)
Bootstrap.reflow(nextElement)
$(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)
}
if (isCycling) {
this['cycle']()
}
}
/**
* ------------------------------------------------------------------------
* jQuery Interface + noConflict implementaiton
* ------------------------------------------------------------------------
*/
/**
* @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
}
/**
* ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/
$(document) $(document)
.on('click.bs.carousel.data-api', '[data-slide]', clickHandler) .on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', Carousel._dataApiClickHandler)
.on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
$(window).on('load', function () { $(window).on('load', function () {
$('[data-ride="carousel"]').each(function () { $('[data-ride="carousel"]').each(function () {
var $carousel = $(this) var $carousel = $(this)
Plugin.call($carousel, $carousel.data()) Carousel._jQueryInterface.call($carousel, /** @type {Object} */ ($carousel.data()))
}) })
}) })
}(jQuery);

View File

@ -1,211 +1,455 @@
/* ======================================================================== /** =======================================================================
* Bootstrap: collapse.js v3.3.2 * Bootstrap: collapse.js v4.0.0
* http://getbootstrap.com/javascript/#collapse * http://getbootstrap.com/javascript/#collapse
* ======================================================================== * ========================================================================
* Copyright 2011-2015 Twitter, Inc. * Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * 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
*
* ========================================================================
*/
+function ($) {
'use strict'; 'use strict';
// COLLAPSE PUBLIC CLASS DEFINITION
// ================================
var Collapse = function (element, options) { /**
this.$element = $(element) * Our collapse class.
this.options = $.extend({}, Collapse.DEFAULTS, options) * @param {Element!} element
this.$trigger = $(this.options.trigger).filter('[href="#' + element.id + '"], [data-target="#' + element.id + '"]') * @param {Object=} opt_config
this.transitioning = null * @constructor
*/
var Collapse = function (element, opt_config) {
if (this.options.parent) { /** @private {Element} */
this.$parent = this.getParent() this._element = element
} else {
this.addAriaAndCollapsedClass(this.$element, this.$trigger) /** @private {Object} */
this._config = $.extend({}, Collapse['Defaults'], opt_config)
/** @private {Element} */
this._trigger = typeof this._config['trigger'] == 'string' ?
$(this._config['trigger'])[0] : this._config['trigger']
/** @private {boolean} */
this._isTransitioning = false
/** @private {?Element} */
this._parent = this._config['parent'] ? this._getParent() : null
if (!this._config['parent']) {
this._addAriaAndCollapsedClass(this._element, this._trigger)
} }
if (this.options.toggle) this.toggle() if (this._config['toggle']) {
this['toggle']()
} }
Collapse.VERSION = '3.3.2'
Collapse.TRANSITION_DURATION = 350
Collapse.DEFAULTS = {
toggle: true,
trigger: '[data-toggle="collapse"]'
}
Collapse.prototype.dimension = function () {
var hasWidth = this.$element.hasClass('width')
return hasWidth ? 'width' : 'height'
}
Collapse.prototype.show = function () {
if (this.transitioning || this.$element.hasClass('in')) return
var activesData
var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
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
if (actives && actives.length) {
Plugin.call(actives, 'hide')
activesData || actives.data('bs.collapse', null)
}
var dimension = this.dimension()
this.$element
.removeClass('collapse')
.addClass('collapsing')[dimension](0)
.attr('aria-expanded', true)
this.$trigger
.removeClass('collapsed')
.attr('aria-expanded', true)
this.transitioning = 1
var complete = function () {
this.$element
.removeClass('collapsing')
.addClass('collapse in')[dimension]('')
this.transitioning = 0
this.$element
.trigger('shown.bs.collapse')
}
if (!$.support.transition) return complete.call(this)
var scrollSize = $.camelCase(['scroll', dimension].join('-'))
this.$element
.one('bsTransitionEnd', $.proxy(complete, this))
.emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
}
Collapse.prototype.hide = function () {
if (this.transitioning || !this.$element.hasClass('in')) return
var startEvent = $.Event('hide.bs.collapse')
this.$element.trigger(startEvent)
if (startEvent.isDefaultPrevented()) return
var dimension = this.dimension()
this.$element[dimension](this.$element[dimension]())[0].offsetHeight
this.$element
.addClass('collapsing')
.removeClass('collapse in')
.attr('aria-expanded', false)
this.$trigger
.addClass('collapsed')
.attr('aria-expanded', false)
this.transitioning = 1
var complete = function () {
this.transitioning = 0
this.$element
.removeClass('collapsing')
.addClass('collapse')
.trigger('hidden.bs.collapse')
}
if (!$.support.transition) return complete.call(this)
this.$element
[dimension](0)
.one('bsTransitionEnd', $.proxy(complete, this))
.emulateTransitionEnd(Collapse.TRANSITION_DURATION)
}
Collapse.prototype.toggle = function () {
this[this.$element.hasClass('in') ? 'hide' : 'show']()
}
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()
}
Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
var isOpen = $element.hasClass('in')
$element.attr('aria-expanded', isOpen)
$trigger
.toggleClass('collapsed', !isOpen)
.attr('aria-expanded', isOpen)
}
function getTargetFromTrigger($trigger) {
var href
var target = $trigger.attr('data-target')
|| (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
return $(target)
} }
// COLLAPSE PLUGIN DEFINITION /**
// ========================== * @const
* @type {string}
*/
Collapse['VERSION'] = '4.0.0'
function Plugin(option) {
/**
* @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 () { return this.each(function () {
var $this = $(this) var $this = $(this)
var data = $this.data('bs.collapse') var data = $this.data(Collapse._DATA_KEY)
var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) var config = $.extend({}, Collapse['Defaults'], $this.data(), typeof opt_config == 'object' && opt_config)
if (!data && options.toggle && option == 'show') options.toggle = false if (!data && config['toggle'] && opt_config == 'show') {
if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) config['toggle'] = false
if (typeof option == 'string') data[option]() }
if (!data) {
data = new Collapse(this, config)
$this.data(Collapse._DATA_KEY, data)
}
if (typeof opt_config == 'string') {
data[opt_config]()
}
}) })
} }
var old = $.fn.collapse
$.fn.collapse = Plugin /**
$.fn.collapse.Constructor = Collapse * Function for getting target element from element
* @return {Element}
* @private
*/
Collapse._getTargetFromElement = function (element) {
var selector = Bootstrap.getSelectorFromElement(element)
return selector ? $(selector)[0] : null
}
// COLLAPSE NO CONFLICT /**
// ==================== * 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']()
}
}
$.fn.collapse.noConflict = function () {
$.fn.collapse = old /**
* Show's the collapsing element
*/
Collapse.prototype['show'] = function () {
if (this._isTransitioning || $(this._element).hasClass(Collapse._ClassName.IN)) {
return
}
var activesData, actives
if (this._parent) {
actives = $.makeArray($(Collapse._Selector.ACTIVES))
if (!actives.length) {
actives = null
}
}
if (actives) {
activesData = $(actives).data(Collapse._DATA_KEY)
if (activesData && activesData._isTransitioning) {
return
}
}
var startEvent = $.Event(Collapse._Event.SHOW)
$(this._element).trigger(startEvent)
if (startEvent.isDefaultPrevented()) {
return
}
if (actives) {
Collapse._jQueryInterface.call($(actives), 'hide')
if (!activesData) {
$(actives).data(Collapse._DATA_KEY, null)
}
}
var dimension = this._getDimension()
$(this._element)
.removeClass(Collapse._ClassName.COLLAPSE)
.addClass(Collapse._ClassName.COLLAPSING)
this._element.style[dimension] = 0
this._element.setAttribute('aria-expanded', true)
if (this._trigger) {
$(this._trigger).removeClass(Collapse._ClassName.COLLAPSED)
this._trigger.setAttribute('aria-expanded', true)
}
this['setTransitioning'](true)
var complete = function () {
$(this._element)
.removeClass(Collapse._ClassName.COLLAPSING)
.addClass(Collapse._ClassName.COLLAPSE)
.addClass(Collapse._ClassName.IN)
this._element.style[dimension] = ''
this['setTransitioning'](false)
$(this._element).trigger(Collapse._Event.SHOWN)
}.bind(this)
if (!Bootstrap.transition) {
complete()
return
}
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
}
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)
}
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)
this._element.style[dimension] = 0
if (!Bootstrap.transition) {
return complete()
}
$(this._element)
.one(Bootstrap.TRANSITION_END, complete)
.emulateTransitionEnd(Collapse._TRANSITION_DURATION)
}
/**
* @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.<Element>} */ ($.makeArray($(parent).find(selector)))
for (var i = 0; i < elements.length; i++) {
this._addAriaAndCollapsedClass(Collapse._getTargetFromElement(elements[i]), elements[i])
}
return parent
}
/**
* 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)
if (trigger) {
trigger.setAttribute('aria-expanded', isOpen)
$(trigger).toggleClass(Collapse._ClassName.COLLAPSED, !isOpen)
}
}
}
/**
* ------------------------------------------------------------------------
* jQuery Interface + noConflict implementaiton
* ------------------------------------------------------------------------
*/
/**
* @const
* @type {Function}
*/
$.fn[Collapse._NAME] = Collapse._jQueryInterface
/**
* @const
* @type {Function}
*/
$.fn[Collapse._NAME]['Constructor'] = Collapse
/**
* @const
* @type {Function}
*/
$.fn[Collapse._NAME]['noConflict'] = function () {
$.fn[Collapse._NAME] = Collapse._JQUERY_NO_CONFLICT
return this return this
} }
// COLLAPSE DATA-API /**
// ================= * ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/
$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (event) {
var $this = $(this) event.preventDefault()
if (!$this.attr('data-target')) e.preventDefault() var target = Collapse._getTargetFromElement(this)
var $target = getTargetFromTrigger($this) var data = $(target).data(Collapse._DATA_KEY)
var data = $target.data('bs.collapse') var config = data ? 'toggle' : $.extend({}, $(this).data(), { trigger: this })
var option = data ? 'toggle' : $.extend({}, $this.data(), { trigger: this })
Plugin.call($target, option) Collapse._jQueryInterface.call($(target), config)
}) })
}(jQuery);

View File

@ -1,161 +1,322 @@
/* ======================================================================== /** =======================================================================
* Bootstrap: dropdown.js v3.3.2 * Bootstrap: dropdown.js v4.0.0
* http://getbootstrap.com/javascript/#dropdowns * http://getbootstrap.com/javascript/#dropdown
* ======================================================================== * ========================================================================
* Copyright 2011-2015 Twitter, Inc. * Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * 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
*
* ========================================================================
*/
+function ($) {
'use strict'; 'use strict';
// DROPDOWN CLASS DEFINITION
// =========================
var backdrop = '.dropdown-backdrop' /**
var toggle = '[data-toggle="dropdown"]' * Our dropdown class.
* @param {Element!} element
* @constructor
*/
var Dropdown = function (element) { var Dropdown = function (element) {
$(element).on('click.bs.dropdown', this.toggle) $(element).on('click.bs.dropdown', this['toggle'])
} }
Dropdown.VERSION = '3.3.2'
Dropdown.prototype.toggle = function (e) { /**
var $this = $(this) * @const
* @type {string}
*/
Dropdown['VERSION'] = '4.0.0'
if ($this.is('.disabled, :disabled')) return
var $parent = getParent($this) /**
var isActive = $parent.hasClass('open') * @const
* @type {string}
* @private
*/
Dropdown._NAME = 'dropdown'
clearMenus()
if (!isActive) { /**
if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { * @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)
}
})
}
/**
* @param {Event=} opt_event
* @private
*/
Dropdown._clearMenus = function (opt_event) {
if (opt_event && opt_event.which == 3) {
return
}
var backdrop = $(Dropdown._Selector.BACKDROP)[0]
if (backdrop) {
backdrop.parentNode.removeChild(backdrop)
}
var toggles = /** @type {Array.<Element>} */ ($.makeArray($(Dropdown._Selector.DATA_TOGGLE)))
for (var i = 0; i < toggles.length; i++) {
var parent = Dropdown._getParentFromElement(toggles[i])
var relatedTarget = { 'relatedTarget': toggles[i] }
if (!$(parent).hasClass(Dropdown._ClassName.OPEN)) {
continue
}
var hideEvent = $.Event(Dropdown._Event.HIDE, relatedTarget)
$(parent).trigger(hideEvent)
if (hideEvent.isDefaultPrevented()) {
continue
}
toggles[i].setAttribute('aria-expanded', 'false')
$(parent)
.removeClass(Dropdown._ClassName.OPEN)
.trigger(Dropdown._Event.HIDDEN, relatedTarget)
}
}
/**
* @param {Element} element
* @return {Element}
* @private
*/
Dropdown._getParentFromElement = function (element) {
var selector = Bootstrap.getSelectorFromElement(element)
if (selector) {
var parent = $(selector)[0]
}
return /** @type {Element} */ (parent || element.parentNode)
}
/**
* @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
}
event.preventDefault()
event.stopPropagation()
if (this.disabled || $(this).hasClass(Dropdown._ClassName.DISABLED)) {
return
}
var parent = Dropdown._getParentFromElement(this)
var isActive = $(parent).hasClass(Dropdown._ClassName.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
}
var items = $.makeArray($(Dropdown._Selector.VISIBLE_ITEMS))
items = items.filter(function (item) {
return item.offsetWidth || item.offsetHeight
})
if (!items.length) {
return
}
var index = items.indexOf(event.target)
if (event.which == 38 && index > 0) index-- // up
if (event.which == 40 && index < items.length - 1) index++ // down
if (!~index) index = 0
items[index].focus()
}
/**
* Toggles the dropdown
* @this {Element}
* @return {boolean|undefined}
*/
Dropdown.prototype['toggle'] = function () {
if (this.disabled || $(this).hasClass(Dropdown._ClassName.DISABLED)) {
return
}
var parent = Dropdown._getParentFromElement(this)
var isActive = $(parent).hasClass(Dropdown._ClassName.OPEN)
Dropdown._clearMenus()
if (isActive) {
return false
}
if ('ontouchstart' in document.documentElement && !$(parent).closest(Dropdown._Selector.NAVBAR_NAV).length) {
// if mobile we use a backdrop because click events don't delegate // if mobile we use a backdrop because click events don't delegate
$('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus) var dropdown = document.createElement('div')
dropdown.className = Dropdown._ClassName.BACKDROP
this.parentNode.insertBefore(this, dropdown)
$(dropdown).on('click', Dropdown._clearMenus)
} }
var relatedTarget = { relatedTarget: this } var relatedTarget = { 'relatedTarget': this }
$parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget)) var showEvent = $.Event(Dropdown._Event.SHOW, relatedTarget)
if (e.isDefaultPrevented()) return $(parent).trigger(showEvent)
$this if (showEvent.isDefaultPrevented()) {
.trigger('focus') return
.attr('aria-expanded', 'true')
$parent
.toggleClass('open')
.trigger('shown.bs.dropdown', relatedTarget)
} }
this.focus()
this.setAttribute('aria-expanded', 'true')
$(parent).toggleClass(Dropdown._ClassName.OPEN)
$(parent).trigger(Dropdown._Event.SHOWN, relatedTarget)
return false return false
} }
Dropdown.prototype.keydown = function (e) {
if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
var $this = $(this) /**
* ------------------------------------------------------------------------
* jQuery Interface + noConflict implementaiton
* ------------------------------------------------------------------------
*/
e.preventDefault() /**
e.stopPropagation() * @const
* @type {Function}
if ($this.is('.disabled, :disabled')) return */
$.fn[Dropdown._NAME] = Dropdown._jQueryInterface
var $parent = getParent($this)
var isActive = $parent.hasClass('open')
if ((!isActive && e.which != 27) || (isActive && e.which == 27)) {
if (e.which == 27) $parent.find(toggle).trigger('focus')
return $this.trigger('click')
}
var desc = ' li:not(.divider):visible a'
var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc)
if (!$items.length) 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
$items.eq(index).trigger('focus')
}
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 }
if (!$parent.hasClass('open')) return
$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
if (e.isDefaultPrevented()) return
$this.attr('aria-expanded', 'false')
$parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
})
}
function getParent($this) {
var selector = $this.attr('data-target')
if (!selector) {
selector = $this.attr('href')
selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
}
var $parent = selector && $(selector)
return $parent && $parent.length ? $parent : $this.parent()
}
// DROPDOWN PLUGIN DEFINITION /**
// ========================== * @const
* @type {Function}
function Plugin(option) { */
return this.each(function () { $.fn[Dropdown._NAME]['Constructor'] = Dropdown
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)
})
}
var old = $.fn.dropdown
$.fn.dropdown = Plugin
$.fn.dropdown.Constructor = Dropdown
// DROPDOWN NO CONFLICT /**
// ==================== * @const
* @type {Function}
$.fn.dropdown.noConflict = function () { */
$.fn.dropdown = old $.fn[Dropdown._NAME]['noConflict'] = function () {
$.fn[Dropdown._NAME] = Dropdown._JQUERY_NO_CONFLICT
return this return this
} }
// APPLY TO STANDARD DROPDOWN ELEMENTS /**
// =================================== * ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/
$(document) $(document)
.on('click.bs.dropdown.data-api', clearMenus) .on('click.bs.dropdown.data-api', Dropdown._clearMenus)
.on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) .on('click.bs.dropdown.data-api', Dropdown._Selector.FORM_CHILD, function (e) { e.stopPropagation() })
.on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) .on('click.bs.dropdown.data-api', Dropdown._Selector.DATA_TOGGLE, Dropdown.prototype['toggle'])
.on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) .on('keydown.bs.dropdown.data-api', Dropdown._Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler)
.on('keydown.bs.dropdown.data-api', '[role="menu"]', Dropdown.prototype.keydown) .on('keydown.bs.dropdown.data-api', Dropdown._Selector.ROLE_MENU, Dropdown._dataApiKeydownHandler)
.on('keydown.bs.dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown) .on('keydown.bs.dropdown.data-api', Dropdown._Selector.ROLE_LISTBOX, Dropdown._dataApiKeydownHandler)
}(jQuery);

6
js/externs/bootstrap.js vendored Normal file
View File

@ -0,0 +1,6 @@
jQuery.event.prototype.handleObj = function () {}
jQuery.event.prototype.handleObj.handler = function () {}
$.event.special = function () {}
$.event.trueHover = true
$.offset = {}
$.offset.setOffset = function (a,b,c) {}

2159
js/externs/jQuery.js Normal file
View File

@ -0,0 +1,2159 @@
/*
* 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:
* <code>var elt = /** @type {Element} * / (foo.get(0));</code>
*
* @see http://api.jquery.com/
* @externs
*/
/**
* @typedef {(Window|Document|Element|Array.<Element>|string|jQuery|
* NodeList)}
*/
var jQuerySelector;
/** @typedef {function(...)|Array.<function(...)>} */
var jQueryCallback;
/** @typedef {
{
accepts: (Object.<string, string>|undefined),
async: (?boolean|undefined),
beforeSend: (function(jQuery.jqXHR, (jQueryAjaxSettings|Object.<string, *>))|undefined),
cache: (?boolean|undefined),
complete: (function(jQuery.jqXHR, string)|undefined),
contents: (Object.<string, RegExp>|undefined),
contentType: (?string|undefined),
context: (Object.<?, ?>|jQueryAjaxSettings|undefined),
converters: (Object.<string, Function>|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.<number, function()>|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.<Element>|jQuery|string|
* function())=} arg1
* @param {(Element|jQuery|Document|
* Object.<string, (string|function(!jQuery.event=))>)=} arg2
* @return {!jQuery}
*/
function jQuery(arg1, arg2) {}
/**
* @constructor
* @extends {jQuery}
* @param {(jQuerySelector|Element|Object|Array.<Element>|jQuery|string|
* function())=} arg1
* @param {(Element|jQuery|Document|
* Object.<string, (string|function(!jQuery.event=))>)=} arg2
* @return {!jQuery}
*/
function $(arg1, arg2) {}
/**
* @param {(jQuerySelector|Array.<Element>|string|jQuery)} arg1
* @param {Element=} context
* @return {!jQuery}
* @nosideeffects
*/
jQuery.prototype.add = function(arg1, context) {};
/**
* @param {(jQuerySelector|Array.<Element>|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.<Element>|jQuery)=} content
* @return {!jQuery}
*/
jQuery.prototype.after = function(arg1, content) {};
/**
* @param {(string|jQueryAjaxSettings|Object.<string,*>)} arg1
* @param {(jQueryAjaxSettings|Object.<string, *>)=} settings
* @return {jQuery.jqXHR}
*/
jQuery.ajax = function(arg1, settings) {};
/**
* @param {(string|jQueryAjaxSettings|Object.<string, *>)} arg1
* @param {(jQueryAjaxSettings|Object.<string, *>)=} settings
* @return {jQuery.jqXHR}
*/
$.ajax = function(arg1, settings) {};
/**
* @param {function(!jQuery.event,XMLHttpRequest,(jQueryAjaxSettings|Object.<string, *>))} handler
* @return {!jQuery}
*/
jQuery.prototype.ajaxComplete = function(handler) {};
/**
* @param {function(!jQuery.event,jQuery.jqXHR,(jQueryAjaxSettings|Object.<string, *>),*)} handler
* @return {!jQuery}
*/
jQuery.prototype.ajaxError = function(handler) {};
/**
* @param {(string|function((jQueryAjaxSettings|Object.<string, *>),(jQueryAjaxSettings|Object.<string, *>),jQuery.jqXHR))} dataTypes
* @param {function((jQueryAjaxSettings|Object.<string, *>),(jQueryAjaxSettings|Object.<string, *>),jQuery.jqXHR)=} handler
*/
jQuery.ajaxPrefilter = function(dataTypes, handler) {};
/**
* @param {(string|function((jQueryAjaxSettings|Object.<string, *>),(jQueryAjaxSettings|Object.<string, *>),jQuery.jqXHR))} dataTypes
* @param {function((jQueryAjaxSettings|Object.<string, *>),(jQueryAjaxSettings|Object.<string, *>),jQuery.jqXHR)=} handler
*/
$.ajaxPrefilter = function(dataTypes, handler) {};
/**
* @param {function(!jQuery.event,jQuery.jqXHR,(jQueryAjaxSettings|Object.<string, *>))} handler
* @return {!jQuery}
*/
jQuery.prototype.ajaxSend = function(handler) {};
/** @const {jQueryAjaxSettings|Object.<string, *>} */
jQuery.ajaxSettings;
/** @const {jQueryAjaxSettings|Object.<string, *>} */
$.ajaxSettings = {};
/** @type {Object.<string, boolean>} */
jQuery.ajaxSettings.flatOptions = {};
/** @type {Object.<string, boolean>} */
$.ajaxSettings.flatOptions = {};
/** @type {boolean} */
jQuery.ajaxSettings.processData;
/** @type {boolean} */
$.ajaxSettings.processData;
/** @type {Object.<string, string>} */
jQuery.ajaxSettings.responseFields = {};
/** @type {Object.<string, string>} */
$.ajaxSettings.responseFields = {};
/** @param {jQueryAjaxSettings|Object.<string, *>} options */
jQuery.ajaxSetup = function(options) {};
/** @param {jQueryAjaxSettings|Object.<string, *>} 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.<string, *>), ?)} handler
* @return {!jQuery}
*/
jQuery.prototype.ajaxSuccess = function(handler) {};
/**
* @deprecated Please use .addBack(selector) instead.
* @return {!jQuery}
* @nosideeffects
*/
jQuery.prototype.andSelf = function() {};
/**
* @param {Object.<string,*>} properties
* @param {(string|number|function()|Object.<string,*>)=} arg2
* @param {(string|function())=} easing
* @param {function()=} complete
* @return {!jQuery}
*/
jQuery.prototype.animate = function(properties, arg2, easing, complete) {};
/**
* @param {(string|Element|Array.<Element>|jQuery|function(number,string))} arg1
* @param {...(string|Element|Array.<Element>|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.<string,*>)} 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.<Element>|jQuery)=} content
* @return {!jQuery}
*/
jQuery.prototype.before = function(arg1, content) {};
/**
* @param {(string|Object.<string, function(!jQuery.event=)>)} arg1
* @param {(Object.<string, *>|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.<string, *>)=} 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.<string, *>)=} 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.<string, *>)=} 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.<string,*>)} arg1
* @param {(string|number|function(number,*))=} arg2
* @return {(string|!jQuery)}
*/
jQuery.prototype.css = function(arg1, arg2) {};
/** @type {Object.<string, *>} */
jQuery.cssHooks;
/** @type {Object.<string, *>} */
$.cssHooks;
/**
* @param {Element} elem
* @param {string=} key
* @param {*=} value
* @return {*}
*/
jQuery.data = function(elem, key, value) {};
/**
* @param {(string|Object.<string, *>)=} 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.<string, *>)=} 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.<string,*>)} arg2
* @param {(function(!jQuery.event=)|Object.<string, *>)=} 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.<string, *>)} 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.<string, *>} */
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.<string, *>} */
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.<string, *>)=} arg1
* @param {function(!jQuery.event=)=} handler
* @return {!jQuery}
*/
jQuery.prototype.focus = function(arg1, handler) {};
/**
* @param {(function(!jQuery.event=)|Object.<string, *>)} arg1
* @param {function(!jQuery.event=)=} handler
* @return {!jQuery}
*/
jQuery.prototype.focusin = function(arg1, handler) {};
/**
* @param {(function(!jQuery.event=)|Object.<string, *>)} 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,*>|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.<Element>)}
* @nosideeffects
*/
jQuery.prototype.get = function(index) {};
/**
* @param {string} url
* @param {(Object.<string,*>|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.<string,*>|
* function(Object.<string,*>,string,jQuery.jqXHR))=} data
* @param {function(Object.<string,*>,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.<string,*>|
* function(Object.<string,*>,string,jQuery.jqXHR))=} data
* @param {function(Object.<string,*>,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.<string, *>)=} arg1
* @param {function(!jQuery.event=)=} handler
* @return {!jQuery}
*/
jQuery.prototype.keydown = function(arg1, handler) {};
/**
* @param {(function(!jQuery.event=)|Object.<string, *>)=} arg1
* @param {function(!jQuery.event=)=} handler
* @return {!jQuery}
*/
jQuery.prototype.keypress = function(arg1, handler) {};
/**
* @param {(function(!jQuery.event=)|Object.<string, *>)=} 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, *>|string)} arg1
* @param {(function(!jQuery.event=)|Object.<string,*>|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.<string, *>)} 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.<string, *>)} 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.<string, *>)=} arg1
* @param {function(!jQuery.event=)=} handler
* @return {!jQuery}
*/
jQuery.prototype.mousedown = function(arg1, handler) {};
/**
* @param {(function(!jQuery.event=)|Object.<string, *>)=} arg1
* @param {function(!jQuery.event=)=} handler
* @return {!jQuery}
*/
jQuery.prototype.mouseenter = function(arg1, handler) {};
/**
* @param {(function(!jQuery.event=)|Object.<string, *>)=} arg1
* @param {function(!jQuery.event=)=} handler
* @return {!jQuery}
*/
jQuery.prototype.mouseleave = function(arg1, handler) {};
/**
* @param {(function(!jQuery.event=)|Object.<string, *>)=} arg1
* @param {function(!jQuery.event=)=} handler
* @return {!jQuery}
*/
jQuery.prototype.mousemove = function(arg1, handler) {};
/**
* @param {(function(!jQuery.event=)|Object.<string, *>)=} arg1
* @param {function(!jQuery.event=)=} handler
* @return {!jQuery}
*/
jQuery.prototype.mouseout = function(arg1, handler) {};
/**
* @param {(function(!jQuery.event=)|Object.<string, *>)=} arg1
* @param {function(!jQuery.event=)=} handler
* @return {!jQuery}
*/
jQuery.prototype.mouseover = function(arg1, handler) {};
/**
* @param {(function(!jQuery.event=)|Object.<string, *>)=} 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.<Element>|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.<string,*>)=} 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.<string,*>)} arg1
* @param {*=} selector
* @param {*=} data
* @param {function(!jQuery.event=)=} handler
* @return {!jQuery}
*/
jQuery.prototype.on = function(arg1, selector, data, handler) {};
/**
* @param {(string|Object.<string,*>)} 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.<string, *>|Array.<Object.<string, *>>)} obj
* @param {boolean=} traditional
* @return {string}
*/
jQuery.param = function(obj, traditional) {};
/**
* @param {(Object.<string, *>|Array.<Object.<string, *>>)} 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.<Element>}
*/
jQuery.parseHTML = function(data, context, keepScripts) {};
/**
* @param {string} data
* @param {(Element|boolean)=} context
* @param {boolean=} keepScripts
* @return {Array.<Element>}
*/
$.parseHTML = function(data, context, keepScripts) {};
/**
* @param {string} json
* @return {string|number|Object.<string, *>|Array.<?>|boolean}
*/
jQuery.parseJSON = function(json) {};
/**
* @param {string} json
* @return {Object.<string, *>}
*/
$.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,*>|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,*>|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.<string,*>)} 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.<Element>} elements
* @param {string=} name
* @param {Array.<*>=} args
* @return {!jQuery}
*/
jQuery.prototype.pushStack = function(elements, name, args) {};
/**
* @param {(string|Array.<function()>|function(function()))=} queueName
* @param {(Array.<function()>|function(function()))=} arg2
* @return {(Array.<Element>|!jQuery)}
*/
jQuery.prototype.queue = function(queueName, arg2) {};
/**
* @param {Element} elem
* @param {string=} queueName
* @param {(Array.<function()>|function())=} arg3
* @return {(Array.<Element>|!jQuery)}
*/
jQuery.queue = function(elem, queueName, arg3) {};
/**
* @param {Element} elem
* @param {string=} queueName
* @param {(Array.<function()>|function())=} arg3
* @return {(Array.<Element>|!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.<string>)=} 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.<string, *>)=} arg1
* @param {function(!jQuery.event=)=} handler
* @return {!jQuery}
*/
jQuery.prototype.resize = function(arg1, handler) {};
/**
* @param {(function(!jQuery.event=)|Object.<string, *>)=} 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.<string, *>)=} arg1
* @param {function(!jQuery.event=)=} handler
* @return {!jQuery}
*/
jQuery.prototype.select = function(arg1, handler) {};
/**
* @return {string}
* @nosideeffects
*/
jQuery.prototype.serialize = function() {};
/**
* @return {Array.<Object.<string, *>>}
* @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,*>|string|number)=} optionsOrDuration
* @param {(function()|string)=} completeOrEasing
* @param {function()=} complete
* @return {!jQuery}
*/
jQuery.prototype.slideDown =
function(optionsOrDuration, completeOrEasing, complete) {};
/**
* @param {(Object.<string,*>|string|number)=} optionsOrDuration
* @param {(function()|string)=} completeOrEasing
* @param {function()=} complete
* @return {!jQuery}
*/
jQuery.prototype.slideToggle =
function(optionsOrDuration, completeOrEasing, complete) {};
/**
* @param {(Object.<string,*>|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.<string, *>)=} arg1
* @param {function(!jQuery.event=)=} handler
* @return {!jQuery}
*/
jQuery.prototype.submit = function(arg1, handler) {};
/** @type {Object.<string, *>}
* @deprecated Please try to use feature detection instead.
*/
jQuery.support;
/** @type {Object.<string, *>}
* @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.<Element>}
* @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.<string,*>|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.<string,*>)=} arg2
* @param {function(!jQuery.event=)=} handler
* @return {!jQuery}
*/
jQuery.prototype.undelegate = function(arg1, arg2, handler) {};
/**
* @param {Array.<Element>} arr
* @return {Array.<Element>}
*/
jQuery.unique = function(arr) {};
/**
* @param {Array.<Element>} arr
* @return {Array.<Element>}
*/
$.unique = function(arr) {};
/**
* @deprecated Please use .on( "unload", handler ) instead.
* @param {(function(!jQuery.event=)|Object.<string, *>)} arg1
* @param {function(!jQuery.event=)=} handler
* @return {!jQuery}
*/
jQuery.prototype.unload = function(arg1, handler) {};
/** @return {!jQuery} */
jQuery.prototype.unwrap = function() {};
/**
* @param {(string|Array.<string>|function(number,*))=} arg1
* @return {(string|number|Array.<string>|!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) {};

View File

@ -1,4 +0,0 @@
$(document).on('mq4hsChange', function (e) {
'use strict';
$(document.documentElement).toggleClass('bs-true-hover', e.trueHover);
});

View File

@ -1,324 +1,598 @@
/* ======================================================================== /** =======================================================================
* Bootstrap: modal.js v3.3.2 * Bootstrap: modal.js v4.0.0
* http://getbootstrap.com/javascript/#modals * http://getbootstrap.com/javascript/#modal
* ======================================================================== * ========================================================================
* Copyright 2011-2015 Twitter, Inc. * Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * 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
*
* ========================================================================
*/
+function ($) {
'use strict'; 'use strict';
// MODAL CLASS DEFINITION
// ======================
var Modal = function (element, options) { /**
this.options = options * Our modal class.
this.$body = $(document.body) * @param {Element} element
this.$element = $(element) * @param {Object} config
this.$backdrop = * @constructor
this.isShown = null */
this.scrollbarWidth = 0 var Modal = function (element, config) {
/** @private {Object} */
this._config = config
/** @private {Element} */
this._element = element
/** @private {Element} */
this._backdrop = null
/** @private {boolean} */
this._isShown = false
/** @private {boolean} */
this._isBodyOverflowing = false
/** @private {number} */
this._scrollbarWidth = 0
if (this.options.remote) {
this.$element
.find('.modal-content')
.load(this.options.remote, $.proxy(function () {
this.$element.trigger('loaded.bs.modal')
}, this))
}
} }
Modal.VERSION = '3.3.2'
Modal.TRANSITION_DURATION = 300 /**
Modal.BACKDROP_TRANSITION_DURATION = 150 * @const
* @type {string}
*/
Modal['VERSION'] = '4.0.0'
Modal.DEFAULTS = {
backdrop: true, /**
keyboard: true, * @const
show: true * @type {Object}
*/
Modal['Defaults'] = {
'backdrop' : true,
'keyboard' : true,
'show' : true
} }
Modal.prototype.toggle = function (_relatedTarget) {
return this.isShown ? this.hide() : this.show(_relatedTarget) /**
* @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'
} }
Modal.prototype.show = function (_relatedTarget) {
var that = this
var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
this.$element.trigger(e) /**
* @const
if (this.isShown || e.isDefaultPrevented()) return * @enum {string}
* @private
this.isShown = true */
Modal._ClassName = {
this.checkScrollbar() BACKDROP : 'modal-backdrop',
this.setScrollbar() OPEN : 'modal-open',
this.$body.addClass('modal-open') FADE : 'fade',
IN : 'in'
this.escape()
this.resize()
this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
this.backdrop(function () {
var transition = $.support.transition && that.$element.hasClass('fade')
if (!that.$element.parent().length) {
that.$element.appendTo(that.$body) // don't move modals dom position
} }
that.$element
.show()
.scrollTop(0)
if (that.options.backdrop) that.adjustBackdrop() /**
that.adjustDialog() * @const
* @enum {string}
if (transition) { * @private
that.$element[0].offsetWidth // force reflow */
Modal._Selector = {
DIALOG : '.modal-dialog',
DATA_TOGGLE : '[data-toggle="modal"]',
DATA_DISMISS : '[data-dismiss="modal"]',
SCROLLBAR_MEASURER : 'modal-scrollbar-measure'
} }
that.$element
.addClass('in')
.attr('aria-hidden', false)
that.enforceFocus()
var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) /**
* 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)
transition ? if (!data) {
that.$element.find('.modal-dialog') // wait for modal to slide in data = new Modal(this, config)
.one('bsTransitionEnd', function () { $(this).data(Modal._DATA_KEY, data)
that.$element.trigger('focus').trigger(e) }
})
.emulateTransitionEnd(Modal.TRANSITION_DURATION) : if (typeof opt_config == 'string') {
that.$element.trigger('focus').trigger(e) data[opt_config](opt_relatedTarget)
} else if (config['show']) {
data['show'](opt_relatedTarget)
}
}) })
} }
Modal.prototype.hide = function (e) {
if (e) e.preventDefault()
e = $.Event('hide.bs.modal') /**
* @param {Element} relatedTarget
*/
Modal.prototype['toggle'] = function (relatedTarget) {
return this._isShown ? this['hide']() : this['show'](relatedTarget)
}
this.$element.trigger(e)
if (!this.isShown || e.isDefaultPrevented()) return /**
* @param {Element} relatedTarget
*/
Modal.prototype['show'] = function (relatedTarget) {
var showEvent = $.Event(Modal._Event.SHOW, { relatedTarget: relatedTarget })
this.isShown = false $(this._element).trigger(showEvent)
this.escape() if (this._isShown || showEvent.isDefaultPrevented()) {
this.resize() return
}
this._isShown = true
this._checkScrollbar()
this._setScrollbar()
$(document.body).addClass(Modal._ClassName.OPEN)
this._escape()
this._resize()
$(this._element).on('click.dismiss.bs.modal', Modal._Selector.DATA_DISMISS, this['hide'].bind(this))
this._showBackdrop(this._showElement.bind(this, relatedTarget))
}
/**
* @param {Event} event
*/
Modal.prototype['hide'] = function (event) {
if (event) {
event.preventDefault()
}
var hideEvent = $.Event(Modal._Event.HIDE)
$(this._element).trigger(hideEvent)
if (!this._isShown || hideEvent.isDefaultPrevented()) {
return
}
this._isShown = false
this._escape()
this._resize()
$(document).off('focusin.bs.modal') $(document).off('focusin.bs.modal')
this.$element $(this._element).removeClass(Modal._ClassName.IN)
.removeClass('in') this._element.setAttribute('aria-hidden', true)
.attr('aria-hidden', true)
.off('click.dismiss.bs.modal')
$.support.transition && this.$element.hasClass('fade') ? $(this._element).off('click.dismiss.bs.modal')
this.$element
.one('bsTransitionEnd', $.proxy(this.hideModal, this)) if (Bootstrap.transition && $(this._element).hasClass(Modal._ClassName.FADE)) {
.emulateTransitionEnd(Modal.TRANSITION_DURATION) : $(this._element)
this.hideModal() .one(Bootstrap.TRANSITION_END, this._hideModal.bind(this))
.emulateTransitionEnd(Modal._TRANSITION_DURATION)
} else {
this._hideModal()
}
} }
Modal.prototype.enforceFocus = function () {
/**
* @param {Element} relatedTarget
* @private
*/
Modal.prototype._showElement = function (relatedTarget) {
var transition = Bootstrap.transition && $(this._element).hasClass(Modal._ClassName.FADE)
if (!this._element.parentNode || this._element.parentNode.nodeType != Node.ELEMENT_NODE) {
document.body.appendChild(this._element) // don't move modals dom position
}
this._element.style.display = 'block'
this._element.scrollTop = 0
if (this._config['backdrop']) {
this._adjustBackdrop()
}
if (transition) {
Bootstrap.reflow(this._element)
}
$(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()
}
}
/**
* @private
*/
Modal.prototype._enforceFocus = function () {
$(document) $(document)
.off('focusin.bs.modal') // guard against infinite focus loop .off('focusin.bs.modal') // guard against infinite focus loop
.on('focusin.bs.modal', $.proxy(function (e) { .on('focusin.bs.modal', function (e) {
if (this.$element[0] !== e.target && !this.$element.has(e.target).length) { if (this._element !== e.target && !$(this._element).has(e.target).length) {
this.$element.trigger('focus') this._element.focus()
} }
}, this)) }.bind(this))
} }
Modal.prototype.escape = function () {
if (this.isShown && this.options.keyboard) { /**
this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) { * @private
e.which == 27 && this.hide() */
}, this)) Modal.prototype._escape = function () {
} else if (!this.isShown) { if (this._isShown && this._config['keyboard']) {
this.$element.off('keydown.dismiss.bs.modal') $(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.resize = function () {
if (this.isShown) { /**
$(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this)) * @private
*/
Modal.prototype._resize = function () {
if (this._isShown) {
$(window).on('resize.bs.modal', this._handleUpdate.bind(this))
} else { } else {
$(window).off('resize.bs.modal') $(window).off('resize.bs.modal')
} }
} }
Modal.prototype.hideModal = function () {
var that = this /**
this.$element.hide() * @private
this.backdrop(function () { */
that.$body.removeClass('modal-open') Modal.prototype._hideModal = function () {
that.resetAdjustments() this._element.style.display = 'none'
that.resetScrollbar() this._showBackdrop(function () {
that.$element.trigger('hidden.bs.modal') $(document.body).removeClass(Modal._ClassName.OPEN)
}) this._resetAdjustments()
this._resetScrollbar()
$(this._element).trigger(Modal._Event.HIDDEN)
}.bind(this))
} }
Modal.prototype.removeBackdrop = function () {
this.$backdrop && this.$backdrop.remove() /**
this.$backdrop = null * @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' : ''
if (this.isShown && this.options.backdrop) { /**
var doAnimate = $.support.transition && animate * @param {Function} callback
* @private
*/
Modal.prototype._showBackdrop = function (callback) {
var animate = $(this._element).hasClass(Modal._ClassName.FADE) ? Modal._ClassName.FADE : ''
this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />') if (this._isShown && this._config['backdrop']) {
.prependTo(this.$element) var doAnimate = Bootstrap.transition && animate
.on('click.dismiss.bs.modal', $.proxy(function (e) {
if (e.target !== e.currentTarget) return
this.options.backdrop == 'static'
? this.$element[0].focus.call(this.$element[0])
: this.hide.call(this)
}, this))
if (doAnimate) this.$backdrop[0].offsetWidth // force reflow this._backdrop = document.createElement('div')
this._backdrop.className = Modal._ClassName.BACKDROP
this.$backdrop.addClass('in') if (animate) {
$(this._backdrop).addClass(animate)
}
if (!callback) return $(this._element).prepend(this._backdrop)
doAnimate ? $(this._backdrop).on('click.dismiss.bs.modal', function (event) {
this.$backdrop if (event.target !== event.currentTarget) return
.one('bsTransitionEnd', callback) this._config['backdrop'] === 'static'
.emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : ? this._element.focus()
: this['hide']()
}.bind(this))
if (doAnimate) {
Bootstrap.reflow(this._backdrop)
}
$(this._backdrop).addClass(Modal._ClassName.IN)
if (!callback) {
return
}
if (!doAnimate) {
callback() callback()
return
}
} else if (!this.isShown && this.$backdrop) { $(this._backdrop)
this.$backdrop.removeClass('in') .one(Bootstrap.TRANSITION_END, callback)
.emulateTransitionEnd(Modal._BACKDROP_TRANSITION_DURATION)
} else if (!this._isShown && this._backdrop) {
$(this._backdrop).removeClass(Modal._ClassName.IN)
var callbackRemove = function () { var callbackRemove = function () {
that.removeBackdrop() this._removeBackdrop()
callback && callback() if (callback) {
callback()
} }
$.support.transition && this.$element.hasClass('fade') ? }.bind(this)
this.$backdrop
.one('bsTransitionEnd', callbackRemove) if (Bootstrap.transition && $(this._element).hasClass(Modal._ClassName.FADE)) {
.emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : $(this._backdrop)
.one(Bootstrap.TRANSITION_END, callbackRemove)
.emulateTransitionEnd(Modal._BACKDROP_TRANSITION_DURATION)
} else {
callbackRemove() callbackRemove()
}
} else if (callback) { } else if (callback) {
callback() callback()
} }
} }
// these following methods are used to handle overflowing modals
Modal.prototype.handleUpdate = function () { /**
if (this.options.backdrop) this.adjustBackdrop() * ------------------------------------------------------------------------
this.adjustDialog() * 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()
} }
Modal.prototype.adjustBackdrop = function () { /**
this.$backdrop * @private
.css('height', 0) */
.css('height', this.$element[0].scrollHeight) 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'
} }
Modal.prototype.adjustDialog = function () {
var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
this.$element.css({ /**
paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '', * @private
paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : '' */
}) 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.resetAdjustments = function () { if (this._isBodyOverflowing && !isModalOverflowing) {
this.$element.css({ this._element.style.paddingRight = this._scrollbarWidth + 'px'
paddingLeft: '', }
paddingRight: ''
})
} }
Modal.prototype.checkScrollbar = function () {
this.bodyIsOverflowing = document.body.scrollHeight > document.documentElement.clientHeight /**
this.scrollbarWidth = this.measureScrollbar() * @private
*/
Modal.prototype._resetAdjustments = function () {
this._element.style.paddingLeft = ''
this._element.style.paddingRight = ''
} }
Modal.prototype.setScrollbar = function () {
var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) /**
if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth) * @private
*/
Modal.prototype._checkScrollbar = function () {
this._isBodyOverflowing = document.body.scrollHeight > document.documentElement.clientHeight
this._scrollbarWidth = this._getScrollbarWidth()
} }
Modal.prototype.resetScrollbar = function () {
this.$body.css('padding-right', '') /**
* @private
*/
Modal.prototype._setScrollbar = function () {
var bodyPadding = parseInt(($(document.body).css('padding-right') || 0), 10)
if (this._isBodyOverflowing) {
document.body.style.paddingRight = bodyPadding + this._scrollbarWidth + 'px'
}
} }
Modal.prototype.measureScrollbar = function () { // thx walsh
/**
* @private
*/
Modal.prototype._resetScrollbar = function () {
document.body.style.paddingRight = ''
}
/**
* @private
*/
Modal.prototype._getScrollbarWidth = function () { // thx walsh
var scrollDiv = document.createElement('div') var scrollDiv = document.createElement('div')
scrollDiv.className = 'modal-scrollbar-measure' scrollDiv.className = Modal._Selector.SCROLLBAR_MEASURER
this.$body.append(scrollDiv) document.body.appendChild(scrollDiv)
var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
this.$body[0].removeChild(scrollDiv) document.body.removeChild(scrollDiv)
return scrollbarWidth return scrollbarWidth
} }
// MODAL PLUGIN DEFINITION /**
// ======================= * ------------------------------------------------------------------------
* jQuery Interface + noConflict implementaiton
* ------------------------------------------------------------------------
*/
function Plugin(option, _relatedTarget) { /**
return this.each(function () { * @const
var $this = $(this) * @type {Function}
var data = $this.data('bs.modal') */
var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) $.fn[Modal._NAME] = Modal._jQueryInterface
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
$.fn.modal = Plugin
$.fn.modal.Constructor = Modal
// MODAL NO CONFLICT /**
// ================= * @const
* @type {Function}
*/
$.fn[Modal._NAME]['Constructor'] = Modal
$.fn.modal.noConflict = function () {
$.fn.modal = old /**
* @const
* @type {Function}
*/
$.fn[Modal._NAME]['noConflict'] = function () {
$.fn[Modal._NAME] = Modal._JQUERY_NO_CONFLICT
return this return this
} }
// MODAL DATA-API /**
// ============== * ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/
$(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { $(document).on('click.bs.modal.data-api', Modal._Selector.DATA_TOGGLE, function (event) {
var $this = $(this) var selector = Bootstrap.getSelectorFromElement(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() if (selector) {
var target = $(selector)[0]
}
$target.one('show.bs.modal', function (showEvent) { var config = $(target).data(Modal._DATA_KEY) ? 'toggle' : $.extend({}, $(target).data(), $(this).data())
if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
$target.one('hidden.bs.modal', function () { if (this.tagName == 'A') {
$this.is(':visible') && $this.trigger('focus') event.preventDefault()
}
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._jQueryInterface.call($(target), config, this)
}) })
})
Plugin.call($target, option, this)
})
}(jQuery);

View File

@ -1,113 +1,283 @@
/* ======================================================================== /** =======================================================================
* Bootstrap: popover.js v3.3.2 * Bootstrap: popover.js v4.0.0
* http://getbootstrap.com/javascript/#popovers * http://getbootstrap.com/javascript/#popovers
* ======================================================================== * ========================================================================
* Copyright 2011-2015 Twitter, Inc. * Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * 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
*
* ========================================================================
*/
+function ($) {
'use strict'; 'use strict';
// POPOVER PUBLIC CLASS DEFINITION
// ===============================
var Popover = function (element, options) { if (!Tooltip) throw new Error('Popover requires tooltip.js')
this.init('popover', element, options)
/**
* 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)
if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
Popover.VERSION = '3.3.2' /**
* @const
* @type {string}
*/
Popover['VERSION'] = '4.0.0'
Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
placement: 'right', /**
trigger: 'click', * @const
content: '', * @type {Object}
template: '<div class="popover" role="tooltip"><div class="popover-arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>' */
Popover['Defaults'] = $.extend({}, $.fn['tooltip']['Constructor']['Defaults'], {
'placement': 'right',
'trigger': 'click',
'content': '',
'template': '<div class="popover" role="tooltip"><div class="popover-arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
}) })
// NOTE: POPOVER EXTENDS tooltip.js /**
// ================================ * @const
* @type {string}
* @private
*/
Popover._NAME = 'popover'
Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
Popover.prototype.constructor = Popover /**
* @const
* @type {string}
* @private
*/
Popover._DATA_KEY = 'bs.popover'
Popover.prototype.getDefaults = function () {
return Popover.DEFAULTS /**
* @const
* @enum {string}
* @private
*/
Popover._Event = {
HIDE : 'hide.bs.popover',
HIDDEN : 'hidden.bs.popover',
SHOW : 'show.bs.popover',
SHOWN : 'shown.bs.popover'
} }
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 * @const
this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text' * @enum {string}
* @private
*/
Popover._ClassName = {
FADE : 'fade',
IN : 'in'
}
/**
* @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 (!data) {
data = new Popover(this, config)
$(this).data(Popover._DATA_KEY, data)
}
if (typeof opt_config === 'string') {
data[opt_config]()
}
})
}
/**
* @return {string}
* @protected
*/
Popover.prototype.getName = function () {
return Popover._NAME
}
/**
* @override
*/
Popover.prototype.getDataKey = function () {
return Popover._DATA_KEY
}
/**
* @override
*/
Popover.prototype.getEventObject = function () {
return Popover._Event
}
/**
* @override
*/
Popover.prototype.getArrowElement = function () {
return (this.arrow = this.arrow || $(this.getTipElement()).find(Popover._Selector.ARROW)[0])
}
/**
* @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]
if (titleElement) {
titleElement[this.config['html'] ? 'innerHTML' : 'innerText'] = title
}
// 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) ](content)
$tip.removeClass('fade popover-top popover-bottom popover-left popover-right in') $(tip)
.removeClass(Popover._ClassName.FADE)
.removeClass(Popover._ClassName.IN)
// IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do for (var direction in Tooltip.Direction) {
// this manually by checking the contents. $(tip).removeClass(Popover._NAME + '-' + Tooltip.Direction[direction])
if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
} }
Popover.prototype.hasContent = 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)
}
Popover.prototype.arrow = function () {
return (this.$arrow = this.$arrow || this.tip().find('.popover-arrow'))
}
Popover.prototype.tip = function () {
if (!this.$tip) this.$tip = $(this.options.template)
return this.$tip
} }
// POPOVER PLUGIN DEFINITION /**
// ========================= * @override
*/
function Plugin(option) { Popover.prototype.isWithContent = function () {
return this.each(function () { return this.getTitle() || this._getContent()
var $this = $(this)
var data = $this.data('bs.popover')
var options = typeof option == 'object' && option
if (!data && option == 'destroy') return
if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
if (typeof option == 'string') data[option]()
})
} }
var old = $.fn.popover
$.fn.popover = Plugin /**
$.fn.popover.Constructor = Popover * @override
*/
Popover.prototype.getTipElement = function () {
return (this.tip = this.tip || $(this.config['template'])[0])
}
// POPOVER NO CONFLICT /**
// =================== * @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'])
}
$.fn.popover.noConflict = function () {
$.fn.popover = old
/**
* ------------------------------------------------------------------------
* jQuery Interface + noConflict implementaiton
* ------------------------------------------------------------------------
*/
/**
* @const
* @type {Function}
*/
$.fn[Popover._NAME] = Popover._jQueryInterface
/**
* @const
* @type {Function}
*/
$.fn[Popover._NAME]['Constructor'] = Popover
/**
* @const
* @type {Function}
*/
$.fn[Popover._NAME]['noConflict'] = function () {
$.fn[Popover._NAME] = Popover._JQUERY_NO_CONFLICT
return this return this
} }
}(jQuery);

View File

@ -1,175 +1,346 @@
/* ======================================================================== /** =======================================================================
* Bootstrap: scrollspy.js v3.3.2 * Bootstrap: scrollspy.js v4.0.0
* http://getbootstrap.com/javascript/#scrollspy * http://getbootstrap.com/javascript/#scrollspy
* ======================================================================== * ========================================================================
* Copyright 2011-2015 Twitter, Inc. * Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * 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
*
* ========================================================================
*/
+function ($) {
'use strict'; 'use strict';
// SCROLLSPY CLASS DEFINITION
// ==========================
function ScrollSpy(element, options) { /**
var process = $.proxy(this.process, this) * Our scrollspy class.
* @param {Element!} element
* @param {Object=} opt_config
* @constructor
*/
function ScrollSpy(element, opt_config) {
this.$body = $('body') /** @private {Element|Window} */
this.$scrollElement = $(element).is('body') ? $(window) : $(element) this._scrollElement = element.tagName == '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
this.$scrollElement.on('scroll.bs.scrollspy', process) /** @private {Object} */
this.refresh() this._config = $.extend({}, ScrollSpy['Defaults'], opt_config)
this.process()
/** @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()
} }
ScrollSpy.VERSION = '3.3.2'
ScrollSpy.DEFAULTS = { /**
offset: 10 * @const
* @type {string}
*/
ScrollSpy['VERSION'] = '4.0.0'
/**
* @const
* @type {Object}
*/
ScrollSpy['Defaults'] = {
'offset': 10
} }
ScrollSpy.prototype.getScrollHeight = function () {
return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight) /**
* @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'
} }
ScrollSpy.prototype.refresh = function () {
/**
* @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]()
}
})
}
/**
* Refresh the scrollspy target cache
*/
ScrollSpy.prototype['refresh'] = function () {
var offsetMethod = 'offset' var offsetMethod = 'offset'
var offsetBase = 0 var offsetBase = 0
if (!$.isWindow(this.$scrollElement[0])) { if (this._scrollElement !== this._scrollElement.window) {
offsetMethod = 'position' offsetMethod = 'position'
offsetBase = this.$scrollElement.scrollTop() offsetBase = this._getScrollTop()
} }
this.offsets = [] this._offsets = []
this.targets = [] this._targets = []
this.scrollHeight = this.getScrollHeight()
var self = this this._scrollHeight = this._getScrollHeight()
this.$body var targets = /** @type {Array.<Element>} */ ($.makeArray($(this._selector)))
.find(this.selector)
.map(function () {
var $el = $(this)
var href = $el.data('target') || $el.attr('href')
var $href = /^#./.test(href) && $(href)
return ($href targets
&& $href.length .map(function (element, index) {
&& $href.is(':visible') var target
&& [[$href[offsetMethod]().top + offsetBase, href]]) || null var targetSelector = Bootstrap.getSelectorFromElement(element)
if (targetSelector) {
target = $(targetSelector)[0]
}
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] }) .sort(function (a, b) { return a[0] - b[0] })
.each(function () { .forEach(function (item, index) {
self.offsets.push(this[0]) this._offsets.push(item[0])
self.targets.push(this[1]) this._targets.push(item[1])
}) }.bind(this))
} }
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() * @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']()
} }
if (scrollTop >= maxScroll) { if (scrollTop >= maxScroll) {
return activeTarget != (i = targets[targets.length - 1]) && this.activate(i) var target = this._targets[this._targets.length - 1]
}
if (activeTarget && scrollTop < offsets[0]) { if (this._activeTarget != target) {
this.activeTarget = null this._activate(target)
return this.clear()
}
for (i = offsets.length; i--;) {
activeTarget != targets[i]
&& scrollTop >= offsets[i]
&& (!offsets[i + 1] || scrollTop <= offsets[i + 1])
&& this.activate(targets[i])
} }
} }
ScrollSpy.prototype.activate = function (target) { if (this._activeTarget && scrollTop < this._offsets[0]) {
this.activeTarget = target this._activeTarget = null
this._clear()
this.clear() return
var selector = this.selector +
'[data-target="' + target + '"],' +
this.selector + '[href="' + target + '"]'
var active = $(selector)
.parents('li')
.addClass('active')
if (active.parent('.dropdown-menu').length) {
active = active
.closest('li.dropdown')
.addClass('active')
} }
active.trigger('activate.bs.scrollspy') 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])
ScrollSpy.prototype.clear = function () { if (isActiveTarget) {
$(this.selector) this._activate(this._targets[i])
.parentsUntil(this.options.target, '.active') }
.removeClass('active') }
} }
// SCROLLSPY PLUGIN DEFINITION /**
// =========================== * @param {Element} target
* @private
*/
ScrollSpy.prototype._activate = function (target) {
this._activeTarget = target
function Plugin(option) { this._clear()
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.scrollspy')
var options = typeof option == 'object' && option
if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options))) var selector = this._selector
if (typeof option == 'string') data[option]() + '[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)
for (var i = parentListItems.length; i--;) {
$(parentListItems[i]).addClass(ScrollSpy._ClassName.ACTIVE)
var itemParent = parentListItems[i].parentNode
if (itemParent && $(itemParent).hasClass(ScrollSpy._ClassName.DROPDOWN_MENU)) {
var closestDropdown = $(itemParent).closest(ScrollSpy._Selector.LI_DROPDOWN)[0]
$(closestDropdown).addClass(ScrollSpy._ClassName.ACTIVE)
}
}
$(this._scrollElement).trigger(ScrollSpy._Event.ACTIVATE, {
relatedTarget: target
}) })
} }
var old = $.fn.scrollspy
$.fn.scrollspy = Plugin /**
$.fn.scrollspy.Constructor = ScrollSpy * @private
*/
ScrollSpy.prototype._clear = function () {
var activeParents = $(this._selector).parentsUntil(this._config.target, ScrollSpy._Selector.ACTIVE)
for (var i = activeParents.length; i--;) {
$(activeParents[i]).removeClass(ScrollSpy._ClassName.ACTIVE)
}
}
// SCROLLSPY NO CONFLICT /**
// ===================== * ------------------------------------------------------------------------
* jQuery Interface + noConflict implementaiton
* ------------------------------------------------------------------------
*/
$.fn.scrollspy.noConflict = function () { /**
$.fn.scrollspy = old * @const
* @type {Function}
*/
$.fn[ScrollSpy._NAME] = ScrollSpy._jQueryInterface
/**
* @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 return this
} }
// SCROLLSPY DATA-API /**
// ================== * ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/
$(window).on('load.bs.scrollspy.data-api', function () { $(window).on('load.bs.scrollspy.data-api', function () {
$('[data-spy="scroll"]').each(function () { var scrollSpys = /** @type {Array.<Element>} */ ($.makeArray($(ScrollSpy._Selector.DATA_SPY)))
var $spy = $(this)
Plugin.call($spy, $spy.data())
})
})
}(jQuery); for (var i = scrollSpys.length; i--;) {
var $spy = $(scrollSpys[i])
ScrollSpy._jQueryInterface.call($spy, /** @type {Object|null} */ ($spy.data()))
}
})

373
js/tab.js
View File

@ -1,153 +1,324 @@
/* ======================================================================== /** =======================================================================
* Bootstrap: tab.js v3.3.2 * Bootstrap: tab.js v4.0.0
* http://getbootstrap.com/javascript/#tabs * http://getbootstrap.com/javascript/#tabs
* ======================================================================== * ========================================================================
* Copyright 2011-2015 Twitter, Inc. * Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * 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
*
* ========================================================================
*/
+function ($) {
'use strict'; 'use strict';
// TAB CLASS DEFINITION /**
// ==================== * Our Tab class.
* @param {Element!} element
* @constructor
*/
var Tab = function (element) { var Tab = function (element) {
this.element = $(element)
/** @type {Element} */
this._element = element
} }
Tab.VERSION = '3.3.2'
Tab.TRANSITION_DURATION = 150 /**
* @const
* @type {string}
*/
Tab['VERSION'] = '4.0.0'
Tab.prototype.show = function () {
var $this = this.element
var $ul = $this.closest('ul:not(.dropdown-menu)')
var selector = $this.data('target')
if (!selector) { /**
selector = $this.attr('href') * @const
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 * @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'
} }
if ($this.parent('li').hasClass('active')) return
var $previous = $ul.find('.active:last a') /**
var hideEvent = $.Event('hide.bs.tab', { * @const
relatedTarget: $this[0] * @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]()
}
}) })
var showEvent = $.Event('show.bs.tab', { }
relatedTarget: $previous[0]
/**
* 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)
if (ulElement) {
var previous = /** @type {Array.<Element>} */ ($.makeArray($(ulElement).find(Tab._Selector.ACTIVE)))
previous = previous[previous.length - 1]
if (previous) {
previous = $(previous).find('a')[0]
}
}
var hideEvent = $.Event(Tab._Event.HIDE, {
relatedTarget: this._element
}) })
$previous.trigger(hideEvent) var showEvent = $.Event(Tab._Event.SHOW, {
$this.trigger(showEvent) relatedTarget: previous
})
if (previous) {
$(previous).trigger(hideEvent)
}
$(this._element).trigger(showEvent)
if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
var $target = $(selector) if (selector) {
var target = $(selector)[0]
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]
})
})
} }
Tab.prototype.activate = function (element, container, callback) { this._activate($(this._element).closest(Tab._Selector.LI)[0], ulElement)
var $active = container.find('> .active')
var transition = callback
&& $.support.transition
&& (($active.length && $active.hasClass('fade')) || !!container.find('> .fade').length)
function next() { var complete = function () {
$active var hiddenEvent = $.Event(Tab._Event.HIDDEN, {
.removeClass('active') relatedTarget: this._element
.find('> .dropdown-menu > .active') })
.removeClass('active')
.end()
.find('[data-toggle="tab"]')
.attr('aria-expanded', false)
element var shownEvent = $.Event(Tab._Event.SHOWN, {
.addClass('active') relatedTarget: previous
.find('[data-toggle="tab"]') })
.attr('aria-expanded', true)
if (transition) { $(previous).trigger(hiddenEvent)
element[0].offsetWidth // reflow for transition $(this._element).trigger(shownEvent)
element.addClass('in') }.bind(this)
if (target) {
this._activate(target, /** @type {Element} */ (target.parentNode), complete)
} else { } else {
element.removeClass('fade') complete()
} }
if (element.parent('.dropdown-menu')) {
element
.closest('li.dropdown')
.addClass('active')
.end()
.find('[data-toggle="tab"]')
.attr('aria-expanded', true)
}
callback && callback()
}
$active.length && transition ?
$active
.one('bsTransitionEnd', next)
.emulateTransitionEnd(Tab.TRANSITION_DURATION) :
next()
$active.removeClass('in')
} }
// TAB PLUGIN DEFINITION /**
// ===================== * @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])
function Plugin(option) { var complete = this._transitionComplete.bind(this, element, active, isTransitioning, opt_callback)
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.tab')
if (!data) $this.data('bs.tab', (data = new Tab(this))) if (active && isTransitioning) {
if (typeof option == 'string') data[option]() $(active)
}) .one(Bootstrap.TRANSITION_END, complete)
.emulateTransitionEnd(Tab._TRANSITION_DURATION)
} else {
complete()
} }
var old = $.fn.tab if (active) {
$(active).removeClass(Tab._ClassName.IN)
$.fn.tab = Plugin }
$.fn.tab.Constructor = Tab }
// TAB NO CONFLICT /**
// =============== * @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)
$.fn.tab.noConflict = function () { var dropdownChild = $(active).find(Tab._Selector.DROPDOWN_ACTIVE_CHILD)[0]
$.fn.tab = old if (dropdownChild) {
$(dropdownChild).removeClass(Tab._ClassName.ACTIVE)
}
var activeToggle = $(active).find(Tab._Selector.DATA_TOGGLE)[0]
if (activeToggle) {
activeToggle.setAttribute('aria-expanded', false)
}
}
$(element).addClass(Tab._ClassName.ACTIVE)
var elementToggle = $(element).find(Tab._Selector.DATA_TOGGLE)[0]
if (elementToggle) {
elementToggle.setAttribute('aria-expanded', true)
}
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)
}
elementToggle = $(element).find(Tab._Selector.DATA_TOGGLE)[0]
if (elementToggle) {
elementToggle.setAttribute('aria-expanded', true)
}
}
if (opt_callback) {
opt_callback()
}
}
/**
* ------------------------------------------------------------------------
* jQuery Interface + noConflict implementaiton
* ------------------------------------------------------------------------
*/
/**
* @const
* @type {Function}
*/
$.fn[Tab._NAME] = Tab._jQueryInterface
/**
* @const
* @type {Function}
*/
$.fn[Tab._NAME]['Constructor'] = Tab
/**
* @const
* @type {Function}
*/
$.fn[Tab._NAME]['noConflict'] = function () {
$.fn[Tab._NAME] = Tab._JQUERY_NO_CONFLICT
return this return this
} }
// TAB DATA-API // TAB DATA-API
// ============ // ============
var clickHandler = function (e) { var clickHandler = function (e) {
e.preventDefault() e.preventDefault()
Plugin.call($(this), 'show') Tab._jQueryInterface.call($(this), 'show')
} }
$(document) $(document)
.on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler) .on('click.bs.tab.data-api', Tab._Selector.DATA_TOGGLE, clickHandler)
.on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
}(jQuery);

83
js/tests/closure.html Normal file
View File

@ -0,0 +1,83 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Bootstrap Plugin Test Suite</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- jQuery -->
<script src="vendor/jquery.min.js"></script>
<!-- QUnit -->
<link rel="stylesheet" href="vendor/qunit.css" media="screen">
<script src="vendor/qunit.js"></script>
<style>
#qunit-tests > li.pass {
display: none;/* Make it easier to see failing tests in Sauce screencasts */
}
#qunit-fixture {
top: 0;
left: 0;
}
</style>
<script>
// See https://github.com/axemclion/grunt-saucelabs#test-result-details-with-qunit
var log = []
QUnit.done(function (testResults) {
var tests = []
for (var i = 0, len = log.length; i < len; i++) {
var details = log[i]
tests.push({
name: details.name,
result: details.result,
expected: details.expected,
actual: details.actual,
source: details.source
})
}
testResults.tests = tests
window.global_test_results = testResults
})
QUnit.testStart(function (testDetails) {
$(window).scrollTop(0)
QUnit.log = function (details) {
if (!details.result) {
details.name = testDetails.name
log.push(details)
}
}
})
// Cleanup
QUnit.testDone(function () {
$('#qunit-fixture').empty()
$('#modal-test, .modal-backdrop').remove()
})
</script>
<!-- Plugin sources -->
<script src="../../dist/js/bootstrap.min.js"></script>
<!-- Unit tests -->
<script src="unit/alert.js"></script>
<script src="unit/button.js"></script>
<script src="unit/carousel.js"></script>
<script src="unit/collapse.js"></script>
<script src="unit/dropdown.js"></script>
<script src="unit/modal.js"></script>
<script src="unit/scrollspy.js"></script>
<script src="unit/tab.js"></script>
<script src="unit/tooltip.js"></script>
<script src="unit/popover.js"></script>
</head>
<body>
<div id="qunit-container">
<div id="qunit"></div>
<div id="qunit-fixture"></div>
</div>
</body>
</html>

View File

@ -59,7 +59,7 @@
</script> </script>
<!-- Plugin sources --> <!-- Plugin sources -->
<script>$.support.transition = false</script> <script src="../../js/util.js"></script>
<script src="../../js/alert.js"></script> <script src="../../js/alert.js"></script>
<script src="../../js/button.js"></script> <script src="../../js/button.js"></script>
<script src="../../js/carousel.js"></script> <script src="../../js/carousel.js"></script>
@ -70,7 +70,6 @@
<script src="../../js/tab.js"></script> <script src="../../js/tab.js"></script>
<script src="../../js/tooltip.js"></script> <script src="../../js/tooltip.js"></script>
<script src="../../js/popover.js"></script> <script src="../../js/popover.js"></script>
<script src="../../js/affix.js"></script>
<!-- Unit tests --> <!-- Unit tests -->
<script src="unit/alert.js"></script> <script src="unit/alert.js"></script>
@ -83,7 +82,6 @@
<script src="unit/tab.js"></script> <script src="unit/tab.js"></script>
<script src="unit/tooltip.js"></script> <script src="unit/tooltip.js"></script>
<script src="unit/popover.js"></script> <script src="unit/popover.js"></script>
<script src="unit/affix.js"></script>
</head> </head>
<body> <body>

View File

@ -29,61 +29,6 @@ $(function () {
strictEqual($button[0], $el[0], 'collection contains element') strictEqual($button[0], $el[0], 'collection contains element')
}) })
test('should return set state to loading', function (assert) {
var $btn = $('<button class="btn" data-loading-text="fat">mdo</button>')
equal($btn.html(), 'mdo', 'btn text equals mdo')
$btn.bootstrapButton('loading')
var done = assert.async()
setTimeout(function () {
equal($btn.html(), 'fat', 'btn text equals fat')
ok($btn[0].hasAttribute('disabled'), 'btn is disabled')
ok($btn.hasClass('disabled'), 'btn has disabled class')
done()
}, 0)
})
test('should return reset state', function (assert) {
var $btn = $('<button class="btn" data-loading-text="fat">mdo</button>')
equal($btn.html(), 'mdo', 'btn text equals mdo')
$btn.bootstrapButton('loading')
var doneOne = assert.async()
setTimeout(function () {
equal($btn.html(), 'fat', 'btn text equals fat')
ok($btn[0].hasAttribute('disabled'), 'btn is disabled')
ok($btn.hasClass('disabled'), 'btn has disabled class')
doneOne()
var doneTwo = assert.async()
$btn.bootstrapButton('reset')
setTimeout(function () {
equal($btn.html(), 'mdo', 'btn text equals mdo')
ok(!$btn[0].hasAttribute('disabled'), 'btn is not disabled')
ok(!$btn.hasClass('disabled'), 'btn does not have disabled class')
doneTwo()
}, 0)
}, 0)
})
test('should work with an empty string as reset state', function (assert) {
var $btn = $('<button class="btn" data-loading-text="fat"/>')
equal($btn.html(), '', 'btn text equals ""')
$btn.bootstrapButton('loading')
var doneOne = assert.async()
setTimeout(function () {
equal($btn.html(), 'fat', 'btn text equals fat')
ok($btn[0].hasAttribute('disabled'), 'btn is disabled')
ok($btn.hasClass('disabled'), 'btn has disabled class')
doneOne()
var doneTwo = assert.async()
$btn.bootstrapButton('reset')
setTimeout(function () {
equal($btn.html(), '', 'btn text equals ""')
ok(!$btn[0].hasAttribute('disabled'), 'btn is not disabled')
ok(!$btn.hasClass('disabled'), 'btn does not have disabled class')
doneTwo()
}, 0)
}, 0)
})
test('should toggle active', function () { test('should toggle active', function () {
var $btn = $('<button class="btn" data-toggle="button">mdo</button>') var $btn = $('<button class="btn" data-toggle="button">mdo</button>')
ok(!$btn.hasClass('active'), 'btn does not have active class') ok(!$btn.hasClass('active'), 'btn does not have active class')

View File

@ -322,30 +322,31 @@ $(function () {
+ '<a class="left carousel-control" href="#myCarousel" data-slide="prev">&lsaquo;</a>' + '<a class="left carousel-control" href="#myCarousel" data-slide="prev">&lsaquo;</a>'
+ '<a class="right carousel-control" href="#myCarousel" data-slide="next">&rsaquo;</a>' + '<a class="right carousel-control" href="#myCarousel" data-slide="next">&rsaquo;</a>'
+ '</div>' + '</div>'
var $carousel = $(templateHTML) var $carousel = $(templateHTML)
$carousel.attr('data-interval', 1814) $carousel.attr('data-interval', 1814)
$carousel.appendTo('body') $carousel.appendTo('body')
$('[data-slide]').first().click() $('[data-slide]').first().click()
equal($carousel.data('bs.carousel').options.interval, 1814) equal($carousel.data('bs.carousel').getConfig().interval, 1814)
$carousel.remove() $carousel.remove()
$carousel.appendTo('body').attr('data-modal', 'foobar') $carousel.appendTo('body').attr('data-modal', 'foobar')
$('[data-slide]').first().click() $('[data-slide]').first().click()
equal($carousel.data('bs.carousel').options.interval, 1814, 'even if there is an data-modal attribute set') equal($carousel.data('bs.carousel').getConfig().interval, 1814, 'even if there is an data-modal attribute set')
$carousel.remove() $carousel.remove()
$carousel.appendTo('body') $carousel.appendTo('body')
$('[data-slide]').first().click() $('[data-slide]').first().click()
$carousel.attr('data-interval', 1860) $carousel.attr('data-interval', 1860)
$('[data-slide]').first().click() $('[data-slide]').first().click()
equal($carousel.data('bs.carousel').options.interval, 1814, 'attributes should be read only on initialization') equal($carousel.data('bs.carousel').getConfig().interval, 1814, 'attributes should be read only on initialization')
$carousel.remove() $carousel.remove()
$carousel.attr('data-interval', false) $carousel.attr('data-interval', false)
$carousel.appendTo('body') $carousel.appendTo('body')
$carousel.bootstrapCarousel(1) $carousel.bootstrapCarousel(1)
strictEqual($carousel.data('bs.carousel').options.interval, false, 'data attribute has higher priority than default options') strictEqual($carousel.data('bs.carousel').getConfig().interval, false, 'data attribute has higher priority than default options')
$carousel.remove() $carousel.remove()
}) })

View File

@ -288,7 +288,7 @@ $(function () {
$body2 $body2
.toggleClass('in collapsing') .toggleClass('in collapsing')
.data('bs.collapse').transitioning = 1 .data('bs.collapse').setTransitioning(true)
$target1.click() $target1.click()

View File

@ -30,7 +30,7 @@ $(function () {
}) })
test('should expose defaults var for settings', function () { test('should expose defaults var for settings', function () {
ok($.fn.bootstrapModal.Constructor.DEFAULTS, 'default object exposed') ok($.fn.bootstrapModal.Constructor.Defaults, 'default object exposed')
}) })
test('should insert into dom when show method is called', function (assert) { test('should insert into dom when show method is called', function (assert) {

View File

@ -30,7 +30,7 @@ $(function () {
}) })
test('should expose default settings', function () { test('should expose default settings', function () {
ok($.fn.bootstrapTooltip.Constructor.DEFAULTS, 'defaults is defined') ok($.fn.bootstrapTooltip.Constructor.Defaults, 'defaults is defined')
}) })
test('should empty title attribute', function () { test('should empty title attribute', function () {
@ -879,17 +879,17 @@ $(function () {
.bootstrapTooltip({ delay: { show: 0, hide: 150 }}) .bootstrapTooltip({ delay: { show: 0, hide: 150 }})
setTimeout(function () { setTimeout(function () {
ok($tooltip.data('bs.tooltip').$tip.is('.fade.in'), '1ms: tooltip faded in') ok($('.tooltip').is('.fade.in'), '1ms: tooltip faded in')
$tooltip.trigger('mouseout') $tooltip.trigger('mouseout')
setTimeout(function () { setTimeout(function () {
ok($tooltip.data('bs.tooltip').$tip.is('.fade.in'), '100ms: tooltip still faded in') ok($('.tooltip').is('.fade.in'), '100ms: tooltip still faded in')
}, 100) }, 100)
setTimeout(function () { setTimeout(function () {
ok(!$tooltip.data('bs.tooltip').$tip.is('.in'), '200ms: tooltip removed') ok(!$('.tooltip').is('.in'), '200ms: tooltip removed')
done() start()
}, 200) }, 200)
}, 0) }, 0)
@ -978,7 +978,7 @@ $(function () {
test('should not reload the tooltip on subsequent mouseenter events', function () { test('should not reload the tooltip on subsequent mouseenter events', function () {
var titleHtml = function () { var titleHtml = function () {
var uid = $.fn.bootstrapTooltip.Constructor.prototype.getUID('tooltip') var uid = 'fatTooltip'
return '<p id="tt-content">' + uid + '</p><p>' + uid + '</p><p>' + uid + '</p>' return '<p id="tt-content">' + uid + '</p><p>' + uid + '</p><p>' + uid + '</p>'
} }
@ -1004,7 +1004,7 @@ $(function () {
test('should not reload the tooltip if the mouse leaves and re-enters before hiding', function () { test('should not reload the tooltip if the mouse leaves and re-enters before hiding', function () {
var titleHtml = function () { var titleHtml = function () {
var uid = $.fn.bootstrapTooltip.Constructor.prototype.getUID('tooltip') var uid = 'fatTooltip'
return '<p id="tt-content">' + uid + '</p><p>' + uid + '</p><p>' + uid + '</p>' return '<p id="tt-content">' + uid + '</p><p>' + uid + '</p><p>' + uid + '</p>'
} }
@ -1029,10 +1029,12 @@ $(function () {
$('#tt-outer').trigger('mouseleave') $('#tt-outer').trigger('mouseleave')
equal(currentUid, $('#tt-content').text()) equal(currentUid, $('#tt-content').text())
ok(obj.hoverState == 'out', 'the tooltip hoverState should be set to "out"') debugger
ok(obj.getHoverState() == 'out', 'the tooltip hoverState should be set to "out"')
$('#tt-content').trigger('mouseenter') $('#tt-content').trigger('mouseenter')
ok(obj.hoverState == 'in', 'the tooltip hoverState should be set to "in"') ok(obj.getHoverState() == 'in', 'the tooltip hoverState should be set to "in"')
equal(currentUid, $('#tt-content').text()) equal(currentUid, $('#tt-content').text())
}) })
@ -1051,7 +1053,7 @@ $(function () {
$('<a href="#" title="tooltip title" style="position: absolute; bottom: 0; right: 0;">Foobar</a>') $('<a href="#" title="tooltip title" style="position: absolute; bottom: 0; right: 0;">Foobar</a>')
.appendTo('body') .appendTo('body')
.on('shown.bs.tooltip', function () { .on('shown.bs.tooltip', function () {
var arrowStyles = $(this).data('bs.tooltip').$tip.find('.tooltip-arrow').attr('style') var arrowStyles = $('.tooltip').find('.tooltip-arrow').attr('style')
ok(/left/i.test(arrowStyles) && !/top/i.test(arrowStyles), 'arrow positioned correctly') ok(/left/i.test(arrowStyles) && !/top/i.test(arrowStyles), 'arrow positioned correctly')
$(this).bootstrapTooltip('hide') $(this).bootstrapTooltip('hide')
}) })

View File

@ -1,299 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Affix</title>
<link rel="stylesheet" href="../../../dist/css/bootstrap.min.css">
<style>
/* Test Styles */
.affixed-element-top.affix {
top: 10px;
}
.affixed-element-top.affix-bottom {
position: absolute;
}
.affixed-element-bottom {
margin-bottom: 0;
}
.affixed-element-bottom.affix {
bottom: 10px;
}
.affixed-element-bottom.affix-bottom {
position: relative;
}
.grow-btn, .shrink-btn {
color: #FFF;
}
.grow-btn {
background-color: #2ECC40;
}
.grow-btn:hover {
background-color: #3D9970;
}
.shrink-btn {
background-color: #FF4136;
}
.shrink-btn:hover {
background-color: #85144B;
}
</style>
</head>
<body>
<div class="container">
<div class="page-header js-page-header">
<h1>Affix <small>Bootstrap Visual Test</small></h1>
</div>
<div class="col-md-3">
<ul class="list-group affixed-element-top js-affixed-element-top">
<li class="list-group-item">Cras justo odio</li>
<li class="list-group-item">Dapibus ac facilisis in</li>
<li class="list-group-item">Morbi leo risus</li>
<li class="list-group-item">Porta ac consectetur ac</li>
<li class="list-group-item">Vestibulum at eros</li>
<li class="list-group-item">Cras justo odio</li>
<li class="list-group-item">Dapibus ac facilisis in</li>
<li class="list-group-item">Morbi leo risus</li>
<li class="list-group-item">Porta ac consectetur ac</li>
<li class="list-group-item">Vestibulum at eros</li>
<li class="list-group-item">Cras justo odio</li>
<li class="list-group-item">Dapibus ac facilisis in</li>
<li class="list-group-item">Morbi leo risus</li>
<li class="list-group-item">Porta ac consectetur ac</li>
<li class="list-group-item">Vestibulum at eros</li>
<li class="list-group-item">Porta ac consectetur ac</li>
</ul>
</div>
<div class="col-md-6 js-content">
<p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue. Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
<p>Nullam id dolor id nibh ultricies vehicula ut id elit. Etiam porta sem malesuada magna mollis euismod. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Curabitur blandit tempus porttitor. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>
<p>Sed posuere consectetur est at lobortis. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Nulla vitae elit libero, a pharetra augue. Nulla vitae elit libero, a pharetra augue.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nulla vitae elit libero, a pharetra augue. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue. Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
<p>Nullam id dolor id nibh ultricies vehicula ut id elit. Etiam porta sem malesuada magna mollis euismod. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Curabitur blandit tempus porttitor. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>
<p>Sed posuere consectetur est at lobortis. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Nulla vitae elit libero, a pharetra augue. Nulla vitae elit libero, a pharetra augue.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nulla vitae elit libero, a pharetra augue. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue. Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
<p>Nullam id dolor id nibh ultricies vehicula ut id elit. Etiam porta sem malesuada magna mollis euismod. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Curabitur blandit tempus porttitor. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>
<p>Sed posuere consectetur est at lobortis. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Nulla vitae elit libero, a pharetra augue. Nulla vitae elit libero, a pharetra augue.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nulla vitae elit libero, a pharetra augue. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue. Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
<p>Nullam id dolor id nibh ultricies vehicula ut id elit. Etiam porta sem malesuada magna mollis euismod. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Curabitur blandit tempus porttitor. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>
<p>Sed posuere consectetur est at lobortis. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Nulla vitae elit libero, a pharetra augue. Nulla vitae elit libero, a pharetra augue.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nulla vitae elit libero, a pharetra augue. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue. Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
<p>Nullam id dolor id nibh ultricies vehicula ut id elit. Etiam porta sem malesuada magna mollis euismod. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Curabitur blandit tempus porttitor. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>
<p>Sed posuere consectetur est at lobortis. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Nulla vitae elit libero, a pharetra augue. Nulla vitae elit libero, a pharetra augue.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nulla vitae elit libero, a pharetra augue. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue. Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
<p>Nullam id dolor id nibh ultricies vehicula ut id elit. Etiam porta sem malesuada magna mollis euismod. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Curabitur blandit tempus porttitor. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>
<p>Sed posuere consectetur est at lobortis. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Nulla vitae elit libero, a pharetra augue. Nulla vitae elit libero, a pharetra augue.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nulla vitae elit libero, a pharetra augue. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue. Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
<p>Nullam id dolor id nibh ultricies vehicula ut id elit. Etiam porta sem malesuada magna mollis euismod. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Curabitur blandit tempus porttitor. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>
<p>Sed posuere consectetur est at lobortis. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Nulla vitae elit libero, a pharetra augue. Nulla vitae elit libero, a pharetra augue.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nulla vitae elit libero, a pharetra augue. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue. Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
<p>Nullam id dolor id nibh ultricies vehicula ut id elit. Etiam porta sem malesuada magna mollis euismod. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Curabitur blandit tempus porttitor. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>
<p>Sed posuere consectetur est at lobortis. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Nulla vitae elit libero, a pharetra augue. Nulla vitae elit libero, a pharetra augue.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nulla vitae elit libero, a pharetra augue. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue. Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
<p>Nullam id dolor id nibh ultricies vehicula ut id elit. Etiam porta sem malesuada magna mollis euismod. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Curabitur blandit tempus porttitor. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>
<p>Sed posuere consectetur est at lobortis. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Nulla vitae elit libero, a pharetra augue. Nulla vitae elit libero, a pharetra augue.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nulla vitae elit libero, a pharetra augue. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue. Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
<p>Nullam id dolor id nibh ultricies vehicula ut id elit. Etiam porta sem malesuada magna mollis euismod. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Curabitur blandit tempus porttitor. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>
<p>Sed posuere consectetur est at lobortis. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Nulla vitae elit libero, a pharetra augue. Nulla vitae elit libero, a pharetra augue.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nulla vitae elit libero, a pharetra augue. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue. Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
<p>Nullam id dolor id nibh ultricies vehicula ut id elit. Etiam porta sem malesuada magna mollis euismod. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Curabitur blandit tempus porttitor. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>
<p>Sed posuere consectetur est at lobortis. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Nulla vitae elit libero, a pharetra augue. Nulla vitae elit libero, a pharetra augue.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nulla vitae elit libero, a pharetra augue. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue. Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
<p>Nullam id dolor id nibh ultricies vehicula ut id elit. Etiam porta sem malesuada magna mollis euismod. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Curabitur blandit tempus porttitor. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>
<p>Sed posuere consectetur est at lobortis. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Nulla vitae elit libero, a pharetra augue. Nulla vitae elit libero, a pharetra augue.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nulla vitae elit libero, a pharetra augue. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue. Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
<p>Nullam id dolor id nibh ultricies vehicula ut id elit. Etiam porta sem malesuada magna mollis euismod. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Curabitur blandit tempus porttitor. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>
<p>Sed posuere consectetur est at lobortis. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Nulla vitae elit libero, a pharetra augue. Nulla vitae elit libero, a pharetra augue.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nulla vitae elit libero, a pharetra augue. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue. Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
<p>Nullam id dolor id nibh ultricies vehicula ut id elit. Etiam porta sem malesuada magna mollis euismod. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Curabitur blandit tempus porttitor. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>
<p>Sed posuere consectetur est at lobortis. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Nulla vitae elit libero, a pharetra augue. Nulla vitae elit libero, a pharetra augue.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nulla vitae elit libero, a pharetra augue. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue. Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
<p>Nullam id dolor id nibh ultricies vehicula ut id elit. Etiam porta sem malesuada magna mollis euismod. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Curabitur blandit tempus porttitor. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>
<p>Sed posuere consectetur est at lobortis. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Nulla vitae elit libero, a pharetra augue. Nulla vitae elit libero, a pharetra augue.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nulla vitae elit libero, a pharetra augue. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue. Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
<p>Nullam id dolor id nibh ultricies vehicula ut id elit. Etiam porta sem malesuada magna mollis euismod. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Curabitur blandit tempus porttitor. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>
<p>Sed posuere consectetur est at lobortis. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Nulla vitae elit libero, a pharetra augue. Nulla vitae elit libero, a pharetra augue.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nulla vitae elit libero, a pharetra augue. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue. Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
<p>Nullam id dolor id nibh ultricies vehicula ut id elit. Etiam porta sem malesuada magna mollis euismod. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Curabitur blandit tempus porttitor. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>
<p>Sed posuere consectetur est at lobortis. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Nulla vitae elit libero, a pharetra augue. Nulla vitae elit libero, a pharetra augue.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nulla vitae elit libero, a pharetra augue. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue. Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
<p>Nullam id dolor id nibh ultricies vehicula ut id elit. Etiam porta sem malesuada magna mollis euismod. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Curabitur blandit tempus porttitor. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>
<p>Sed posuere consectetur est at lobortis. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Nulla vitae elit libero, a pharetra augue. Nulla vitae elit libero, a pharetra augue.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nulla vitae elit libero, a pharetra augue. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue. Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
<p>Nullam id dolor id nibh ultricies vehicula ut id elit. Etiam porta sem malesuada magna mollis euismod. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Curabitur blandit tempus porttitor. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>
<p>Sed posuere consectetur est at lobortis. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Nulla vitae elit libero, a pharetra augue. Nulla vitae elit libero, a pharetra augue.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nulla vitae elit libero, a pharetra augue. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue. Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
<p>Nullam id dolor id nibh ultricies vehicula ut id elit. Etiam porta sem malesuada magna mollis euismod. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Curabitur blandit tempus porttitor. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>
<p>Sed posuere consectetur est at lobortis. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Nulla vitae elit libero, a pharetra augue. Nulla vitae elit libero, a pharetra augue.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nulla vitae elit libero, a pharetra augue. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
</div>
<div class="col-md-3">
<ul class="list-group affixed-element-bottom js-affixed-element-bottom">
<li class="list-group-item">Sit necessitatibus aspernatur.</li>
<li class="list-group-item">Adipisicing alias dolor!</li>
<li class="list-group-item">Ipsum molestiae impedit.</li>
<li class="list-group-item">Amet quis iste?</li>
<li class="list-group-item">Ipsum quaerat porro.</li>
<li class="list-group-item">Elit lorem libero.</li>
<li class="list-group-item">Ipsum dolore facilis.</li>
<li class="list-group-item">Elit ad atque.</li>
<li class="list-group-item">Dolor amet sequi!</li>
<li class="list-group-item">Consectetur voluptatum facilis!</li>
<li class="list-group-item">Sit neque eligendi?</li>
<li class="list-group-item">Amet fuga consectetur!</li>
<li class="list-group-item">Amet molestias repellat!</li>
<li class="list-group-item">Consectetur minima repellendus.</li>
<li class="list-group-item grow-btn js-grow-btn">Grow content</li>
<li class="list-group-item shrink-btn js-shrink-btn">Shrink content</li>
</ul>
</div>
<div class="col-md-12 js-footer">
<hr>
<p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue. Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
<p>Nullam id dolor id nibh ultricies vehicula ut id elit. Etiam porta sem malesuada magna mollis euismod. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Curabitur blandit tempus porttitor. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>
<p>Sed posuere consectetur est at lobortis. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Nulla vitae elit libero, a pharetra augue. Nulla vitae elit libero, a pharetra augue.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nulla vitae elit libero, a pharetra augue. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
</div>
</div>
<!-- JavaScript Includes -->
<script src="../vendor/jquery.min.js"></script>
<script src="../../transition.js"></script>
<script src="../../affix.js"></script>
<!-- JavaScript Test -->
<script>
$(function () {
$('.js-affixed-element-top').affix({
offset: {
top: $('.js-page-header').outerHeight(true) - 10
, bottom: $('.js-footer').outerHeight(true) + 10
}
})
// todo(fat): sux you have to do this.
.on('affix.bs.affix', function (e) {
$(e.target).width(e.target.offsetWidth)
})
$('.js-affixed-element-bottom').affix({
offset: {
bottom: $('.js-footer').outerHeight(true) + 10
}
})
$('.js-grow-btn').on('click', function() {
$('.js-content').append('<p>Ipsum corrupti ipsam est temporibus.</p>')
})
$('.js-shrink-btn').on('click', function() {
$('.js-content p').last().remove()
})
})
</script>
</body>
</html>

View File

@ -34,7 +34,7 @@
<!-- JavaScript Includes --> <!-- JavaScript Includes -->
<script src="../vendor/jquery.min.js"></script> <script src="../vendor/jquery.min.js"></script>
<script src="../../transition.js"></script> <script src="../../util.js"></script>
<script src="../../alert.js"></script> <script src="../../alert.js"></script>
</body> </body>

View File

@ -15,10 +15,6 @@
<h1>Button <small>Bootstrap Visual Test</small></h1> <h1>Button <small>Bootstrap Visual Test</small></h1>
</div> </div>
<button type="button" data-loading-text="Loading for 3 seconds..." class="btn btn-primary js-loading-button">
Loading state
</button>
<button type="button" class="btn btn-primary" data-toggle="button">Single toggle</button> <button type="button" class="btn btn-primary" data-toggle="button">Single toggle</button>
<div class="btn-group" data-toggle="buttons"> <div class="btn-group" data-toggle="buttons">
@ -49,7 +45,7 @@
<!-- JavaScript Includes --> <!-- JavaScript Includes -->
<script src="../vendor/jquery.min.js"></script> <script src="../vendor/jquery.min.js"></script>
<script src="../../transition.js"></script> <script src="../../util.js"></script>
<script src="../../button.js"></script> <script src="../../button.js"></script>
<!-- JavaScript Test --> <!-- JavaScript Test -->

View File

@ -44,7 +44,7 @@
<!-- JavaScript Includes --> <!-- JavaScript Includes -->
<script src="../vendor/jquery.min.js"></script> <script src="../vendor/jquery.min.js"></script>
<script src="../../transition.js"></script> <script src="../../util.js"></script>
<script src="../../carousel.js"></script> <script src="../../carousel.js"></script>
</body> </body>

View File

@ -64,7 +64,7 @@
<!-- JavaScript Includes --> <!-- JavaScript Includes -->
<script src="../vendor/jquery.min.js"></script> <script src="../vendor/jquery.min.js"></script>
<script src="../../transition.js"></script> <script src="../../util.js"></script>
<script src="../../collapse.js"></script> <script src="../../collapse.js"></script>
</body> </body>

View File

@ -93,7 +93,7 @@
<!-- JavaScript Includes --> <!-- JavaScript Includes -->
<script src="../vendor/jquery.min.js"></script> <script src="../vendor/jquery.min.js"></script>
<script src="../../transition.js"></script> <script src="../../util.js"></script>
<script src="../../dropdown.js"></script> <script src="../../dropdown.js"></script>
<script src="../../collapse.js"></script> <script src="../../collapse.js"></script>

View File

@ -63,7 +63,7 @@
<!-- JavaScript Includes --> <!-- JavaScript Includes -->
<script src="../vendor/jquery.min.js"></script> <script src="../vendor/jquery.min.js"></script>
<script src="../../transition.js"></script> <script src="../../util.js"></script>
<script src="../../modal.js"></script> <script src="../../modal.js"></script>
<script src="../../tooltip.js"></script> <script src="../../tooltip.js"></script>
<script src="../../popover.js"></script> <script src="../../popover.js"></script>

View File

@ -32,7 +32,7 @@
<!-- JavaScript Includes --> <!-- JavaScript Includes -->
<script src="../vendor/jquery.min.js"></script> <script src="../vendor/jquery.min.js"></script>
<script src="../../transition.js"></script> <script src="../../util.js"></script>
<script src="../../tooltip.js"></script> <script src="../../tooltip.js"></script>
<script src="../../popover.js"></script> <script src="../../popover.js"></script>

View File

@ -93,7 +93,7 @@
<!-- JavaScript Includes --> <!-- JavaScript Includes -->
<script src="../vendor/jquery.min.js"></script> <script src="../vendor/jquery.min.js"></script>
<script src="../../transition.js"></script> <script src="../../util.js"></script>
<script src="../../scrollspy.js"></script> <script src="../../scrollspy.js"></script>
<script src="../../dropdown.js"></script> <script src="../../dropdown.js"></script>
<script src="../../collapse.js"></script> <script src="../../collapse.js"></script>

View File

@ -157,7 +157,7 @@
<!-- JavaScript Includes --> <!-- JavaScript Includes -->
<script src="../vendor/jquery.min.js"></script> <script src="../vendor/jquery.min.js"></script>
<script src="../../transition.js"></script> <script src="../../util.js"></script>
<script src="../../tab.js"></script> <script src="../../tab.js"></script>
<script src="../../dropdown.js"></script> <script src="../../dropdown.js"></script>

View File

@ -29,7 +29,7 @@
<!-- JavaScript Includes --> <!-- JavaScript Includes -->
<script src="../vendor/jquery.min.js"></script> <script src="../vendor/jquery.min.js"></script>
<script src="../../transition.js"></script> <script src="../../util.js"></script>
<script src="../../tooltip.js"></script> <script src="../../tooltip.js"></script>
<!-- JavaScript Test --> <!-- JavaScript Test -->

View File

@ -1,378 +1,661 @@
/* ======================================================================== /** =======================================================================
* Bootstrap: tooltip.js v3.3.2 * Bootstrap: tooltip.js v4.0.0
* http://getbootstrap.com/javascript/#tooltip * http://getbootstrap.com/javascript/#tooltip
* Inspired by the original jQuery.tipsy by Jason Frame
* ======================================================================== * ========================================================================
* Copyright 2011-2015 Twitter, Inc. * Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */ * ========================================================================
* @fileoverview - Bootstrap's tooltip plugin.
* (Inspired by jQuery.tipsy by Jason Frame)
*
* Public Methods & Properties:
*
* + $.tooltip
* + $.tooltip.noConflict
* + $.tooltip.Constructor
* + $.tooltip.Constructor.VERSION
* + $.tooltip.Constructor.Defaults
* + $.tooltip.Constructor.Defaults.container
* + $.tooltip.Constructor.Defaults.animation
* + $.tooltip.Constructor.Defaults.placement
* + $.tooltip.Constructor.Defaults.selector
* + $.tooltip.Constructor.Defaults.template
* + $.tooltip.Constructor.Defaults.trigger
* + $.tooltip.Constructor.Defaults.title
* + $.tooltip.Constructor.Defaults.delay
* + $.tooltip.Constructor.Defaults.html
* + $.tooltip.Constructor.Defaults.viewport
* + $.tooltip.Constructor.Defaults.viewport.selector
* + $.tooltip.Constructor.Defaults.viewport.padding
* + $.tooltip.Constructor.prototype.enable
* + $.tooltip.Constructor.prototype.disable
* + $.tooltip.Constructor.prototype.destroy
* + $.tooltip.Constructor.prototype.toggleEnabled
* + $.tooltip.Constructor.prototype.toggle
* + $.tooltip.Constructor.prototype.show
* + $.tooltip.Constructor.prototype.hide
*
* ========================================================================
*/
+function ($) {
'use strict'; 'use strict';
// TOOLTIP PUBLIC CLASS DEFINITION
// ===============================
var Tooltip = function (element, options) { /**
this.type = * Our tooltip class.
this.options = * @param {Element!} element
this.enabled = * @param {Object=} opt_config
this.timeout = * @constructor
this.hoverState = */
this.$element = null var Tooltip = function (element, opt_config) {
/** @private {boolean} */
this._isEnabled = true
/** @private {number} */
this._timeout = 0
/** @private {string} */
this._hoverState = ''
/** @protected {Element} */
this.element = element
/** @protected {Object} */
this.config = this._getConfig(opt_config)
/** @protected {Element} */
this.tip = null
/** @protected {Element} */
this.arrow = null
if (this.config['viewport']) {
/** @private {Element} */
this._viewport = $(this.config['viewport']['selector'] || this.config['viewport'])[0]
this.init('tooltip', element, options)
} }
Tooltip.VERSION = '3.3.2' this._setListeners()
}
Tooltip.TRANSITION_DURATION = 150
Tooltip.DEFAULTS = { /**
animation: true, * @const
placement: 'top', * @type {string}
selector: false, */
template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>', Tooltip['VERSION'] = '4.0.0'
trigger: 'hover focus',
title: '',
delay: 0, /**
html: false, * @const
container: false, * @type {Object}
viewport: { */
selector: 'body', Tooltip['Defaults'] = {
padding: 0 'container' : false,
'animation' : true,
'placement' : 'top',
'selector' : false,
'template' : '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
'trigger' : 'hover focus',
'title' : '',
'delay' : 0,
'html' : false,
'viewport': {
'selector': 'body',
'padding' : 0
} }
} }
Tooltip.prototype.init = function (type, element, options) {
this.enabled = true
this.type = type
this.$element = $(element)
this.options = this.getOptions(options)
this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
var triggers = this.options.trigger.split(' ') /**
* @const
* @enum {string}
* @protected
*/
Tooltip.Direction = {
TOP: 'top',
LEFT: 'left',
RIGHT: 'right',
BOTTOM: 'bottom'
}
for (var i = triggers.length; i--;) {
var trigger = triggers[i]
/**
* @const
* @type {string}
* @private
*/
Tooltip._NAME = 'tooltip'
/**
* @const
* @type {string}
* @private
*/
Tooltip._DATA_KEY = 'bs.tooltip'
/**
* @const
* @type {number}
* @private
*/
Tooltip._TRANSITION_DURATION = 150
/**
* @const
* @enum {string}
* @private
*/
Tooltip._HoverState = {
IN: 'in',
OUT: 'out'
}
/**
* @const
* @enum {string}
* @private
*/
Tooltip._Event = {
HIDE : 'hide.bs.tooltip',
HIDDEN : 'hidden.bs.tooltip',
SHOW : 'show.bs.tooltip',
SHOWN : 'shown.bs.tooltip'
}
/**
* @const
* @enum {string}
* @private
*/
Tooltip._ClassName = {
FADE : 'fade',
IN : 'in'
}
/**
* @const
* @enum {string}
* @private
*/
Tooltip._Selector = {
TOOLTIP : '.tooltip',
TOOLTIP_INNER : '.tooltip-inner',
TOOLTIP_ARROW : '.tooltip-arrow'
}
/**
* @const
* @type {Function}
* @private
*/
Tooltip._JQUERY_NO_CONFLICT = $.fn[Tooltip._NAME]
/**
* @param {Object=} opt_config
* @this {jQuery}
* @return {jQuery}
* @private
*/
Tooltip._jQueryInterface = function (opt_config) {
return this.each(function () {
var data = $(this).data(Tooltip._DATA_KEY)
var config = typeof opt_config == 'object' ? opt_config : null
if (!data && opt_config == 'destroy') {
return
}
if (!data) {
data = new Tooltip(this, config)
$(this).data(Tooltip._DATA_KEY, data)
}
if (typeof opt_config === 'string') {
data[opt_config]()
}
})
}
/**
* Enable tooltip
*/
Tooltip.prototype['enable'] = function () {
this._isEnabled = true
}
/**
* Disable tooltip
*/
Tooltip.prototype['disable'] = function () {
this._isEnabled = false
}
/**
* Toggle the tooltip enable state
*/
Tooltip.prototype['toggleEnabled'] = function () {
this._isEnabled = !this._isEnabled
}
/**
* Toggle the tooltips display
* @param {Event} opt_event
*/
Tooltip.prototype['toggle'] = function (opt_event) {
var context = this
var dataKey = this.getDataKey()
if (opt_event) {
context = $(opt_event.currentTarget).data(dataKey)
if (!context) {
context = new this.constructor(opt_event.currentTarget, this._getDelegateConfig())
$(opt_event.currentTarget).data(dataKey, context)
}
}
$(context.getTipElement()).hasClass(Tooltip._ClassName.IN) ?
context._leave(null, context) :
context._enter(null, context)
}
/**
* Remove tooltip functionality
*/
Tooltip.prototype['destroy'] = function () {
clearTimeout(this._timeout)
this['hide'](function () {
$(this.element)
.off(Tooltip._Selector.TOOLTIP)
.removeData(this.getDataKey())
}.bind(this))
}
/**
* Show the tooltip
* todo (fat): ~fuck~ this is a big function - refactor out all of positioning logic
* and replace with external lib
*/
Tooltip.prototype['show'] = function () {
var showEvent = $.Event(this.getEventObject().SHOW)
if (this.isWithContent() && this._isEnabled) {
$(this.element).trigger(showEvent)
var isInTheDom = $.contains(this.element.ownerDocument.documentElement, this.element)
if (showEvent.isDefaultPrevented() || !isInTheDom) {
return
}
var tip = this.getTipElement()
var tipId = Bootstrap.getUID(this.getName())
tip.setAttribute('id', tipId)
this.element.setAttribute('aria-describedby', tipId)
this.setContent()
if (this.config['animation']) {
$(tip).addClass(Tooltip._ClassName.FADE)
}
var placement = typeof this.config['placement'] == 'function' ?
this.config['placement'].call(this, tip, this.element) :
this.config['placement']
var autoToken = /\s?auto?\s?/i
var isWithAutoPlacement = autoToken.test(placement)
if (isWithAutoPlacement) {
placement = placement.replace(autoToken, '') || Tooltip.Direction.TOP
}
if (tip.parentNode && tip.parentNode.nodeType == Node.ELEMENT_NODE) {
tip.parentNode.removeChild(tip)
}
tip.style.top = 0
tip.style.left = 0
tip.style.display = 'block'
$(tip).addClass(Tooltip._NAME + '-' + placement)
$(tip).data(this.getDataKey(), this)
if (this.config['container']) {
$(this.config['container'])[0].appendChild(tip)
} else {
this.element.parentNode.insertBefore(tip, this.element.nextSibling)
}
var position = this._getPosition()
var actualWidth = tip.offsetWidth
var actualHeight = tip.offsetHeight
var calculatedPlacement = this._getCalculatedAutoPlacement(isWithAutoPlacement, placement, position, actualWidth, actualHeight)
var calculatedOffset = this._getCalculatedOffset(calculatedPlacement, position, actualWidth, actualHeight)
this._applyCalculatedPlacement(calculatedOffset, calculatedPlacement)
var complete = function () {
var prevHoverState = this.hoverState
$(this.element).trigger(this.getEventObject().SHOWN)
this.hoverState = null
if (prevHoverState == 'out') this._leave(null, this)
}.bind(this)
Bootstrap.transition && $(this._tip).hasClass(Tooltip._ClassName.FADE) ?
$(this._tip)
.one(Bootstrap.TRANSITION_END, complete)
.emulateTransitionEnd(Tooltip._TRANSITION_DURATION) :
complete()
}
}
/**
* Hide the tooltip breh
*/
Tooltip.prototype['hide'] = function (callback) {
var tip = this.getTipElement()
var hideEvent = $.Event(this.getEventObject().HIDE)
var complete = function () {
if (this._hoverState != Tooltip._HoverState.IN) {
tip.parentNode.removeChild(tip)
}
this.element.removeAttribute('aria-describedby')
$(this.element).trigger(this.getEventObject().HIDDEN)
if (callback) {
callback()
}
}.bind(this)
$(this.element).trigger(hideEvent)
if (hideEvent.isDefaultPrevented()) return
$(tip).removeClass(Tooltip._ClassName.IN)
if (Bootstrap.transition && $(this._tip).hasClass(Tooltip._ClassName.FADE)) {
$(tip)
.one(Bootstrap.TRANSITION_END, complete)
.emulateTransitionEnd(Tooltip._TRANSITION_DURATION)
} else {
complete()
}
this._hoverState = ''
}
/**
* @return {string}
*/
Tooltip.prototype['getHoverState'] = function (callback) {
return this._hoverState
}
/**
* @return {string}
* @protected
*/
Tooltip.prototype.getName = function () {
return Tooltip._NAME
}
/**
* @return {string}
* @protected
*/
Tooltip.prototype.getDataKey = function () {
return Tooltip._DATA_KEY
}
/**
* @return {Object}
* @protected
*/
Tooltip.prototype.getEventObject = function () {
return Tooltip._Event
}
/**
* @return {string}
* @protected
*/
Tooltip.prototype.getTitle = function () {
var title = this.element.getAttribute('data-original-title')
if (!title) {
title = typeof this.config['title'] === 'function' ?
this.config['title'].call(this.element) :
this.config['title']
}
return /** @type {string} */ (title)
}
/**
* @return {Element}
* @protected
*/
Tooltip.prototype.getTipElement = function () {
return (this._tip = this._tip || $(this.config['template'])[0])
}
/**
* @return {Element}
* @protected
*/
Tooltip.prototype.getArrowElement = function () {
return (this.arrow = this.arrow || $(this.getTipElement()).find(Tooltip._Selector.TOOLTIP_ARROW)[0])
}
/**
* @return {boolean}
* @protected
*/
Tooltip.prototype.isWithContent = function () {
return !!this.getTitle()
}
/**
* @protected
*/
Tooltip.prototype.setContent = function () {
var tip = this.getTipElement()
var title = this.getTitle()
$(tip).find(Tooltip._Selector.TOOLTIP_INNER)[0][this.config['html'] ? 'innerHTML' : 'innerText'] = title
$(tip)
.removeClass(Tooltip._ClassName.FADE)
.removeClass(Tooltip._ClassName.IN)
for (var direction in Tooltip.Direction) {
$(tip).removeClass(Tooltip._NAME + '-' + direction)
}
}
/**
* @private
*/
Tooltip.prototype._setListeners = function () {
var triggers = this.config['trigger'].split(' ')
triggers.forEach(function (trigger) {
if (trigger == 'click') { if (trigger == 'click') {
this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) $(this.element).on('click.bs.tooltip', this.config['selector'], this['toggle'].bind(this))
} else if (trigger != 'manual') { } else if (trigger != 'manual') {
var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) $(this.element)
this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) .on(eventIn + '.bs.tooltip', this.config['selector'], this._enter.bind(this))
.on(eventOut + '.bs.tooltip', this.config['selector'], this._leave.bind(this))
}
}.bind(this))
if (this.config['selector']) {
this.config = $.extend({}, this.config, { 'trigger': 'manual', 'selector': '' })
} else {
this._fixTitle()
} }
} }
this.options.selector ?
(this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
this.fixTitle()
}
Tooltip.prototype.getDefaults = function () { /**
return Tooltip.DEFAULTS * @param {Object=} opt_config
} * @return {Object}
* @private
*/
Tooltip.prototype._getConfig = function (opt_config) {
var config = $.extend({}, this.constructor['Defaults'], $(this.element).data(), opt_config)
Tooltip.prototype.getOptions = function (options) { if (config['delay'] && typeof config['delay'] == 'number') {
options = $.extend({}, this.getDefaults(), this.$element.data(), options) config['delay'] = {
'show': config['delay'],
if (options.delay && typeof options.delay == 'number') { 'hide': config['delay']
options.delay = {
show: options.delay,
hide: options.delay
} }
} }
return options return config
} }
Tooltip.prototype.getDelegateOptions = function () {
var options = {}
var defaults = this.getDefaults()
this._options && $.each(this._options, function (key, value) { /**
if (defaults[key] != value) options[key] = value * @return {Object}
}) * @private
*/
Tooltip.prototype._getDelegateConfig = function () {
var config = {}
var defaults = this.constructor['Defaults']
return options if (this.config) {
for (var key in this.config) {
var value = this.config[key]
if (defaults[key] != value) config[key] = value
}
} }
Tooltip.prototype.enter = function (obj) { return config
var self = obj instanceof this.constructor ?
obj : $(obj.currentTarget).data('bs.' + this.type)
if (self && self.$tip && self.$tip.is(':visible')) {
self.hoverState = 'in'
return
} }
if (!self) {
self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
$(obj.currentTarget).data('bs.' + this.type, self)
}
clearTimeout(self.timeout)
self.hoverState = 'in' /**
* @param {boolean} isWithAutoPlacement
* @param {string} placement
* @param {Object} position
* @param {number} actualWidth
* @param {number} actualHeight
* @return {string}
* @private
*/
Tooltip.prototype._getCalculatedAutoPlacement = function (isWithAutoPlacement, placement, position, actualWidth, actualHeight) {
if (isWithAutoPlacement) {
var originalPlacement = placement
var container = this.config['container'] ? $(this.config['container'])[0] : this.element.parentNode
var containerDim = this._getPosition(/** @type {Element} */ (container))
if (!self.options.delay || !self.options.delay.show) return self.show() placement = placement == Tooltip.Direction.BOTTOM && position.bottom + actualHeight > containerDim.bottom ? Tooltip.Direction.TOP :
placement == Tooltip.Direction.TOP && position.top - actualHeight < containerDim.top ? Tooltip.Direction.BOTTOM :
self.timeout = setTimeout(function () { placement == Tooltip.Direction.RIGHT && position.right + actualWidth > containerDim.width ? Tooltip.Direction.LEFT :
if (self.hoverState == 'in') self.show() placement == Tooltip.Direction.LEFT && position.left - actualWidth < containerDim.left ? Tooltip.Direction.RIGHT :
}, self.options.delay.show)
}
Tooltip.prototype.leave = function (obj) {
var self = obj instanceof this.constructor ?
obj : $(obj.currentTarget).data('bs.' + this.type)
if (!self) {
self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
$(obj.currentTarget).data('bs.' + this.type, self)
}
clearTimeout(self.timeout)
self.hoverState = 'out'
if (!self.options.delay || !self.options.delay.hide) return self.hide()
self.timeout = setTimeout(function () {
if (self.hoverState == 'out') self.hide()
}, self.options.delay.hide)
}
Tooltip.prototype.show = function () {
var e = $.Event('show.bs.' + this.type)
if (this.hasContent() && this.enabled) {
this.$element.trigger(e)
var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
if (e.isDefaultPrevented() || !inDom) return
var that = this
var $tip = this.tip()
var tipId = this.getUID(this.type)
this.setContent()
$tip.attr('id', tipId)
this.$element.attr('aria-describedby', tipId)
if (this.options.animation) $tip.addClass('fade')
var placement = typeof this.options.placement == 'function' ?
this.options.placement.call(this, $tip[0], this.$element[0]) :
this.options.placement
var autoToken = /\s?auto?\s?/i
var autoPlace = autoToken.test(placement)
if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
$tip
.detach()
.css({ top: 0, left: 0, display: 'block' })
.addClass(this.type + '-' + placement)
.data('bs.' + this.type, this)
this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
var pos = this.getPosition()
var actualWidth = $tip[0].offsetWidth
var actualHeight = $tip[0].offsetHeight
if (autoPlace) {
var origPlacement = placement
var $container = this.options.container ? $(this.options.container) : this.$element.parent()
var containerDim = this.getPosition($container)
placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top' :
placement == 'top' && pos.top - actualHeight < containerDim.top ? 'bottom' :
placement == 'right' && pos.right + actualWidth > containerDim.width ? 'left' :
placement == 'left' && pos.left - actualWidth < containerDim.left ? 'right' :
placement placement
$tip $(this._tip)
.removeClass(this.type + '-' + origPlacement) .removeClass(Tooltip._NAME + '-' + originalPlacement)
.addClass(this.type + '-' + placement) .addClass(Tooltip._NAME + '-' + placement)
} }
var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) return placement
this.applyPlacement(calculatedOffset, placement)
var complete = function () {
var prevHoverState = that.hoverState
that.$element.trigger('shown.bs.' + that.type)
that.hoverState = null
if (prevHoverState == 'out') that.leave(that)
} }
$.support.transition && this.$tip.hasClass('fade') ?
$tip /**
.one('bsTransitionEnd', complete) * @param {string} placement
.emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : * @param {Object} position
complete() * @param {number} actualWidth
} * @param {number} actualHeight
* @return {{left: number, top: number}}
* @private
*/
Tooltip.prototype._getCalculatedOffset = function (placement, position, actualWidth, actualHeight) {
return placement == Tooltip.Direction.BOTTOM ? { top: position.top + position.height, left: position.left + position.width / 2 - actualWidth / 2 } :
placement == Tooltip.Direction.TOP ? { top: position.top - actualHeight, left: position.left + position.width / 2 - actualWidth / 2 } :
placement == Tooltip.Direction.LEFT ? { top: position.top + position.height / 2 - actualHeight / 2, left: position.left - actualWidth } :
/* placement == Tooltip.Direction.RIGHT */ { top: position.top + position.height / 2 - actualHeight / 2, left: position.left + position.width }
} }
Tooltip.prototype.applyPlacement = function (offset, placement) {
var $tip = this.tip()
var width = $tip[0].offsetWidth
var height = $tip[0].offsetHeight
// manually read margins because getBoundingClientRect includes difference /**
var marginTop = parseInt($tip.css('margin-top'), 10) * @param {string} placement
var marginLeft = parseInt($tip.css('margin-left'), 10) * @param {Object} position
* @param {number} actualWidth
// we must check for NaN for IE9 * @param {number} actualHeight
if (isNaN(marginTop)) marginTop = 0 * @return {Object}
if (isNaN(marginLeft)) marginLeft = 0 * @private
*/
offset.top = offset.top + marginTop Tooltip.prototype._getViewportAdjustedDelta = function (placement, position, actualWidth, actualHeight) {
offset.left = offset.left + marginLeft
// $.fn.offset doesn't round pixel values
// so we use setOffset directly with our own function B-0
$.offset.setOffset($tip[0], $.extend({
using: function (props) {
$tip.css({
top: Math.round(props.top),
left: Math.round(props.left)
})
}
}, offset), 0)
$tip.addClass('in')
// check to see if placing tip in new offset caused the tip to resize itself
var actualWidth = $tip[0].offsetWidth
var actualHeight = $tip[0].offsetHeight
if (placement == 'top' && actualHeight != height) {
offset.top = offset.top + height - actualHeight
}
var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
if (delta.left) offset.left += delta.left
else offset.top += delta.top
var isVertical = /top|bottom/.test(placement)
var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
$tip.offset(offset)
this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
}
Tooltip.prototype.replaceArrow = function (delta, dimension, isHorizontal) {
this.arrow()
.css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
.css(isHorizontal ? 'top' : 'left', '')
}
Tooltip.prototype.setContent = function () {
var $tip = this.tip()
var title = this.getTitle()
$tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
$tip.removeClass('fade in tooltip-top tooltip-bottom tooltip-left tooltip-right')
}
Tooltip.prototype.hide = function (callback) {
var that = this
var $tip = this.tip()
var e = $.Event('hide.bs.' + this.type)
function complete() {
if (that.hoverState != 'in') $tip.detach()
that.$element
.removeAttr('aria-describedby')
.trigger('hidden.bs.' + that.type)
callback && callback()
}
this.$element.trigger(e)
if (e.isDefaultPrevented()) return
$tip.removeClass('in')
$.support.transition && this.$tip.hasClass('fade') ?
$tip
.one('bsTransitionEnd', complete)
.emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
complete()
this.hoverState = null
return this
}
Tooltip.prototype.fixTitle = function () {
var $e = this.$element
if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
$e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
}
}
Tooltip.prototype.hasContent = function () {
return this.getTitle()
}
Tooltip.prototype.getPosition = function ($element) {
$element = $element || this.$element
var el = $element[0]
var isBody = el.tagName == 'BODY'
var elRect = el.getBoundingClientRect()
if (elRect.width == null) {
// width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
}
var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
return $.extend({}, elRect, scroll, outerDims, elOffset)
}
Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
/* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
}
Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
var delta = { top: 0, left: 0 } var delta = { top: 0, left: 0 }
if (!this.$viewport) return delta
var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 if (!this._viewport) {
var viewportDimensions = this.getPosition(this.$viewport) return delta
}
var viewportPadding = this.config['viewport'] && this.config['viewport']['padding'] || 0
var viewportDimensions = this._getPosition(this._viewport)
if (placement === Tooltip.Direction.RIGHT || placement === Tooltip.Direction.LEFT) {
var topEdgeOffset = position.top - viewportPadding - viewportDimensions.scroll
var bottomEdgeOffset = position.top + viewportPadding - viewportDimensions.scroll + actualHeight
if (/right|left/.test(placement)) {
var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
if (topEdgeOffset < viewportDimensions.top) { // top overflow if (topEdgeOffset < viewportDimensions.top) { // top overflow
delta.top = viewportDimensions.top - topEdgeOffset delta.top = viewportDimensions.top - topEdgeOffset
} else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
} }
} else { } else {
var leftEdgeOffset = pos.left - viewportPadding var leftEdgeOffset = position.left - viewportPadding
var rightEdgeOffset = pos.left + viewportPadding + actualWidth var rightEdgeOffset = position.left + viewportPadding + actualWidth
if (leftEdgeOffset < viewportDimensions.left) { // left overflow if (leftEdgeOffset < viewportDimensions.left) { // left overflow
delta.left = viewportDimensions.left - leftEdgeOffset delta.left = viewportDimensions.left - leftEdgeOffset
} else if (rightEdgeOffset > viewportDimensions.width) { // right overflow } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
} }
@ -381,92 +664,205 @@
return delta return delta
} }
Tooltip.prototype.getTitle = function () {
var title
var $e = this.$element
var o = this.options
title = $e.attr('data-original-title') /**
|| (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) * @param {Element=} opt_element
* @return {Object}
* @private
*/
Tooltip.prototype._getPosition = function (opt_element) {
var element = opt_element || this.element
var isBody = element.tagName == 'BODY'
var rect = element.getBoundingClientRect()
var offset = isBody ? { top: 0, left: 0 } : $(element).offset()
var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : this.element.scrollTop }
var outerDims = isBody ? { width: window.innerWidth, height: window.innerHeight } : null
return title return $.extend({}, rect, scroll, outerDims, offset)
}
Tooltip.prototype.getUID = function (prefix) {
do prefix += ~~(Math.random() * 1000000)
while (document.getElementById(prefix))
return prefix
}
Tooltip.prototype.tip = function () {
return (this.$tip = this.$tip || $(this.options.template))
}
Tooltip.prototype.arrow = function () {
return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
}
Tooltip.prototype.enable = function () {
this.enabled = true
}
Tooltip.prototype.disable = function () {
this.enabled = false
}
Tooltip.prototype.toggleEnabled = function () {
this.enabled = !this.enabled
}
Tooltip.prototype.toggle = function (e) {
var self = this
if (e) {
self = $(e.currentTarget).data('bs.' + this.type)
if (!self) {
self = new this.constructor(e.currentTarget, this.getDelegateOptions())
$(e.currentTarget).data('bs.' + this.type, self)
}
}
self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
}
Tooltip.prototype.destroy = function () {
var that = this
clearTimeout(this.timeout)
this.hide(function () {
that.$element.off('.' + that.type).removeData('bs.' + that.type)
})
} }
// TOOLTIP PLUGIN DEFINITION /**
// ========================= * @param {{left: number, top: number}} offset
* @param {string} placement
* @private
*/
Tooltip.prototype._applyCalculatedPlacement = function (offset, placement) {
var tip = this.getTipElement()
var width = tip.offsetWidth
var height = tip.offsetHeight
function Plugin(option) { // manually read margins because getBoundingClientRect includes difference
return this.each(function () { var marginTop = parseInt(tip.style.marginTop, 10)
var $this = $(this) var marginLeft = parseInt(tip.style.marginLeft, 10)
var data = $this.data('bs.tooltip')
var options = typeof option == 'object' && option
if (!data && option == 'destroy') return // we must check for NaN for ie 8/9
if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) if (isNaN(marginTop)) {
if (typeof option == 'string') data[option]() marginTop = 0
}) }
if (isNaN(marginLeft)) {
marginLeft = 0
} }
var old = $.fn.tooltip offset.top = offset.top + marginTop
offset.left = offset.left + marginLeft
$.fn.tooltip = Plugin // $.fn.offset doesn't round pixel values
$.fn.tooltip.Constructor = Tooltip // so we use setOffset directly with our own function B-0
$.offset.setOffset(tip, $.extend({
using: function (props) {
tip.style.top = Math.round(props.top) + 'px'
tip.style.left = Math.round(props.left) + 'px'
}
}, offset), 0)
$(tip).addClass(Tooltip._ClassName.IN)
// check to see if placing tip in new offset caused the tip to resize itself
var actualWidth = tip.offsetWidth
var actualHeight = tip.offsetHeight
if (placement == Tooltip.Direction.TOP && actualHeight != height) {
offset.top = offset.top + height - actualHeight
}
var delta = this._getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
if (delta.left) {
offset.left += delta.left
} else {
offset.top += delta.top
}
var isVertical = placement === Tooltip.Direction.TOP || placement === Tooltip.Direction.BOTTOM
var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
$(tip).offset(offset)
this._replaceArrow(arrowDelta, tip[arrowOffsetPosition], isVertical)
}
// TOOLTIP NO CONFLICT /**
// =================== * @param {number} delta
* @param {number} dimension
* @param {boolean} isHorizontal
* @private
*/
Tooltip.prototype._replaceArrow = function (delta, dimension, isHorizontal) {
var arrow = this.getArrowElement()
$.fn.tooltip.noConflict = function () { arrow.style[isHorizontal ? 'left' : 'top'] = 50 * (1 - delta / dimension) + '%'
$.fn.tooltip = old arrow.style[isHorizontal ? 'top' : 'left'] = ''
}
/**
* @private
*/
Tooltip.prototype._fixTitle = function () {
if (this.element.getAttribute('title') || typeof this.element.getAttribute('data-original-title') != 'string') {
this.element.setAttribute('data-original-title', this.element.getAttribute('title') || '')
this.element.setAttribute('title', '')
}
}
/**
* @param {Event=} opt_event
* @param {Object=} opt_context
* @private
*/
Tooltip.prototype._enter = function (opt_event, opt_context) {
var dataKey = this.getDataKey()
var context = opt_context || $(opt_event.currentTarget).data(dataKey)
if (context && context._tip && context._tip.offsetWidth) {
context._hoverState = Tooltip._HoverState.IN
return
}
if (!context) {
context = new this.constructor(opt_event.currentTarget, this._getDelegateConfig())
$(opt_event.currentTarget).data(dataKey, context)
}
clearTimeout(context._timeout)
context._hoverState = Tooltip._HoverState.IN
if (!context.config['delay'] || !context.config['delay']['show']) {
context['show']()
return
}
context._timeout = setTimeout(function () {
if (context._hoverState == Tooltip._HoverState.IN) {
context['show']()
}
}, context.config['delay']['show'])
}
/**
* @param {Event=} opt_event
* @param {Object=} opt_context
* @private
*/
Tooltip.prototype._leave = function (opt_event, opt_context) {
var dataKey = this.getDataKey()
var context = opt_context || $(opt_event.currentTarget).data(dataKey)
if (!context) {
context = new this.constructor(opt_event.currentTarget, this._getDelegateConfig())
$(opt_event.currentTarget).data(dataKey, context)
}
clearTimeout(context._timeout)
context._hoverState = Tooltip._HoverState.OUT
if (!context.config['delay'] || !context.config['delay']['hide']) {
context['hide']()
return
}
context._timeout = setTimeout(function () {
if (context._hoverState == Tooltip._HoverState.OUT) {
context['hide']()
}
}, context.config['delay']['hide'])
}
/**
* ------------------------------------------------------------------------
* jQuery Interface + noConflict implementaiton
* ------------------------------------------------------------------------
*/
/**
* @const
* @type {Function}
*/
$.fn[Tooltip._NAME] = Tooltip._jQueryInterface
/**
* @const
* @type {Function}
*/
$.fn[Tooltip._NAME]['Constructor'] = Tooltip
/**
* @const
* @type {Function}
*/
$.fn[Tooltip._NAME]['noConflict'] = function () {
$.fn[Tooltip._NAME] = Tooltip._JQUERY_NO_CONFLICT
return this return this
} }
}(jQuery);

165
js/util.js Normal file
View File

@ -0,0 +1,165 @@
/** =======================================================================
* Bootstrap: util.js v4.0.0
* http://getbootstrap.com/javascript/#alerts
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ========================================================================
* @fileoverview - Bootstrap's private util helper. Adds private util
* helpers for things like accesibility and transitions. These methods are
* shared across all bootstrap plugins.
* ========================================================================
*/
'use strict';
/**
* @type {Object}
*/
var Bootstrap = {}
/**
* @const
* @type {string}
*/
Bootstrap.TRANSITION_END = 'bsTransitionEnd'
/**
* @const
* @type {Object}
*/
Bootstrap.TransitionEndEvent = {
'WebkitTransition' : 'webkitTransitionEnd',
'MozTransition' : 'transitionend',
'OTransition' : 'oTransitionEnd otransitionend',
'transition' : 'transitionend'
}
/**
* @param {Function} childConstructor
* @param {Function} parentConstructor
*/
Bootstrap.inherits = function(childConstructor, parentConstructor) {
/** @constructor */
function tempConstructor() {}
tempConstructor.prototype = parentConstructor.prototype
childConstructor.prototype = new tempConstructor()
/** @override */
childConstructor.prototype.constructor = childConstructor
}
/**
* @param {Element} element
* @return {string|null}
*/
Bootstrap.getSelectorFromElement = function (element) {
var selector = element.getAttribute('data-target')
if (!selector) {
selector = element.getAttribute('href') || ''
selector = /^#[a-z]/i.test(selector) ? selector : null
}
return selector
}
/**
* @param {string} prefix
* @return {string}
*/
Bootstrap.getUID = function (prefix) {
do prefix += ~~(Math.random() * 1000000)
while (document.getElementById(prefix))
return prefix
}
/**
* @return {Object}
*/
Bootstrap.getSpecialTransitionEndEvent = function () {
return {
bindType: Bootstrap.transition.end,
delegateType: Bootstrap.transition.end,
handle: /** @param {jQuery.Event} event */ (function (event) {
if ($(event.target).is(this)) {
return event.handleObj.handler.apply(this, arguments)
}
})
}
}
/**
* @param {Element} element
*/
Bootstrap.reflow = function (element) {
new Function('bs',"return bs")(element.offsetHeight)
}
/**
* @return {Object|boolean}
*/
Bootstrap.transitionEndTest = function () {
if (window['QUnit']) {
return false
}
var el = document.createElement('bootstrap')
for (var name in Bootstrap.TransitionEndEvent) {
if (el.style[name] !== undefined) {
return { end: Bootstrap.TransitionEndEvent[name] }
}
}
return false
}
/**
* @param {number} duration
* @this {Element}
* @return {Object}
*/
Bootstrap.transitionEndEmulator = function (duration) {
var called = false
$(this).one(Bootstrap.TRANSITION_END, function () {
called = true
})
var callback = function () {
if (!called) {
$(this).trigger(Bootstrap.transition.end)
}
}.bind(this)
setTimeout(callback, duration)
return this
}
/**
* ------------------------------------------------------------------------
* jQuery Interface
* ------------------------------------------------------------------------
*/
$.fn.emulateTransitionEnd = Bootstrap.transitionEndEmulator
$(function () {
Bootstrap.transition = Bootstrap.transitionEndTest()
if (!Bootstrap.transition) {
return
}
$.event.special[Bootstrap.TRANSITION_END] = Bootstrap.getSpecialTransitionEndEvent()
})

View File

@ -36,8 +36,9 @@
"grunt": "~0.4.5", "grunt": "~0.4.5",
"grunt-autoprefixer": "~2.2.0", "grunt-autoprefixer": "~2.2.0",
"grunt-banner": "~0.3.1", "grunt-banner": "~0.3.1",
"grunt-closure-tools": "^0.9.7",
"grunt-contrib-clean": "~0.6.0", "grunt-contrib-clean": "~0.6.0",
"grunt-contrib-compress": "~0.13.0", "grunt-contrib-compress": "^0.13.0",
"grunt-contrib-concat": "~0.5.0", "grunt-contrib-concat": "~0.5.0",
"grunt-contrib-connect": "~0.9.0", "grunt-contrib-connect": "~0.9.0",
"grunt-contrib-copy": "~0.7.0", "grunt-contrib-copy": "~0.7.0",
@ -63,6 +64,8 @@
"markdown-it": "^3.0.4", "markdown-it": "^3.0.4",
"mq4-hover-shim": "^0.1.0", "mq4-hover-shim": "^0.1.0",
"npm-shrinkwrap": "^200.0.0", "npm-shrinkwrap": "^200.0.0",
"remarkable": "~1.6.0",
"superstartup-closure-compiler": "^0.1.6",
"time-grunt": "~1.0.0" "time-grunt": "~1.0.0"
}, },
"engines": { "engines": {