bootstrap onto closure

This commit is contained in:
fat 2015-01-03 13:58:44 -08:00
parent aed1cd3121
commit 834220ea20
38 changed files with 10739 additions and 4110 deletions

View File

@ -108,33 +108,79 @@ module.exports = function (grunt) {
},
bootstrap: {
src: [
'js/hover.js',
mq4HoverShim.featureDetector.umdGlobal,
'js/transition.js',
'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/scrollspy.js',
'js/tab.js',
'js/affix.js'
'js/tab.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: {
options: {
preserveComments: 'some'
},
core: {
src: '<%= concat.bootstrap.dest %>',
dest: 'dist/js/<%= pkg.name %>.min.js'
},
docsJs: {
src: configBridge.paths.docsJs,
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']);
// JS distribution task.
grunt.registerTask('dist-js', ['concat', 'uglify:core', 'commonjs']);
grunt.registerTask('dist-js', ['concat', 'closureCompiler', 'commonjs']);
grunt.registerTask('test-scss', ['scsslint:scss']);

6039
dist/js/bootstrap.js vendored

File diff suppressed because it is too large Load Diff

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.
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/button.js')
require('../../js/carousel.js')
require('../../js/collapse.js')
require('../../js/dropdown.js')
require('../../js/modal.js')
require('../../js/scrollspy.js')
require('../../js/tooltip.js')
require('../../js/popover.js')
require('../../js/scrollspy.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
* ========================================================================
* 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';
+function ($) {
'use strict';
// ALERT CLASS DEFINITION
// ======================
var dismiss = '[data-dismiss="alert"]'
var Alert = function (el) {
$(el).on('click', dismiss, this.close)
}
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()
/**
* 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))
}
}
// 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 () {
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 (typeof option == 'string') data[option].call($this)
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()
}
var old = $.fn.alert
$.fn.alert = Plugin
$.fn.alert.Constructor = Alert
alertInstance['close'](this)
}
}
// ALERT NO CONFLICT
// =================
/**
* Close the alert component
* @param {Element} element
*/
Alert.prototype['close'] = function (element) {
var rootElement = this._getRootElement(element)
var customEvent = this._triggerCloseEvent(rootElement)
$.fn.alert.noConflict = function () {
$.fn.alert = old
return this
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]
}
// ALERT DATA-API
// ==============
return parent
}
$(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
}(jQuery);
/**
* 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
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
* ========================================================================
* @fileoverview - Bootstrap's generic button component.
*
* Note (@fat): Deprecated "setState" imo, better solutions for managing a
* buttons state should exist outside this plugin.
*
* Public Methods & Properties:
*
* + $.button
* + $.button.noConflict
* + $.button.Constructor
* + $.button.Constructor.VERSION
* + $.button.Constructor.prototype.toggle
*
* ========================================================================
*/
'use strict';
+function ($) {
'use strict';
/**
* Our Button class.
* @param {Element!} element
* @constructor
*/
var Button = function (element) {
// BUTTON PUBLIC CLASS DEFINITION
// ==============================
/** @private {Element} */
this._element = element
var Button = function (element, options) {
this.$element = $(element)
this.options = $.extend({}, Button.DEFAULTS, options)
this.isLoading = false
}
Button.VERSION = '3.3.2'
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 () {
var $this = $(this)
var data = $this.data('bs.button')
var options = typeof option == 'object' && option
var data = $(this).data(Button._DATA_KEY)
if (!data) $this.data('bs.button', (data = new Button(this, options)))
if (option == 'toggle') data.toggle()
else if (option) data.setState(option)
})
if (!data) {
data = new Button(this)
$(this).data(Button._DATA_KEY, data)
}
var old = $.fn.button
$.fn.button = Plugin
$.fn.button.Constructor = Button
if (opt_config === 'toggle') {
data[opt_config]()
}
})
}
// BUTTON NO CONFLICT
// ==================
/**
* Toggle's the button active state
*/
Button.prototype['toggle'] = function () {
var triggerChangeEvent = true
var rootElement = $(this._element).closest(Button._Selector.DATA_TOGGLE)[0]
$.fn.button.noConflict = function () {
$.fn.button = old
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)
}
}
/**
* ------------------------------------------------------------------------
* jQuery Interface + noConflict implementaiton
* ------------------------------------------------------------------------
*/
/**
* @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
}
/**
* ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/
$(document)
.on('click.bs.button.data-api', Button._Selector.DATA_TOGGLE_CARROT, function (event) {
event.preventDefault()
var button = event.target
if (!$(button).hasClass(Button._ClassName.BUTTON)) {
button = $(button).closest(Button._Selector.BUTTON)
}
// BUTTON DATA-API
// ===============
$(document)
.on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
var $btn = $(e.target)
if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
Plugin.call($btn, 'toggle')
e.preventDefault()
Button._jQueryInterface.call($(button), 'toggle')
})
.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))
.on('focus.bs.button.data-api blur.bs.button.data-api', Button._Selector.DATA_TOGGLE_CARROT, function (event) {
var button = $(event.target).closest(Button._Selector.BUTTON)[0]
$(button).toggleClass(Button._ClassName.FOCUS, /^focus(in)?$/.test(event.type))
})
}(jQuery);

View File

@ -1,237 +1,576 @@
/* ========================================================================
* Bootstrap: carousel.js v3.3.2
/** =======================================================================
* Bootstrap: carousel.js v4.0.0
* http://getbootstrap.com/javascript/#carousel
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
* ========================================================================
* @fileoverview - Bootstrap's carousel. A slideshow component for cycling
* through elements, like a carousel. Nested carousels are not supported.
*
* Public Methods & Properties:
*
* + $.carousel
* + $.carousel.noConflict
* + $.carousel.Constructor
* + $.carousel.Constructor.VERSION
* + $.carousel.Constructor.Defaults
* + $.carousel.Constructor.Defaults.interval
* + $.carousel.Constructor.Defaults.pause
* + $.carousel.Constructor.Defaults.wrap
* + $.carousel.Constructor.Defaults.keyboard
* + $.carousel.Constructor.Defaults.slide
* + $.carousel.Constructor.prototype.next
* + $.carousel.Constructor.prototype.prev
* + $.carousel.Constructor.prototype.pause
* + $.carousel.Constructor.prototype.cycle
*
* ========================================================================
*/
'use strict';
+function ($) {
'use strict';
/**
* Our carousel class.
* @param {Element!} element
* @param {Object=} opt_config
* @constructor
*/
var Carousel = function (element, opt_config) {
// CAROUSEL CLASS DEFINITION
// =========================
/** @private {Element} */
this._element = $(element)[0]
var Carousel = function (element, options) {
this.$element = $(element)
this.$indicators = this.$element.find('.carousel-indicators')
this.options = options
this.paused =
this.sliding =
this.interval =
this.$active =
this.$items = null
/** @private {Element} */
this._indicatorsElement = $(this._element).find(Carousel._Selector.INDICATORS)[0]
this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
/** @private {?Object} */
this._config = opt_config || null
this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
.on('mouseenter.bs.carousel', $.proxy(this.pause, this))
.on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
}
/** @private {boolean} */
this._isPaused = false
Carousel.VERSION = '3.3.2'
/** @private {boolean} */
this._isSliding = false
Carousel.TRANSITION_DURATION = 600
/** @private {?number} */
this._interval = null
Carousel.DEFAULTS = {
interval: 5000,
pause: 'hover',
wrap: true,
keyboard: true
}
/** @private {?Element} */
this._activeElement = null
Carousel.prototype.keydown = function (e) {
if (/input|textarea/i.test(e.target.tagName)) return
switch (e.which) {
case 37: this.prev(); break
case 39: this.next(); break
default: return
}
/** @private {?Array} */
this._items = null
e.preventDefault()
}
this._addEventListeners()
Carousel.prototype.cycle = function (e) {
e || (this.paused = false)
this.interval && clearInterval(this.interval)
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 () {
var $this = $(this)
var data = $this.data('bs.carousel')
var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
var action = typeof option == 'string' ? option : options.slide
var data = $(this).data(Carousel._DATA_KEY)
var config = $.extend({}, Carousel['Defaults'], $(this).data(), typeof opt_config == 'object' && opt_config)
var action = typeof opt_config == 'string' ? opt_config : config.slide
if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
if (typeof option == 'number') data.to(option)
else if (action) data[action]()
else if (options.interval) data.pause().cycle()
if (!data) {
data = new Carousel(this, config)
$(this).data(Carousel._DATA_KEY, data)
}
if (typeof opt_config == 'number') {
data.to(opt_config)
} else if (action) {
data[action]()
} else if (config.interval) {
data['pause']()
data['cycle']()
}
})
}
/**
* Click handler for data api
* @param {Event} event
* @this {Element}
* @private
*/
Carousel._dataApiClickHandler = function (event) {
var selector = Bootstrap.getSelectorFromElement(this)
if (!selector) {
return
}
var old = $.fn.carousel
var target = $(selector)[0]
$.fn.carousel = Plugin
$.fn.carousel.Constructor = Carousel
// CAROUSEL NO CONFLICT
// ====================
$.fn.carousel.noConflict = function () {
$.fn.carousel = old
return this
if (!target || !$(target).hasClass(Carousel._ClassName.CAROUSEL)) {
return
}
var config = $.extend({}, $(target).data(), $(this).data())
// CAROUSEL DATA-API
// =================
var slideIndex = this.getAttribute('data-slide-to')
if (slideIndex) {
config.interval = false
}
var clickHandler = function (e) {
var href
var $this = $(this)
var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
if (!$target.hasClass('carousel')) return
var options = $.extend({}, $target.data(), $this.data())
var slideIndex = $this.attr('data-slide-to')
if (slideIndex) options.interval = false
Plugin.call($target, options)
Carousel._jQueryInterface.call($(target), config)
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
}
$(document)
.on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
.on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
if ($(this._element).find(Carousel._Selector.NEXT_PREV)[0] && Bootstrap.transition) {
$(this._element).trigger(Bootstrap.transition.end)
this['cycle'](true)
}
$(window).on('load', function () {
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)
.on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', Carousel._dataApiClickHandler)
$(window).on('load', function () {
$('[data-ride="carousel"]').each(function () {
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
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
* ========================================================================
* @fileoverview - Bootstrap's collapse plugin. Flexible support for
* collapsible components like accordions and navigation.
*
* Public Methods & Properties:
*
* + $.carousel
* + $.carousel.noConflict
* + $.carousel.Constructor
* + $.carousel.Constructor.VERSION
* + $.carousel.Constructor.Defaults
* + $.carousel.Constructor.Defaults.toggle
* + $.carousel.Constructor.Defaults.trigger
* + $.carousel.Constructor.Defaults.parent
* + $.carousel.Constructor.prototype.toggle
* + $.carousel.Constructor.prototype.show
* + $.carousel.Constructor.prototype.hide
*
* ========================================================================
*/
'use strict';
+function ($) {
'use strict';
/**
* Our collapse class.
* @param {Element!} element
* @param {Object=} opt_config
* @constructor
*/
var Collapse = function (element, opt_config) {
// COLLAPSE PUBLIC CLASS DEFINITION
// ================================
/** @private {Element} */
this._element = element
var Collapse = function (element, options) {
this.$element = $(element)
this.options = $.extend({}, Collapse.DEFAULTS, options)
this.$trigger = $(this.options.trigger).filter('[href="#' + element.id + '"], [data-target="#' + element.id + '"]')
this.transitioning = null
/** @private {Object} */
this._config = $.extend({}, Collapse['Defaults'], opt_config)
if (this.options.parent) {
this.$parent = this.getParent()
} else {
this.addAriaAndCollapsedClass(this.$element, this.$trigger)
/** @private {Element} */
this._trigger = typeof this._config['trigger'] == 'string' ?
$(this._config['trigger'])[0] : this._config['trigger']
/** @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 () {
var $this = $(this)
var data = $this.data('bs.collapse')
var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
var data = $this.data(Collapse._DATA_KEY)
var config = $.extend({}, Collapse['Defaults'], $this.data(), typeof opt_config == 'object' && opt_config)
if (!data && options.toggle && option == 'show') options.toggle = false
if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
if (typeof option == 'string') data[option]()
})
if (!data && config['toggle'] && opt_config == 'show') {
config['toggle'] = false
}
var old = $.fn.collapse
if (!data) {
data = new Collapse(this, config)
$this.data(Collapse._DATA_KEY, data)
}
$.fn.collapse = Plugin
$.fn.collapse.Constructor = Collapse
if (typeof opt_config == 'string') {
data[opt_config]()
}
})
}
// COLLAPSE NO CONFLICT
// ====================
/**
* Function for getting target element from element
* @return {Element}
* @private
*/
Collapse._getTargetFromElement = function (element) {
var selector = Bootstrap.getSelectorFromElement(element)
$.fn.collapse.noConflict = function () {
$.fn.collapse = old
return selector ? $(selector)[0] : null
}
/**
* Toggles the collapse element based on the presence of the 'in' class
*/
Collapse.prototype['toggle'] = function () {
if ($(this._element).hasClass(Collapse._ClassName.IN)) {
this['hide']()
} else {
this['show']()
}
}
/**
* 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
}
}
// COLLAPSE DATA-API
// =================
/**
* ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/
$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
var $this = $(this)
$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (event) {
event.preventDefault()
if (!$this.attr('data-target')) e.preventDefault()
var target = Collapse._getTargetFromElement(this)
var $target = getTargetFromTrigger($this)
var data = $target.data('bs.collapse')
var option = data ? 'toggle' : $.extend({}, $this.data(), { trigger: this })
var data = $(target).data(Collapse._DATA_KEY)
var config = data ? 'toggle' : $.extend({}, $(this).data(), { trigger: this })
Plugin.call($target, option)
})
}(jQuery);
Collapse._jQueryInterface.call($(target), config)
})

View File

@ -1,161 +1,322 @@
/* ========================================================================
* Bootstrap: dropdown.js v3.3.2
* http://getbootstrap.com/javascript/#dropdowns
/** =======================================================================
* Bootstrap: dropdown.js v4.0.0
* http://getbootstrap.com/javascript/#dropdown
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
* ========================================================================
* @fileoverview - Add dropdown menus to nearly anything with this simple
* plugin, including the navbar, tabs, and pills.
*
* Public Methods & Properties:
*
* + $.dropdown
* + $.dropdown.noConflict
* + $.dropdown.Constructor
* + $.dropdown.Constructor.VERSION
* + $.dropdown.Constructor.prototype.toggle
*
* ========================================================================
*/
'use strict';
+function ($) {
'use strict';
/**
* Our dropdown class.
* @param {Element!} element
* @constructor
*/
var Dropdown = function (element) {
$(element).on('click.bs.dropdown', this['toggle'])
}
// DROPDOWN CLASS DEFINITION
// =========================
var backdrop = '.dropdown-backdrop'
var toggle = '[data-toggle="dropdown"]'
var Dropdown = function (element) {
$(element).on('click.bs.dropdown', this.toggle)
/**
* @const
* @type {string}
*/
Dropdown['VERSION'] = '4.0.0'
/**
* @const
* @type {string}
* @private
*/
Dropdown._NAME = 'dropdown'
/**
* @const
* @type {string}
* @private
*/
Dropdown._DATA_KEY = 'bs.dropdown'
/**
* @const
* @type {Function}
* @private
*/
Dropdown._JQUERY_NO_CONFLICT = $.fn[Dropdown._NAME]
/**
* @const
* @enum {string}
* @private
*/
Dropdown._Event = {
HIDE : 'hide.bs.dropdown',
HIDDEN : 'hidden.bs.dropdown',
SHOW : 'show.bs.dropdown',
SHOWN : 'shown.bs.dropdown'
}
/**
* @const
* @enum {string}
* @private
*/
Dropdown._ClassName = {
BACKDROP : 'dropdown-backdrop',
DISABLED : 'disabled',
OPEN : 'open'
}
/**
* @const
* @enum {string}
* @private
*/
Dropdown._Selector = {
BACKDROP : '.dropdown-backdrop',
DATA_TOGGLE : '[data-toggle="dropdown"]',
FORM_CHILD : '.dropdown form',
ROLE_MENU : '[role="menu"]',
ROLE_LISTBOX : '[role="listbox"]',
NAVBAR_NAV : '.navbar-nav',
VISIBLE_ITEMS : '[role="menu"] li:not(.divider) a, [role="listbox"] li:not(.divider) a'
}
/**
* Provides the jQuery Interface for the alert component.
* @param {string=} opt_config
* @this {jQuery}
* @return {jQuery}
* @private
*/
Dropdown._jQueryInterface = function (opt_config) {
return this.each(function () {
var data = $(this).data(Dropdown._DATA_KEY)
if (!data) {
$(this).data(Dropdown._DATA_KEY, (data = new Dropdown(this)))
}
Dropdown.VERSION = '3.3.2'
if (typeof opt_config === 'string') {
data[opt_config].call(this)
}
})
}
Dropdown.prototype.toggle = function (e) {
var $this = $(this)
if ($this.is('.disabled, :disabled')) return
var $parent = getParent($this)
var isActive = $parent.hasClass('open')
clearMenus()
if (!isActive) {
if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
// if mobile we use a backdrop because click events don't delegate
$('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
/**
* @param {Event=} opt_event
* @private
*/
Dropdown._clearMenus = function (opt_event) {
if (opt_event && opt_event.which == 3) {
return
}
var relatedTarget = { relatedTarget: this }
$parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
if (e.isDefaultPrevented()) return
$this
.trigger('focus')
.attr('aria-expanded', 'true')
$parent
.toggleClass('open')
.trigger('shown.bs.dropdown', relatedTarget)
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
}
Dropdown.prototype.keydown = function (e) {
if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
var $this = $(this)
e.preventDefault()
e.stopPropagation()
if ($this.is('.disabled, :disabled')) return
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')
if ('ontouchstart' in document.documentElement && !$(parent).closest(Dropdown._Selector.NAVBAR_NAV).length) {
// if mobile we use a backdrop because click events don't delegate
var dropdown = document.createElement('div')
dropdown.className = Dropdown._ClassName.BACKDROP
this.parentNode.insertBefore(this, dropdown)
$(dropdown).on('click', Dropdown._clearMenus)
}
var desc = ' li:not(.divider):visible a'
var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc)
var relatedTarget = { 'relatedTarget': this }
var showEvent = $.Event(Dropdown._Event.SHOW, relatedTarget)
if (!$items.length) return
$(parent).trigger(showEvent)
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')
if (showEvent.isDefaultPrevented()) {
return
}
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 }
this.focus()
this.setAttribute('aria-expanded', 'true')
if (!$parent.hasClass('open')) return
$(parent).toggleClass(Dropdown._ClassName.OPEN)
$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
$(parent).trigger(Dropdown._Event.SHOWN, 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()
}
return false
}
// DROPDOWN PLUGIN DEFINITION
// ==========================
/**
* ------------------------------------------------------------------------
* jQuery Interface + noConflict implementaiton
* ------------------------------------------------------------------------
*/
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.dropdown')
if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
if (typeof option == 'string') data[option].call($this)
})
}
var old = $.fn.dropdown
$.fn.dropdown = Plugin
$.fn.dropdown.Constructor = Dropdown
/**
* @const
* @type {Function}
*/
$.fn[Dropdown._NAME] = Dropdown._jQueryInterface
// DROPDOWN NO CONFLICT
// ====================
/**
* @const
* @type {Function}
*/
$.fn[Dropdown._NAME]['Constructor'] = Dropdown
$.fn.dropdown.noConflict = function () {
$.fn.dropdown = old
/**
* @const
* @type {Function}
*/
$.fn[Dropdown._NAME]['noConflict'] = function () {
$.fn[Dropdown._NAME] = Dropdown._JQUERY_NO_CONFLICT
return this
}
}
// APPLY TO STANDARD DROPDOWN ELEMENTS
// ===================================
/**
* ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/
$(document)
.on('click.bs.dropdown.data-api', clearMenus)
.on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
.on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
.on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
.on('keydown.bs.dropdown.data-api', '[role="menu"]', Dropdown.prototype.keydown)
.on('keydown.bs.dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown)
}(jQuery);
$(document)
.on('click.bs.dropdown.data-api', Dropdown._clearMenus)
.on('click.bs.dropdown.data-api', Dropdown._Selector.FORM_CHILD, function (e) { e.stopPropagation() })
.on('click.bs.dropdown.data-api', Dropdown._Selector.DATA_TOGGLE, Dropdown.prototype['toggle'])
.on('keydown.bs.dropdown.data-api', Dropdown._Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler)
.on('keydown.bs.dropdown.data-api', Dropdown._Selector.ROLE_MENU, Dropdown._dataApiKeydownHandler)
.on('keydown.bs.dropdown.data-api', Dropdown._Selector.ROLE_LISTBOX, Dropdown._dataApiKeydownHandler)

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

File diff suppressed because it is too large Load Diff

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

View File

@ -1,113 +1,283 @@
/* ========================================================================
* Bootstrap: popover.js v3.3.2
/** =======================================================================
* Bootstrap: popover.js v4.0.0
* http://getbootstrap.com/javascript/#popovers
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
* ========================================================================
* @fileoverview - Bootstrap's popover plugin - extends tooltip.
*
* Public Methods & Properties:
*
* + $.popover
* + $.popover.noConflict
* + $.popover.Constructor
* + $.popover.Constructor.VERSION
* + $.popover.Constructor.Defaults
* + $.popover.Constructor.Defaults.container
* + $.popover.Constructor.Defaults.animation
* + $.popover.Constructor.Defaults.placement
* + $.popover.Constructor.Defaults.selector
* + $.popover.Constructor.Defaults.template
* + $.popover.Constructor.Defaults.trigger
* + $.popover.Constructor.Defaults.title
* + $.popover.Constructor.Defaults.content
* + $.popover.Constructor.Defaults.delay
* + $.popover.Constructor.Defaults.html
* + $.popover.Constructor.Defaults.viewport
* + $.popover.Constructor.Defaults.viewport.selector
* + $.popover.Constructor.Defaults.viewport.padding
* + $.popover.Constructor.prototype.enable
* + $.popover.Constructor.prototype.disable
* + $.popover.Constructor.prototype.destroy
* + $.popover.Constructor.prototype.toggleEnabled
* + $.popover.Constructor.prototype.toggle
* + $.popover.Constructor.prototype.show
* + $.popover.Constructor.prototype.hide
*
* ========================================================================
*/
+function ($) {
'use strict';
'use strict';
// POPOVER PUBLIC CLASS DEFINITION
// ===============================
var Popover = function (element, options) {
this.init('popover', element, options)
if (!Tooltip) throw new Error('Popover requires tooltip.js')
/**
* Our tooltip class.
* @param {Element!} element
* @param {Object=} opt_config
* @constructor
* @extends {Tooltip}
*/
var Popover = function (element, opt_config) {
Tooltip.apply(this, arguments)
}
Bootstrap.inherits(Popover, Tooltip)
/**
* @const
* @type {string}
*/
Popover['VERSION'] = '4.0.0'
/**
* @const
* @type {Object}
*/
Popover['Defaults'] = $.extend({}, $.fn['tooltip']['Constructor']['Defaults'], {
'placement': 'right',
'trigger': 'click',
'content': '',
'template': '<div class="popover" role="tooltip"><div class="popover-arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
})
/**
* @const
* @type {string}
* @private
*/
Popover._NAME = 'popover'
/**
* @const
* @type {string}
* @private
*/
Popover._DATA_KEY = 'bs.popover'
/**
* @const
* @enum {string}
* @private
*/
Popover._Event = {
HIDE : 'hide.bs.popover',
HIDDEN : 'hidden.bs.popover',
SHOW : 'show.bs.popover',
SHOWN : 'shown.bs.popover'
}
/**
* @const
* @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 (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
if (!data) {
data = new Popover(this, config)
$(this).data(Popover._DATA_KEY, data)
}
Popover.VERSION = '3.3.2'
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>'
if (typeof opt_config === 'string') {
data[opt_config]()
}
})
}
// NOTE: POPOVER EXTENDS tooltip.js
// ================================
/**
* @return {string}
* @protected
*/
Popover.prototype.getName = function () {
return Popover._NAME
}
Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
Popover.prototype.constructor = Popover
/**
* @override
*/
Popover.prototype.getDataKey = function () {
return Popover._DATA_KEY
}
Popover.prototype.getDefaults = function () {
return Popover.DEFAULTS
/**
* @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
}
Popover.prototype.setContent = function () {
var $tip = this.tip()
var title = this.getTitle()
var content = this.getContent()
$tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
$tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
// we use append for html objects to maintain js events
$(tip).find(Popover._Selector.CONTENT).children().detach().end()[
this.config['html'] ? (typeof content == 'string' ? 'html' : 'append') : 'text'
](content)
$tip.removeClass('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
// this manually by checking the contents.
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
for (var direction in Tooltip.Direction) {
$(tip).removeClass(Popover._NAME + '-' + Tooltip.Direction[direction])
}
}
// POPOVER PLUGIN DEFINITION
// =========================
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.popover')
var options = typeof option == 'object' && option
if (!data && 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.isWithContent = function () {
return this.getTitle() || this._getContent()
}
// POPOVER NO CONFLICT
// ===================
/**
* @override
*/
Popover.prototype.getTipElement = function () {
return (this.tip = this.tip || $(this.config['template'])[0])
}
$.fn.popover.noConflict = function () {
$.fn.popover = old
/**
* @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'])
}
/**
* ------------------------------------------------------------------------
* 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
}
}(jQuery);
}

View File

@ -1,175 +1,346 @@
/* ========================================================================
* Bootstrap: scrollspy.js v3.3.2
/** =======================================================================
* Bootstrap: scrollspy.js v4.0.0
* http://getbootstrap.com/javascript/#scrollspy
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
* ========================================================================
* @fileoverview - Bootstrap's scrollspy plugin.
*
* Public Methods & Properties:
*
* + $.scrollspy
* + $.scrollspy.noConflict
* + $.scrollspy.Constructor
* + $.scrollspy.Constructor.VERSION
* + $.scrollspy.Constructor.Defaults
* + $.scrollspy.Constructor.Defaults.offset
* + $.scrollspy.Constructor.prototype.refresh
*
* ========================================================================
*/
'use strict';
+function ($) {
'use strict';
/**
* Our scrollspy class.
* @param {Element!} element
* @param {Object=} opt_config
* @constructor
*/
function ScrollSpy(element, opt_config) {
// SCROLLSPY CLASS DEFINITION
// ==========================
/** @private {Element|Window} */
this._scrollElement = element.tagName == 'BODY' ? window : element
function ScrollSpy(element, options) {
var process = $.proxy(this.process, this)
/** @private {Object} */
this._config = $.extend({}, ScrollSpy['Defaults'], opt_config)
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
/** @private {string} */
this._selector = (this._config.target || '') + ' .nav li > a'
this.$scrollElement.on('scroll.bs.scrollspy', process)
this.refresh()
this.process()
/** @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()
}
/**
* @const
* @type {string}
*/
ScrollSpy['VERSION'] = '4.0.0'
/**
* @const
* @type {Object}
*/
ScrollSpy['Defaults'] = {
'offset': 10
}
/**
* @const
* @type {string}
* @private
*/
ScrollSpy._NAME = 'scrollspy'
/**
* @const
* @type {string}
* @private
*/
ScrollSpy._DATA_KEY = 'bs.scrollspy'
/**
* @const
* @type {Function}
* @private
*/
ScrollSpy._JQUERY_NO_CONFLICT = $.fn[ScrollSpy._NAME]
/**
* @const
* @enum {string}
* @private
*/
ScrollSpy._Event = {
ACTIVATE: 'activate.bs.scrollspy'
}
/**
* @const
* @enum {string}
* @private
*/
ScrollSpy._ClassName = {
DROPDOWN_MENU : 'dropdown-menu',
ACTIVE : 'active'
}
/**
* @const
* @enum {string}
* @private
*/
ScrollSpy._Selector = {
DATA_SPY : '[data-spy="scroll"]',
ACTIVE : '.active',
LI_DROPDOWN : 'li.dropdown',
LI : 'li'
}
/**
* @param {Object=} opt_config
* @this {jQuery}
* @return {jQuery}
* @private
*/
ScrollSpy._jQueryInterface = function (opt_config) {
return this.each(function () {
var data = $(this).data(ScrollSpy._DATA_KEY)
var config = typeof opt_config === 'object' && opt_config || null
if (!data) {
data = new ScrollSpy(this, config)
$(this).data(ScrollSpy._DATA_KEY, data)
}
ScrollSpy.VERSION = '3.3.2'
ScrollSpy.DEFAULTS = {
offset: 10
if (typeof opt_config === 'string') {
data[opt_config]()
}
})
}
ScrollSpy.prototype.getScrollHeight = function () {
return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
}
ScrollSpy.prototype.refresh = function () {
/**
* Refresh the scrollspy target cache
*/
ScrollSpy.prototype['refresh'] = function () {
var offsetMethod = 'offset'
var offsetBase = 0
if (!$.isWindow(this.$scrollElement[0])) {
if (this._scrollElement !== this._scrollElement.window) {
offsetMethod = 'position'
offsetBase = this.$scrollElement.scrollTop()
offsetBase = this._getScrollTop()
}
this.offsets = []
this.targets = []
this.scrollHeight = this.getScrollHeight()
this._offsets = []
this._targets = []
var self = this
this._scrollHeight = this._getScrollHeight()
this.$body
.find(this.selector)
.map(function () {
var $el = $(this)
var href = $el.data('target') || $el.attr('href')
var $href = /^#./.test(href) && $(href)
var targets = /** @type {Array.<Element>} */ ($.makeArray($(this._selector)))
return ($href
&& $href.length
&& $href.is(':visible')
&& [[$href[offsetMethod]().top + offsetBase, href]]) || null
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] })
.each(function () {
self.offsets.push(this[0])
self.targets.push(this[1])
})
}
.forEach(function (item, index) {
this._offsets.push(item[0])
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) {
return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
}
var target = this._targets[this._targets.length - 1]
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])
if (this._activeTarget != target) {
this._activate(target)
}
}
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')
if (this._activeTarget && scrollTop < this._offsets[0]) {
this._activeTarget = null
this._clear()
return
}
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])
if (isActiveTarget) {
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)
}
}
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]()
$(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)
}
var old = $.fn.scrollspy
$.fn.scrollspy = Plugin
$.fn.scrollspy.Constructor = ScrollSpy
}
// 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
}
/**
* ------------------------------------------------------------------------
* 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()))
}
// 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);
})

383
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
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
* ========================================================================
* @fileoverview - Bootstrap's tab plugin. Tab O_O
*
* Public Methods & Properties:
*
* + $.tab
* + $.tab.noConflict
* + $.tab.Constructor
* + $.tab.Constructor.VERSION
* + $.tab.Constructor.prototype.show
*
* ========================================================================
*/
+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
}
/**
* @const
* @type {string}
*/
Tab['VERSION'] = '4.0.0'
/**
* @const
* @type {string}
* @private
*/
Tab._NAME = 'tab'
/**
* @const
* @type {string}
* @private
*/
Tab._DATA_KEY = 'bs.tab'
/**
* @const
* @type {number}
* @private
*/
Tab._TRANSITION_DURATION = 150
/**
* @const
* @enum {string}
* @private
*/
Tab._Event = {
HIDE : 'hide.bs.tab',
HIDDEN : 'hidden.bs.tab',
SHOW : 'show.bs.tab',
SHOWN : 'shown.bs.tab'
}
/**
* @const
* @enum {string}
* @private
*/
Tab._ClassName = {
DROPDOWN_MENU : 'dropdown-menu',
ACTIVE : 'active',
FADE : 'fade',
IN : 'in'
}
/**
* @const
* @enum {string}
* @private
*/
Tab._Selector = {
A : 'a',
LI : 'li',
LI_DROPDOWN : 'li.dropdown',
UL : 'ul:not(.dropdown-menu)',
FADE_CHILD : ':scope > .fade',
ACTIVE : '.active',
ACTIVE_CHILD : ':scope > .active',
DATA_TOGGLE : '[data-toggle="tab"], [data-toggle="pill"]',
DROPDOWN_ACTIVE_CHILD : ':scope > .dropdown-menu > .active'
}
/**
* @param {Object|string=} opt_config
* @this {jQuery}
* @return {jQuery}
* @private
*/
Tab._jQueryInterface = function (opt_config) {
return this.each(function () {
var $this = $(this)
var data = $this.data(Tab._DATA_KEY)
if (!data) {
data = data = new Tab(this)
$this.data(Tab._DATA_KEY, data)
}
Tab.VERSION = '3.3.2'
if (typeof opt_config === 'string') {
data[opt_config]()
}
})
}
Tab.TRANSITION_DURATION = 150
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')
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
/**
* 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
}
if ($this.parent('li').hasClass('active')) return
var ulElement = $(this._element).closest(Tab._Selector.UL)[0]
var selector = Bootstrap.getSelectorFromElement(this._element)
var $previous = $ul.find('.active:last a')
var hideEvent = $.Event('hide.bs.tab', {
relatedTarget: $this[0]
})
var showEvent = $.Event('show.bs.tab', {
relatedTarget: $previous[0]
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)
$this.trigger(showEvent)
var showEvent = $.Event(Tab._Event.SHOW, {
relatedTarget: previous
})
if (previous) {
$(previous).trigger(hideEvent)
}
$(this._element).trigger(showEvent)
if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
var $target = $(selector)
this.activate($this.closest('li'), $ul)
this.activate($target, $target.parent(), function () {
$previous.trigger({
type: 'hidden.bs.tab',
relatedTarget: $this[0]
})
$this.trigger({
type: 'shown.bs.tab',
relatedTarget: $previous[0]
})
})
if (selector) {
var target = $(selector)[0]
}
Tab.prototype.activate = function (element, container, callback) {
var $active = container.find('> .active')
var transition = callback
&& $.support.transition
&& (($active.length && $active.hasClass('fade')) || !!container.find('> .fade').length)
this._activate($(this._element).closest(Tab._Selector.LI)[0], ulElement)
function next() {
$active
.removeClass('active')
.find('> .dropdown-menu > .active')
.removeClass('active')
.end()
.find('[data-toggle="tab"]')
.attr('aria-expanded', false)
var complete = function () {
var hiddenEvent = $.Event(Tab._Event.HIDDEN, {
relatedTarget: this._element
})
element
.addClass('active')
.find('[data-toggle="tab"]')
.attr('aria-expanded', true)
var shownEvent = $.Event(Tab._Event.SHOWN, {
relatedTarget: previous
})
if (transition) {
element[0].offsetWidth // reflow for transition
element.addClass('in')
$(previous).trigger(hiddenEvent)
$(this._element).trigger(shownEvent)
}.bind(this)
if (target) {
this._activate(target, /** @type {Element} */ (target.parentNode), complete)
} else {
element.removeClass('fade')
complete()
}
}
/**
* @param {Element} element
* @param {Element} container
* @param {Function=} opt_callback
* @private
*/
Tab.prototype._activate = function (element, container, opt_callback) {
var active = $(container).find(Tab._Selector.ACTIVE_CHILD)[0]
var isTransitioning = opt_callback
&& Bootstrap.transition
&& ((active && $(active).hasClass(Tab._ClassName.FADE))
|| !!$(container).find(Tab._Selector.FADE_CHILD)[0])
var complete = this._transitionComplete.bind(this, element, active, isTransitioning, opt_callback)
if (active && isTransitioning) {
$(active)
.one(Bootstrap.TRANSITION_END, complete)
.emulateTransitionEnd(Tab._TRANSITION_DURATION)
} else {
complete()
}
if (element.parent('.dropdown-menu')) {
element
.closest('li.dropdown')
.addClass('active')
.end()
.find('[data-toggle="tab"]')
.attr('aria-expanded', true)
if (active) {
$(active).removeClass(Tab._ClassName.IN)
}
}
/**
* @param {Element} element
* @param {Element} active
* @param {boolean} isTransitioning
* @param {Function=} opt_callback
* @private
*/
Tab.prototype._transitionComplete = function (element, active, isTransitioning, opt_callback) {
if (active) {
$(active).removeClass(Tab._ClassName.ACTIVE)
var dropdownChild = $(active).find(Tab._Selector.DROPDOWN_ACTIVE_CHILD)[0]
if (dropdownChild) {
$(dropdownChild).removeClass(Tab._ClassName.ACTIVE)
}
callback && callback()
var activeToggle = $(active).find(Tab._Selector.DATA_TOGGLE)[0]
if (activeToggle) {
activeToggle.setAttribute('aria-expanded', false)
}
}
$active.length && transition ?
$active
.one('bsTransitionEnd', next)
.emulateTransitionEnd(Tab.TRANSITION_DURATION) :
next()
$(element).addClass(Tab._ClassName.ACTIVE)
$active.removeClass('in')
var elementToggle = $(element).find(Tab._Selector.DATA_TOGGLE)[0]
if (elementToggle) {
elementToggle.setAttribute('aria-expanded', true)
}
// TAB PLUGIN DEFINITION
// =====================
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.tab')
if (!data) $this.data('bs.tab', (data = new Tab(this)))
if (typeof option == 'string') data[option]()
})
if (isTransitioning) {
Bootstrap.reflow(element)
$(element).addClass(Tab._ClassName.IN)
} else {
$(element).removeClass(Tab._ClassName.FADE)
}
var old = $.fn.tab
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)
}
$.fn.tab = Plugin
$.fn.tab.Constructor = Tab
elementToggle = $(element).find(Tab._Selector.DATA_TOGGLE)[0]
if (elementToggle) {
elementToggle.setAttribute('aria-expanded', true)
}
}
if (opt_callback) {
opt_callback()
}
}
// TAB NO CONFLICT
// ===============
/**
* ------------------------------------------------------------------------
* jQuery Interface + noConflict implementaiton
* ------------------------------------------------------------------------
*/
$.fn.tab.noConflict = function () {
$.fn.tab = old
/**
* @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
}
}
// TAB DATA-API
// ============
var clickHandler = function (e) {
// TAB DATA-API
// ============
var clickHandler = function (e) {
e.preventDefault()
Plugin.call($(this), 'show')
}
Tab._jQueryInterface.call($(this), 'show')
}
$(document)
.on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
.on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
}(jQuery);
$(document)
.on('click.bs.tab.data-api', Tab._Selector.DATA_TOGGLE, clickHandler)

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

View File

@ -29,61 +29,6 @@ $(function () {
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 () {
var $btn = $('<button class="btn" data-toggle="button">mdo</button>')
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="right carousel-control" href="#myCarousel" data-slide="next">&rsaquo;</a>'
+ '</div>'
var $carousel = $(templateHTML)
$carousel.attr('data-interval', 1814)
$carousel.appendTo('body')
$('[data-slide]').first().click()
equal($carousel.data('bs.carousel').options.interval, 1814)
equal($carousel.data('bs.carousel').getConfig().interval, 1814)
$carousel.remove()
$carousel.appendTo('body').attr('data-modal', 'foobar')
$('[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.appendTo('body')
$('[data-slide]').first().click()
$carousel.attr('data-interval', 1860)
$('[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.attr('data-interval', false)
$carousel.appendTo('body')
$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()
})

View File

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

View File

@ -30,7 +30,7 @@ $(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) {

View File

@ -30,7 +30,7 @@ $(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 () {
@ -879,17 +879,17 @@ $(function () {
.bootstrapTooltip({ delay: { show: 0, hide: 150 }})
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')
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)
setTimeout(function () {
ok(!$tooltip.data('bs.tooltip').$tip.is('.in'), '200ms: tooltip removed')
done()
ok(!$('.tooltip').is('.in'), '200ms: tooltip removed')
start()
}, 200)
}, 0)
@ -978,7 +978,7 @@ $(function () {
test('should not reload the tooltip on subsequent mouseenter events', 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>'
}
@ -1004,7 +1004,7 @@ $(function () {
test('should not reload the tooltip if the mouse leaves and re-enters before hiding', 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>'
}
@ -1029,10 +1029,12 @@ $(function () {
$('#tt-outer').trigger('mouseleave')
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')
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())
})
@ -1051,7 +1053,7 @@ $(function () {
$('<a href="#" title="tooltip title" style="position: absolute; bottom: 0; right: 0;">Foobar</a>')
.appendTo('body')
.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')
$(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 -->
<script src="../vendor/jquery.min.js"></script>
<script src="../../transition.js"></script>
<script src="../../util.js"></script>
<script src="../../alert.js"></script>
</body>

View File

@ -15,10 +15,6 @@
<h1>Button <small>Bootstrap Visual Test</small></h1>
</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>
<div class="btn-group" data-toggle="buttons">
@ -49,7 +45,7 @@
<!-- JavaScript Includes -->
<script src="../vendor/jquery.min.js"></script>
<script src="../../transition.js"></script>
<script src="../../util.js"></script>
<script src="../../button.js"></script>
<!-- JavaScript Test -->

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

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-autoprefixer": "~2.2.0",
"grunt-banner": "~0.3.1",
"grunt-closure-tools": "^0.9.7",
"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-connect": "~0.9.0",
"grunt-contrib-copy": "~0.7.0",
@ -63,6 +64,8 @@
"markdown-it": "^3.0.4",
"mq4-hover-shim": "^0.1.0",
"npm-shrinkwrap": "^200.0.0",
"remarkable": "~1.6.0",
"superstartup-closure-compiler": "^0.1.6",
"time-grunt": "~1.0.0"
},
"engines": {