modified .gitignore
This commit is contained in:
+10
-10
@@ -4,7 +4,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v4.0.0-alpha.6): alert.js
|
||||
* Bootstrap (v4.0.0-beta): alert.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -18,7 +18,7 @@ var Alert = function ($) {
|
||||
*/
|
||||
|
||||
var NAME = 'alert';
|
||||
var VERSION = '4.0.0-alpha.6';
|
||||
var VERSION = '4.0.0-beta';
|
||||
var DATA_KEY = 'bs.alert';
|
||||
var EVENT_KEY = '.' + DATA_KEY;
|
||||
var DATA_API_KEY = '.data-api';
|
||||
@@ -39,14 +39,14 @@ var Alert = function ($) {
|
||||
ALERT: 'alert',
|
||||
FADE: 'fade',
|
||||
SHOW: 'show'
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------
|
||||
* Class Definition
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------
|
||||
* Class Definition
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
var Alert = function () {
|
||||
function Alert(element) {
|
||||
_classCallCheck(this, Alert);
|
||||
@@ -180,4 +180,4 @@ var Alert = function ($) {
|
||||
|
||||
return Alert;
|
||||
}(jQuery);
|
||||
//# sourceMappingURL=alert.js.map
|
||||
//# sourceMappingURL=alert.js.map
|
||||
+18
-11
@@ -4,7 +4,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v4.0.0-alpha.6): button.js
|
||||
* Bootstrap (v4.0.0-beta): button.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -18,7 +18,7 @@ var Button = function ($) {
|
||||
*/
|
||||
|
||||
var NAME = 'button';
|
||||
var VERSION = '4.0.0-alpha.6';
|
||||
var VERSION = '4.0.0-beta';
|
||||
var DATA_KEY = 'bs.button';
|
||||
var EVENT_KEY = '.' + DATA_KEY;
|
||||
var DATA_API_KEY = '.data-api';
|
||||
@@ -41,14 +41,14 @@ var Button = function ($) {
|
||||
var Event = {
|
||||
CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY,
|
||||
FOCUS_BLUR_DATA_API: 'focus' + EVENT_KEY + DATA_API_KEY + ' ' + ('blur' + EVENT_KEY + DATA_API_KEY)
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------
|
||||
* Class Definition
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------
|
||||
* Class Definition
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
var Button = function () {
|
||||
function Button(element) {
|
||||
_classCallCheck(this, Button);
|
||||
@@ -62,6 +62,7 @@ var Button = function ($) {
|
||||
|
||||
Button.prototype.toggle = function toggle() {
|
||||
var triggerChangeEvent = true;
|
||||
var addAriaPressed = true;
|
||||
var rootElement = $(this._element).closest(Selector.DATA_TOGGLE)[0];
|
||||
|
||||
if (rootElement) {
|
||||
@@ -81,15 +82,21 @@ var Button = function ($) {
|
||||
}
|
||||
|
||||
if (triggerChangeEvent) {
|
||||
if (input.hasAttribute('disabled') || rootElement.hasAttribute('disabled') || input.classList.contains('disabled') || rootElement.classList.contains('disabled')) {
|
||||
return;
|
||||
}
|
||||
input.checked = !$(this._element).hasClass(ClassName.ACTIVE);
|
||||
$(input).trigger('change');
|
||||
}
|
||||
|
||||
input.focus();
|
||||
addAriaPressed = false;
|
||||
}
|
||||
}
|
||||
|
||||
this._element.setAttribute('aria-pressed', !$(this._element).hasClass(ClassName.ACTIVE));
|
||||
if (addAriaPressed) {
|
||||
this._element.setAttribute('aria-pressed', !$(this._element).hasClass(ClassName.ACTIVE));
|
||||
}
|
||||
|
||||
if (triggerChangeEvent) {
|
||||
$(this._element).toggleClass(ClassName.ACTIVE);
|
||||
@@ -164,4 +171,4 @@ var Button = function ($) {
|
||||
|
||||
return Button;
|
||||
}(jQuery);
|
||||
//# sourceMappingURL=button.js.map
|
||||
//# sourceMappingURL=button.js.map
|
||||
+50
-23
@@ -6,7 +6,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v4.0.0-alpha.6): carousel.js
|
||||
* Bootstrap (v4.0.0-beta): carousel.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -20,7 +20,7 @@ var Carousel = function ($) {
|
||||
*/
|
||||
|
||||
var NAME = 'carousel';
|
||||
var VERSION = '4.0.0-alpha.6';
|
||||
var VERSION = '4.0.0-beta';
|
||||
var DATA_KEY = 'bs.carousel';
|
||||
var EVENT_KEY = '.' + DATA_KEY;
|
||||
var DATA_API_KEY = '.data-api';
|
||||
@@ -28,6 +28,7 @@ var Carousel = function ($) {
|
||||
var TRANSITION_DURATION = 600;
|
||||
var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key
|
||||
var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key
|
||||
var TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch
|
||||
|
||||
var Default = {
|
||||
interval: 5000,
|
||||
@@ -58,6 +59,7 @@ var Carousel = function ($) {
|
||||
KEYDOWN: 'keydown' + EVENT_KEY,
|
||||
MOUSEENTER: 'mouseenter' + EVENT_KEY,
|
||||
MOUSELEAVE: 'mouseleave' + EVENT_KEY,
|
||||
TOUCHEND: 'touchend' + EVENT_KEY,
|
||||
LOAD_DATA_API: 'load' + EVENT_KEY + DATA_API_KEY,
|
||||
CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
|
||||
};
|
||||
@@ -81,14 +83,14 @@ var Carousel = function ($) {
|
||||
INDICATORS: '.carousel-indicators',
|
||||
DATA_SLIDE: '[data-slide], [data-slide-to]',
|
||||
DATA_RIDE: '[data-ride="carousel"]'
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------
|
||||
* Class Definition
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------
|
||||
* Class Definition
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
var Carousel = function () {
|
||||
function Carousel(element, config) {
|
||||
_classCallCheck(this, Carousel);
|
||||
@@ -100,6 +102,8 @@ var Carousel = function ($) {
|
||||
this._isPaused = false;
|
||||
this._isSliding = false;
|
||||
|
||||
this.touchTimeout = null;
|
||||
|
||||
this._config = this._getConfig(config);
|
||||
this._element = $(element)[0];
|
||||
this._indicatorsElement = $(this._element).find(Selector.INDICATORS)[0];
|
||||
@@ -112,10 +116,9 @@ var Carousel = function ($) {
|
||||
// public
|
||||
|
||||
Carousel.prototype.next = function next() {
|
||||
if (this._isSliding) {
|
||||
throw new Error('Carousel is sliding');
|
||||
if (!this._isSliding) {
|
||||
this._slide(Direction.NEXT);
|
||||
}
|
||||
this._slide(Direction.NEXT);
|
||||
};
|
||||
|
||||
Carousel.prototype.nextWhenVisible = function nextWhenVisible() {
|
||||
@@ -126,10 +129,9 @@ var Carousel = function ($) {
|
||||
};
|
||||
|
||||
Carousel.prototype.prev = function prev() {
|
||||
if (this._isSliding) {
|
||||
throw new Error('Carousel is sliding');
|
||||
if (!this._isSliding) {
|
||||
this._slide(Direction.PREV);
|
||||
}
|
||||
this._slide(Direction.PREVIOUS);
|
||||
};
|
||||
|
||||
Carousel.prototype.pause = function pause(event) {
|
||||
@@ -185,7 +187,7 @@ var Carousel = function ($) {
|
||||
return;
|
||||
}
|
||||
|
||||
var direction = index > activeIndex ? Direction.NEXT : Direction.PREVIOUS;
|
||||
var direction = index > activeIndex ? Direction.NEXT : Direction.PREV;
|
||||
|
||||
this._slide(direction, this._items[index]);
|
||||
};
|
||||
@@ -221,12 +223,30 @@ var Carousel = function ($) {
|
||||
});
|
||||
}
|
||||
|
||||
if (this._config.pause === 'hover' && !('ontouchstart' in document.documentElement)) {
|
||||
if (this._config.pause === 'hover') {
|
||||
$(this._element).on(Event.MOUSEENTER, function (event) {
|
||||
return _this2.pause(event);
|
||||
}).on(Event.MOUSELEAVE, function (event) {
|
||||
return _this2.cycle(event);
|
||||
});
|
||||
if ('ontouchstart' in document.documentElement) {
|
||||
// if it's a touch-enabled device, mouseenter/leave are fired as
|
||||
// part of the mouse compatibility events on first tap - the carousel
|
||||
// would stop cycling until user tapped out of it;
|
||||
// here, we listen for touchend, explicitly pause the carousel
|
||||
// (as if it's the second time we tap on it, mouseenter compat event
|
||||
// is NOT fired) and after a timeout (to allow for mouse compatibility
|
||||
// events to fire) we explicitly restart cycling
|
||||
$(this._element).on(Event.TOUCHEND, function () {
|
||||
_this2.pause();
|
||||
if (_this2.touchTimeout) {
|
||||
clearTimeout(_this2.touchTimeout);
|
||||
}
|
||||
_this2.touchTimeout = setTimeout(function (event) {
|
||||
return _this2.cycle(event);
|
||||
}, TOUCHEVENT_COMPAT_WAIT + _this2._config.interval);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -256,7 +276,7 @@ var Carousel = function ($) {
|
||||
|
||||
Carousel.prototype._getItemByDirection = function _getItemByDirection(direction, activeElement) {
|
||||
var isNextDirection = direction === Direction.NEXT;
|
||||
var isPrevDirection = direction === Direction.PREVIOUS;
|
||||
var isPrevDirection = direction === Direction.PREV;
|
||||
var activeIndex = this._getItemIndex(activeElement);
|
||||
var lastItemIndex = this._items.length - 1;
|
||||
var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex;
|
||||
@@ -265,16 +285,20 @@ var Carousel = function ($) {
|
||||
return activeElement;
|
||||
}
|
||||
|
||||
var delta = direction === Direction.PREVIOUS ? -1 : 1;
|
||||
var delta = direction === Direction.PREV ? -1 : 1;
|
||||
var itemIndex = (activeIndex + delta) % this._items.length;
|
||||
|
||||
return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex];
|
||||
};
|
||||
|
||||
Carousel.prototype._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, eventDirectionName) {
|
||||
var targetIndex = this._getItemIndex(relatedTarget);
|
||||
var fromIndex = this._getItemIndex($(this._element).find(Selector.ACTIVE_ITEM)[0]);
|
||||
var slideEvent = $.Event(Event.SLIDE, {
|
||||
relatedTarget: relatedTarget,
|
||||
direction: eventDirectionName
|
||||
direction: eventDirectionName,
|
||||
from: fromIndex,
|
||||
to: targetIndex
|
||||
});
|
||||
|
||||
$(this._element).trigger(slideEvent);
|
||||
@@ -298,8 +322,9 @@ var Carousel = function ($) {
|
||||
var _this3 = this;
|
||||
|
||||
var activeElement = $(this._element).find(Selector.ACTIVE_ITEM)[0];
|
||||
var activeElementIndex = this._getItemIndex(activeElement);
|
||||
var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement);
|
||||
|
||||
var nextElementIndex = this._getItemIndex(nextElement);
|
||||
var isCycling = Boolean(this._interval);
|
||||
|
||||
var directionalClassName = void 0;
|
||||
@@ -341,7 +366,9 @@ var Carousel = function ($) {
|
||||
|
||||
var slidEvent = $.Event(Event.SLID, {
|
||||
relatedTarget: nextElement,
|
||||
direction: eventDirectionName
|
||||
direction: eventDirectionName,
|
||||
from: activeElementIndex,
|
||||
to: nextElementIndex
|
||||
});
|
||||
|
||||
if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.SLIDE)) {
|
||||
@@ -483,4 +510,4 @@ var Carousel = function ($) {
|
||||
|
||||
return Carousel;
|
||||
}(jQuery);
|
||||
//# sourceMappingURL=carousel.js.map
|
||||
//# sourceMappingURL=carousel.js.map
|
||||
+44
-35
@@ -6,7 +6,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v4.0.0-alpha.6): collapse.js
|
||||
* Bootstrap (v4.0.0-beta): collapse.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -20,7 +20,7 @@ var Collapse = function ($) {
|
||||
*/
|
||||
|
||||
var NAME = 'collapse';
|
||||
var VERSION = '4.0.0-alpha.6';
|
||||
var VERSION = '4.0.0-beta';
|
||||
var DATA_KEY = 'bs.collapse';
|
||||
var EVENT_KEY = '.' + DATA_KEY;
|
||||
var DATA_API_KEY = '.data-api';
|
||||
@@ -58,16 +58,16 @@ var Collapse = function ($) {
|
||||
};
|
||||
|
||||
var Selector = {
|
||||
ACTIVES: '.card > .show, .card > .collapsing',
|
||||
ACTIVES: '.show, .collapsing',
|
||||
DATA_TOGGLE: '[data-toggle="collapse"]'
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------
|
||||
* Class Definition
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------
|
||||
* Class Definition
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
var Collapse = function () {
|
||||
function Collapse(element, config) {
|
||||
_classCallCheck(this, Collapse);
|
||||
@@ -76,6 +76,14 @@ var Collapse = function ($) {
|
||||
this._element = element;
|
||||
this._config = this._getConfig(config);
|
||||
this._triggerArray = $.makeArray($('[data-toggle="collapse"][href="#' + element.id + '"],' + ('[data-toggle="collapse"][data-target="#' + element.id + '"]')));
|
||||
var tabToggles = $(Selector.DATA_TOGGLE);
|
||||
for (var i = 0; i < tabToggles.length; i++) {
|
||||
var elem = tabToggles[i];
|
||||
var selector = Util.getSelectorFromElement(elem);
|
||||
if (selector !== null && $(selector).filter(element).length > 0) {
|
||||
this._triggerArray.push(elem);
|
||||
}
|
||||
}
|
||||
|
||||
this._parent = this._config.parent ? this._getParent() : null;
|
||||
|
||||
@@ -103,11 +111,7 @@ var Collapse = function ($) {
|
||||
Collapse.prototype.show = function show() {
|
||||
var _this = this;
|
||||
|
||||
if (this._isTransitioning) {
|
||||
throw new Error('Collapse is transitioning');
|
||||
}
|
||||
|
||||
if ($(this._element).hasClass(ClassName.SHOW)) {
|
||||
if (this._isTransitioning || $(this._element).hasClass(ClassName.SHOW)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -115,7 +119,7 @@ var Collapse = function ($) {
|
||||
var activesData = void 0;
|
||||
|
||||
if (this._parent) {
|
||||
actives = $.makeArray($(this._parent).find(Selector.ACTIVES));
|
||||
actives = $.makeArray($(this._parent).children().children(Selector.ACTIVES));
|
||||
if (!actives.length) {
|
||||
actives = null;
|
||||
}
|
||||
@@ -146,7 +150,6 @@ var Collapse = function ($) {
|
||||
$(this._element).removeClass(ClassName.COLLAPSE).addClass(ClassName.COLLAPSING);
|
||||
|
||||
this._element.style[dimension] = 0;
|
||||
this._element.setAttribute('aria-expanded', true);
|
||||
|
||||
if (this._triggerArray.length) {
|
||||
$(this._triggerArray).removeClass(ClassName.COLLAPSED).attr('aria-expanded', true);
|
||||
@@ -180,11 +183,7 @@ var Collapse = function ($) {
|
||||
Collapse.prototype.hide = function hide() {
|
||||
var _this2 = this;
|
||||
|
||||
if (this._isTransitioning) {
|
||||
throw new Error('Collapse is transitioning');
|
||||
}
|
||||
|
||||
if (!$(this._element).hasClass(ClassName.SHOW)) {
|
||||
if (this._isTransitioning || !$(this._element).hasClass(ClassName.SHOW)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -195,18 +194,24 @@ var Collapse = function ($) {
|
||||
}
|
||||
|
||||
var dimension = this._getDimension();
|
||||
var offsetDimension = dimension === Dimension.WIDTH ? 'offsetWidth' : 'offsetHeight';
|
||||
|
||||
this._element.style[dimension] = this._element[offsetDimension] + 'px';
|
||||
this._element.style[dimension] = this._element.getBoundingClientRect()[dimension] + 'px';
|
||||
|
||||
Util.reflow(this._element);
|
||||
|
||||
$(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.SHOW);
|
||||
|
||||
this._element.setAttribute('aria-expanded', false);
|
||||
|
||||
if (this._triggerArray.length) {
|
||||
$(this._triggerArray).addClass(ClassName.COLLAPSED).attr('aria-expanded', false);
|
||||
for (var i = 0; i < this._triggerArray.length; i++) {
|
||||
var trigger = this._triggerArray[i];
|
||||
var selector = Util.getSelectorFromElement(trigger);
|
||||
if (selector !== null) {
|
||||
var $elem = $(selector);
|
||||
if (!$elem.hasClass(ClassName.SHOW)) {
|
||||
$(trigger).addClass(ClassName.COLLAPSED).attr('aria-expanded', false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.setTransitioning(true);
|
||||
@@ -270,7 +275,6 @@ var Collapse = function ($) {
|
||||
Collapse.prototype._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) {
|
||||
if (element) {
|
||||
var isOpen = $(element).hasClass(ClassName.SHOW);
|
||||
element.setAttribute('aria-expanded', isOpen);
|
||||
|
||||
if (triggerArray.length) {
|
||||
$(triggerArray).toggleClass(ClassName.COLLAPSED, !isOpen).attr('aria-expanded', isOpen);
|
||||
@@ -331,13 +335,18 @@ var Collapse = function ($) {
|
||||
*/
|
||||
|
||||
$(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
|
||||
event.preventDefault();
|
||||
if (!/input|textarea/i.test(event.target.tagName)) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
var target = Collapse._getTargetFromElement(this);
|
||||
var data = $(target).data(DATA_KEY);
|
||||
var config = data ? 'toggle' : $(this).data();
|
||||
|
||||
Collapse._jQueryInterface.call($(target), config);
|
||||
var $trigger = $(this);
|
||||
var selector = Util.getSelectorFromElement(this);
|
||||
$(selector).each(function () {
|
||||
var $target = $(this);
|
||||
var data = $target.data(DATA_KEY);
|
||||
var config = data ? 'toggle' : $trigger.data();
|
||||
Collapse._jQueryInterface.call($target, config);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -355,4 +364,4 @@ var Collapse = function ($) {
|
||||
|
||||
return Collapse;
|
||||
}(jQuery);
|
||||
//# sourceMappingURL=collapse.js.map
|
||||
//# sourceMappingURL=collapse.js.map
|
||||
+197
-53
@@ -1,16 +1,26 @@
|
||||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
|
||||
|
||||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
||||
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v4.0.0-alpha.6): dropdown.js
|
||||
* Bootstrap (v4.0.0-beta): dropdown.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
var Dropdown = function ($) {
|
||||
|
||||
/**
|
||||
* Check for Popper dependency
|
||||
* Popper - https://popper.js.org
|
||||
*/
|
||||
if (typeof Popper === 'undefined') {
|
||||
throw new Error('Bootstrap dropdown require Popper.js (https://popper.js.org)');
|
||||
}
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------
|
||||
* Constants
|
||||
@@ -18,15 +28,18 @@ var Dropdown = function ($) {
|
||||
*/
|
||||
|
||||
var NAME = 'dropdown';
|
||||
var VERSION = '4.0.0-alpha.6';
|
||||
var VERSION = '4.0.0-beta';
|
||||
var DATA_KEY = 'bs.dropdown';
|
||||
var EVENT_KEY = '.' + DATA_KEY;
|
||||
var DATA_API_KEY = '.data-api';
|
||||
var JQUERY_NO_CONFLICT = $.fn[NAME];
|
||||
var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key
|
||||
var SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key
|
||||
var TAB_KEYCODE = 9; // KeyboardEvent.which value for tab key
|
||||
var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key
|
||||
var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key
|
||||
var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse)
|
||||
var REGEXP_KEYDOWN = new RegExp(ARROW_UP_KEYCODE + '|' + ARROW_DOWN_KEYCODE + '|' + ESCAPE_KEYCODE);
|
||||
|
||||
var Event = {
|
||||
HIDE: 'hide' + EVENT_KEY,
|
||||
@@ -35,37 +48,60 @@ var Dropdown = function ($) {
|
||||
SHOWN: 'shown' + EVENT_KEY,
|
||||
CLICK: 'click' + EVENT_KEY,
|
||||
CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY,
|
||||
FOCUSIN_DATA_API: 'focusin' + EVENT_KEY + DATA_API_KEY,
|
||||
KEYDOWN_DATA_API: 'keydown' + EVENT_KEY + DATA_API_KEY
|
||||
KEYDOWN_DATA_API: 'keydown' + EVENT_KEY + DATA_API_KEY,
|
||||
KEYUP_DATA_API: 'keyup' + EVENT_KEY + DATA_API_KEY
|
||||
};
|
||||
|
||||
var ClassName = {
|
||||
BACKDROP: 'dropdown-backdrop',
|
||||
DISABLED: 'disabled',
|
||||
SHOW: 'show'
|
||||
SHOW: 'show',
|
||||
DROPUP: 'dropup',
|
||||
MENURIGHT: 'dropdown-menu-right',
|
||||
MENULEFT: 'dropdown-menu-left'
|
||||
};
|
||||
|
||||
var Selector = {
|
||||
BACKDROP: '.dropdown-backdrop',
|
||||
DATA_TOGGLE: '[data-toggle="dropdown"]',
|
||||
FORM_CHILD: '.dropdown form',
|
||||
ROLE_MENU: '[role="menu"]',
|
||||
ROLE_LISTBOX: '[role="listbox"]',
|
||||
MENU: '.dropdown-menu',
|
||||
NAVBAR_NAV: '.navbar-nav',
|
||||
VISIBLE_ITEMS: '[role="menu"] li:not(.disabled) a, ' + '[role="listbox"] li:not(.disabled) a'
|
||||
VISIBLE_ITEMS: '.dropdown-menu .dropdown-item:not(.disabled)'
|
||||
};
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------
|
||||
* Class Definition
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
var AttachmentMap = {
|
||||
TOP: 'top-start',
|
||||
TOPEND: 'top-end',
|
||||
BOTTOM: 'bottom-start',
|
||||
BOTTOMEND: 'bottom-end'
|
||||
};
|
||||
|
||||
var Default = {
|
||||
placement: AttachmentMap.BOTTOM,
|
||||
offset: 0,
|
||||
flip: true
|
||||
};
|
||||
|
||||
var DefaultType = {
|
||||
placement: 'string',
|
||||
offset: '(number|string)',
|
||||
flip: 'boolean'
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------
|
||||
* Class Definition
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
};
|
||||
var Dropdown = function () {
|
||||
function Dropdown(element) {
|
||||
function Dropdown(element, config) {
|
||||
_classCallCheck(this, Dropdown);
|
||||
|
||||
this._element = element;
|
||||
this._popper = null;
|
||||
this._config = this._getConfig(config);
|
||||
this._menu = this._getMenuElement();
|
||||
this._inNavbar = this._detectNavbar();
|
||||
|
||||
this._addEventListeners();
|
||||
}
|
||||
@@ -75,58 +111,144 @@ var Dropdown = function ($) {
|
||||
// public
|
||||
|
||||
Dropdown.prototype.toggle = function toggle() {
|
||||
if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {
|
||||
return false;
|
||||
if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var parent = Dropdown._getParentFromElement(this);
|
||||
var isActive = $(parent).hasClass(ClassName.SHOW);
|
||||
var parent = Dropdown._getParentFromElement(this._element);
|
||||
var isActive = $(this._menu).hasClass(ClassName.SHOW);
|
||||
|
||||
Dropdown._clearMenus();
|
||||
|
||||
if (isActive) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ('ontouchstart' in document.documentElement && !$(parent).closest(Selector.NAVBAR_NAV).length) {
|
||||
|
||||
// if mobile we use a backdrop because click events don't delegate
|
||||
var dropdown = document.createElement('div');
|
||||
dropdown.className = ClassName.BACKDROP;
|
||||
$(dropdown).insertBefore(this);
|
||||
$(dropdown).on('click', Dropdown._clearMenus);
|
||||
return;
|
||||
}
|
||||
|
||||
var relatedTarget = {
|
||||
relatedTarget: this
|
||||
relatedTarget: this._element
|
||||
};
|
||||
var showEvent = $.Event(Event.SHOW, relatedTarget);
|
||||
|
||||
$(parent).trigger(showEvent);
|
||||
|
||||
if (showEvent.isDefaultPrevented()) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.focus();
|
||||
this.setAttribute('aria-expanded', true);
|
||||
var element = this._element;
|
||||
// for dropup with alignment we use the parent as popper container
|
||||
if ($(parent).hasClass(ClassName.DROPUP)) {
|
||||
if ($(this._menu).hasClass(ClassName.MENULEFT) || $(this._menu).hasClass(ClassName.MENURIGHT)) {
|
||||
element = parent;
|
||||
}
|
||||
}
|
||||
this._popper = new Popper(element, this._menu, this._getPopperConfig());
|
||||
|
||||
$(parent).toggleClass(ClassName.SHOW);
|
||||
$(parent).trigger($.Event(Event.SHOWN, relatedTarget));
|
||||
// if this is a touch-enabled device we add extra
|
||||
// empty mouseover listeners to the body's immediate children;
|
||||
// only needed because of broken event delegation on iOS
|
||||
// https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
|
||||
if ('ontouchstart' in document.documentElement && !$(parent).closest(Selector.NAVBAR_NAV).length) {
|
||||
$('body').children().on('mouseover', null, $.noop);
|
||||
}
|
||||
|
||||
return false;
|
||||
this._element.focus();
|
||||
this._element.setAttribute('aria-expanded', true);
|
||||
|
||||
$(this._menu).toggleClass(ClassName.SHOW);
|
||||
$(parent).toggleClass(ClassName.SHOW).trigger($.Event(Event.SHOWN, relatedTarget));
|
||||
};
|
||||
|
||||
Dropdown.prototype.dispose = function dispose() {
|
||||
$.removeData(this._element, DATA_KEY);
|
||||
$(this._element).off(EVENT_KEY);
|
||||
this._element = null;
|
||||
this._menu = null;
|
||||
if (this._popper !== null) {
|
||||
this._popper.destroy();
|
||||
}
|
||||
this._popper = null;
|
||||
};
|
||||
|
||||
Dropdown.prototype.update = function update() {
|
||||
this._inNavbar = this._detectNavbar();
|
||||
if (this._popper !== null) {
|
||||
this._popper.scheduleUpdate();
|
||||
}
|
||||
};
|
||||
|
||||
// private
|
||||
|
||||
Dropdown.prototype._addEventListeners = function _addEventListeners() {
|
||||
$(this._element).on(Event.CLICK, this.toggle);
|
||||
var _this = this;
|
||||
|
||||
$(this._element).on(Event.CLICK, function (event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
_this.toggle();
|
||||
});
|
||||
};
|
||||
|
||||
Dropdown.prototype._getConfig = function _getConfig(config) {
|
||||
var elementData = $(this._element).data();
|
||||
if (elementData.placement !== undefined) {
|
||||
elementData.placement = AttachmentMap[elementData.placement.toUpperCase()];
|
||||
}
|
||||
|
||||
config = $.extend({}, this.constructor.Default, $(this._element).data(), config);
|
||||
|
||||
Util.typeCheckConfig(NAME, config, this.constructor.DefaultType);
|
||||
|
||||
return config;
|
||||
};
|
||||
|
||||
Dropdown.prototype._getMenuElement = function _getMenuElement() {
|
||||
if (!this._menu) {
|
||||
var parent = Dropdown._getParentFromElement(this._element);
|
||||
this._menu = $(parent).find(Selector.MENU)[0];
|
||||
}
|
||||
return this._menu;
|
||||
};
|
||||
|
||||
Dropdown.prototype._getPlacement = function _getPlacement() {
|
||||
var $parentDropdown = $(this._element).parent();
|
||||
var placement = this._config.placement;
|
||||
|
||||
// Handle dropup
|
||||
if ($parentDropdown.hasClass(ClassName.DROPUP) || this._config.placement === AttachmentMap.TOP) {
|
||||
placement = AttachmentMap.TOP;
|
||||
if ($(this._menu).hasClass(ClassName.MENURIGHT)) {
|
||||
placement = AttachmentMap.TOPEND;
|
||||
}
|
||||
} else if ($(this._menu).hasClass(ClassName.MENURIGHT)) {
|
||||
placement = AttachmentMap.BOTTOMEND;
|
||||
}
|
||||
return placement;
|
||||
};
|
||||
|
||||
Dropdown.prototype._detectNavbar = function _detectNavbar() {
|
||||
return $(this._element).closest('.navbar').length > 0;
|
||||
};
|
||||
|
||||
Dropdown.prototype._getPopperConfig = function _getPopperConfig() {
|
||||
var popperConfig = {
|
||||
placement: this._getPlacement(),
|
||||
modifiers: {
|
||||
offset: {
|
||||
offset: this._config.offset
|
||||
},
|
||||
flip: {
|
||||
enabled: this._config.flip
|
||||
}
|
||||
}
|
||||
|
||||
// Disable Popper.js for Dropdown in Navbar
|
||||
};if (this._inNavbar) {
|
||||
popperConfig.modifiers.applyStyle = {
|
||||
enabled: !this._inNavbar
|
||||
};
|
||||
}
|
||||
return popperConfig;
|
||||
};
|
||||
|
||||
// static
|
||||
@@ -134,9 +256,10 @@ var Dropdown = function ($) {
|
||||
Dropdown._jQueryInterface = function _jQueryInterface(config) {
|
||||
return this.each(function () {
|
||||
var data = $(this).data(DATA_KEY);
|
||||
var _config = (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' ? config : null;
|
||||
|
||||
if (!data) {
|
||||
data = new Dropdown(this);
|
||||
data = new Dropdown(this, _config);
|
||||
$(this).data(DATA_KEY, data);
|
||||
}
|
||||
|
||||
@@ -144,34 +267,34 @@ var Dropdown = function ($) {
|
||||
if (data[config] === undefined) {
|
||||
throw new Error('No method named "' + config + '"');
|
||||
}
|
||||
data[config].call(this);
|
||||
data[config]();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Dropdown._clearMenus = function _clearMenus(event) {
|
||||
if (event && event.which === RIGHT_MOUSE_BUTTON_WHICH) {
|
||||
if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || event.type === 'keyup' && event.which !== TAB_KEYCODE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var backdrop = $(Selector.BACKDROP)[0];
|
||||
if (backdrop) {
|
||||
backdrop.parentNode.removeChild(backdrop);
|
||||
}
|
||||
|
||||
var toggles = $.makeArray($(Selector.DATA_TOGGLE));
|
||||
|
||||
for (var i = 0; i < toggles.length; i++) {
|
||||
var parent = Dropdown._getParentFromElement(toggles[i]);
|
||||
var context = $(toggles[i]).data(DATA_KEY);
|
||||
var relatedTarget = {
|
||||
relatedTarget: toggles[i]
|
||||
};
|
||||
|
||||
if (!context) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var dropdownMenu = context._menu;
|
||||
if (!$(parent).hasClass(ClassName.SHOW)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'focusin') && $.contains(parent, event.target)) {
|
||||
if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && $.contains(parent, event.target)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -181,8 +304,15 @@ var Dropdown = function ($) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if this is a touch-enabled device we remove the extra
|
||||
// empty mouseover listeners we added for iOS support
|
||||
if ('ontouchstart' in document.documentElement) {
|
||||
$('body').children().off('mouseover', null, $.noop);
|
||||
}
|
||||
|
||||
toggles[i].setAttribute('aria-expanded', 'false');
|
||||
|
||||
$(dropdownMenu).removeClass(ClassName.SHOW);
|
||||
$(parent).removeClass(ClassName.SHOW).trigger($.Event(Event.HIDDEN, relatedTarget));
|
||||
}
|
||||
};
|
||||
@@ -199,7 +329,7 @@ var Dropdown = function ($) {
|
||||
};
|
||||
|
||||
Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) {
|
||||
if (!/(38|40|27|32)/.test(event.which) || /input|textarea/i.test(event.target.tagName)) {
|
||||
if (!REGEXP_KEYDOWN.test(event.which) || /button/i.test(event.target.tagName) && event.which === SPACE_KEYCODE || /input|textarea/i.test(event.target.tagName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -213,7 +343,7 @@ var Dropdown = function ($) {
|
||||
var parent = Dropdown._getParentFromElement(this);
|
||||
var isActive = $(parent).hasClass(ClassName.SHOW);
|
||||
|
||||
if (!isActive && event.which !== ESCAPE_KEYCODE || isActive && event.which === ESCAPE_KEYCODE) {
|
||||
if (!isActive && (event.which !== ESCAPE_KEYCODE || event.which !== SPACE_KEYCODE) || isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) {
|
||||
|
||||
if (event.which === ESCAPE_KEYCODE) {
|
||||
var toggle = $(parent).find(Selector.DATA_TOGGLE)[0];
|
||||
@@ -254,6 +384,16 @@ var Dropdown = function ($) {
|
||||
get: function get() {
|
||||
return VERSION;
|
||||
}
|
||||
}, {
|
||||
key: 'Default',
|
||||
get: function get() {
|
||||
return Default;
|
||||
}
|
||||
}, {
|
||||
key: 'DefaultType',
|
||||
get: function get() {
|
||||
return DefaultType;
|
||||
}
|
||||
}]);
|
||||
|
||||
return Dropdown;
|
||||
@@ -265,7 +405,11 @@ var Dropdown = function ($) {
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
$(document).on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.ROLE_MENU, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.ROLE_LISTBOX, Dropdown._dataApiKeydownHandler).on(Event.CLICK_DATA_API + ' ' + Event.FOCUSIN_DATA_API, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, Dropdown.prototype.toggle).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) {
|
||||
$(document).on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler).on(Event.CLICK_DATA_API + ' ' + Event.KEYUP_DATA_API, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
Dropdown._jQueryInterface.call($(this), 'toggle');
|
||||
}).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
@@ -283,5 +427,5 @@ var Dropdown = function ($) {
|
||||
};
|
||||
|
||||
return Dropdown;
|
||||
}(jQuery);
|
||||
//# sourceMappingURL=dropdown.js.map
|
||||
}(jQuery); /* global Popper */
|
||||
//# sourceMappingURL=dropdown.js.map
|
||||
+73
-31
@@ -6,7 +6,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v4.0.0-alpha.6): modal.js
|
||||
* Bootstrap (v4.0.0-beta): modal.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -20,7 +20,7 @@ var Modal = function ($) {
|
||||
*/
|
||||
|
||||
var NAME = 'modal';
|
||||
var VERSION = '4.0.0-alpha.6';
|
||||
var VERSION = '4.0.0-beta';
|
||||
var DATA_KEY = 'bs.modal';
|
||||
var EVENT_KEY = '.' + DATA_KEY;
|
||||
var DATA_API_KEY = '.data-api';
|
||||
@@ -69,15 +69,16 @@ var Modal = function ($) {
|
||||
DIALOG: '.modal-dialog',
|
||||
DATA_TOGGLE: '[data-toggle="modal"]',
|
||||
DATA_DISMISS: '[data-dismiss="modal"]',
|
||||
FIXED_CONTENT: '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top'
|
||||
FIXED_CONTENT: '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top',
|
||||
NAVBAR_TOGGLER: '.navbar-toggler'
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------
|
||||
* Class Definition
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------
|
||||
* Class Definition
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
var Modal = function () {
|
||||
function Modal(element, config) {
|
||||
_classCallCheck(this, Modal);
|
||||
@@ -89,7 +90,6 @@ var Modal = function ($) {
|
||||
this._isShown = false;
|
||||
this._isBodyOverflowing = false;
|
||||
this._ignoreBackdropClick = false;
|
||||
this._isTransitioning = false;
|
||||
this._originalBodyPadding = 0;
|
||||
this._scrollbarWidth = 0;
|
||||
}
|
||||
@@ -106,12 +106,13 @@ var Modal = function ($) {
|
||||
var _this = this;
|
||||
|
||||
if (this._isTransitioning) {
|
||||
throw new Error('Modal is transitioning');
|
||||
return;
|
||||
}
|
||||
|
||||
if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE)) {
|
||||
this._isTransitioning = true;
|
||||
}
|
||||
|
||||
var showEvent = $.Event(Event.SHOW, {
|
||||
relatedTarget: relatedTarget
|
||||
});
|
||||
@@ -156,16 +157,18 @@ var Modal = function ($) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
if (this._isTransitioning) {
|
||||
throw new Error('Modal is transitioning');
|
||||
if (this._isTransitioning || !this._isShown) {
|
||||
return;
|
||||
}
|
||||
|
||||
var transition = Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE);
|
||||
|
||||
if (transition) {
|
||||
this._isTransitioning = true;
|
||||
}
|
||||
|
||||
var hideEvent = $.Event(Event.HIDE);
|
||||
|
||||
$(this._element).trigger(hideEvent);
|
||||
|
||||
if (!this._isShown || hideEvent.isDefaultPrevented()) {
|
||||
@@ -185,6 +188,7 @@ var Modal = function ($) {
|
||||
$(this._dialog).off(Event.MOUSEDOWN_DISMISS);
|
||||
|
||||
if (transition) {
|
||||
|
||||
$(this._element).one(Util.TRANSITION_END, function (event) {
|
||||
return _this2._hideModal(event);
|
||||
}).emulateTransitionEnd(TRANSITION_DURATION);
|
||||
@@ -205,10 +209,13 @@ var Modal = function ($) {
|
||||
this._isShown = null;
|
||||
this._isBodyOverflowing = null;
|
||||
this._ignoreBackdropClick = null;
|
||||
this._originalBodyPadding = null;
|
||||
this._scrollbarWidth = null;
|
||||
};
|
||||
|
||||
Modal.prototype.handleUpdate = function handleUpdate() {
|
||||
this._adjustDialog();
|
||||
};
|
||||
|
||||
// private
|
||||
|
||||
Modal.prototype._getConfig = function _getConfig(config) {
|
||||
@@ -277,6 +284,7 @@ var Modal = function ($) {
|
||||
if (this._isShown && this._config.keyboard) {
|
||||
$(this._element).on(Event.KEYDOWN_DISMISS, function (event) {
|
||||
if (event.which === ESCAPE_KEYCODE) {
|
||||
event.preventDefault();
|
||||
_this5.hide();
|
||||
}
|
||||
});
|
||||
@@ -290,7 +298,7 @@ var Modal = function ($) {
|
||||
|
||||
if (this._isShown) {
|
||||
$(window).on(Event.RESIZE, function (event) {
|
||||
return _this6._handleUpdate(event);
|
||||
return _this6.handleUpdate(event);
|
||||
});
|
||||
} else {
|
||||
$(window).off(Event.RESIZE);
|
||||
@@ -301,7 +309,7 @@ var Modal = function ($) {
|
||||
var _this7 = this;
|
||||
|
||||
this._element.style.display = 'none';
|
||||
this._element.setAttribute('aria-hidden', 'true');
|
||||
this._element.setAttribute('aria-hidden', true);
|
||||
this._isTransitioning = false;
|
||||
this._showBackdrop(function () {
|
||||
$(document.body).removeClass(ClassName.OPEN);
|
||||
@@ -391,10 +399,6 @@ var Modal = function ($) {
|
||||
// todo (fat): these should probably be refactored out of modal.js
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
Modal.prototype._handleUpdate = function _handleUpdate() {
|
||||
this._adjustDialog();
|
||||
};
|
||||
|
||||
Modal.prototype._adjustDialog = function _adjustDialog() {
|
||||
var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;
|
||||
|
||||
@@ -418,17 +422,55 @@ var Modal = function ($) {
|
||||
};
|
||||
|
||||
Modal.prototype._setScrollbar = function _setScrollbar() {
|
||||
var bodyPadding = parseInt($(Selector.FIXED_CONTENT).css('padding-right') || 0, 10);
|
||||
|
||||
this._originalBodyPadding = document.body.style.paddingRight || '';
|
||||
var _this9 = this;
|
||||
|
||||
if (this._isBodyOverflowing) {
|
||||
document.body.style.paddingRight = bodyPadding + this._scrollbarWidth + 'px';
|
||||
// Note: DOMNode.style.paddingRight returns the actual value or '' if not set
|
||||
// while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set
|
||||
|
||||
// Adjust fixed content padding
|
||||
$(Selector.FIXED_CONTENT).each(function (index, element) {
|
||||
var actualPadding = $(element)[0].style.paddingRight;
|
||||
var calculatedPadding = $(element).css('padding-right');
|
||||
$(element).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + _this9._scrollbarWidth + 'px');
|
||||
});
|
||||
|
||||
// Adjust navbar-toggler margin
|
||||
$(Selector.NAVBAR_TOGGLER).each(function (index, element) {
|
||||
var actualMargin = $(element)[0].style.marginRight;
|
||||
var calculatedMargin = $(element).css('margin-right');
|
||||
$(element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) + _this9._scrollbarWidth + 'px');
|
||||
});
|
||||
|
||||
// Adjust body padding
|
||||
var actualPadding = document.body.style.paddingRight;
|
||||
var calculatedPadding = $('body').css('padding-right');
|
||||
$('body').data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + this._scrollbarWidth + 'px');
|
||||
}
|
||||
};
|
||||
|
||||
Modal.prototype._resetScrollbar = function _resetScrollbar() {
|
||||
document.body.style.paddingRight = this._originalBodyPadding;
|
||||
// Restore fixed content padding
|
||||
$(Selector.FIXED_CONTENT).each(function (index, element) {
|
||||
var padding = $(element).data('padding-right');
|
||||
if (typeof padding !== 'undefined') {
|
||||
$(element).css('padding-right', padding).removeData('padding-right');
|
||||
}
|
||||
});
|
||||
|
||||
// Restore navbar-toggler margin
|
||||
$(Selector.NAVBAR_TOGGLER).each(function (index, element) {
|
||||
var margin = $(element).data('margin-right');
|
||||
if (typeof margin !== 'undefined') {
|
||||
$(element).css('margin-right', margin).removeData('margin-right');
|
||||
}
|
||||
});
|
||||
|
||||
// Restore body padding
|
||||
var padding = $('body').data('padding-right');
|
||||
if (typeof padding !== 'undefined') {
|
||||
$('body').css('padding-right', padding).removeData('padding-right');
|
||||
}
|
||||
};
|
||||
|
||||
Modal.prototype._getScrollbarWidth = function _getScrollbarWidth() {
|
||||
@@ -436,7 +478,7 @@ var Modal = function ($) {
|
||||
var scrollDiv = document.createElement('div');
|
||||
scrollDiv.className = ClassName.SCROLLBAR_MEASURER;
|
||||
document.body.appendChild(scrollDiv);
|
||||
var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
|
||||
var scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth;
|
||||
document.body.removeChild(scrollDiv);
|
||||
return scrollbarWidth;
|
||||
};
|
||||
@@ -486,7 +528,7 @@ var Modal = function ($) {
|
||||
*/
|
||||
|
||||
$(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
|
||||
var _this9 = this;
|
||||
var _this10 = this;
|
||||
|
||||
var target = void 0;
|
||||
var selector = Util.getSelectorFromElement(this);
|
||||
@@ -508,8 +550,8 @@ var Modal = function ($) {
|
||||
}
|
||||
|
||||
$target.one(Event.HIDDEN, function () {
|
||||
if ($(_this9).is(':visible')) {
|
||||
_this9.focus();
|
||||
if ($(_this10).is(':visible')) {
|
||||
_this10.focus();
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -532,4 +574,4 @@ var Modal = function ($) {
|
||||
|
||||
return Modal;
|
||||
}(jQuery);
|
||||
//# sourceMappingURL=modal.js.map
|
||||
//# sourceMappingURL=modal.js.map
|
||||
+27
-15
@@ -10,7 +10,7 @@ function _inherits(subClass, superClass) { if (typeof superClass !== "function"
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v4.0.0-alpha.6): popover.js
|
||||
* Bootstrap (v4.0.0-beta): popover.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -24,16 +24,18 @@ var Popover = function ($) {
|
||||
*/
|
||||
|
||||
var NAME = 'popover';
|
||||
var VERSION = '4.0.0-alpha.6';
|
||||
var VERSION = '4.0.0-beta';
|
||||
var DATA_KEY = 'bs.popover';
|
||||
var EVENT_KEY = '.' + DATA_KEY;
|
||||
var JQUERY_NO_CONFLICT = $.fn[NAME];
|
||||
var CLASS_PREFIX = 'bs-popover';
|
||||
var BSCLS_PREFIX_REGEX = new RegExp('(^|\\s)' + CLASS_PREFIX + '\\S+', 'g');
|
||||
|
||||
var Default = $.extend({}, Tooltip.Default, {
|
||||
placement: 'right',
|
||||
trigger: 'click',
|
||||
content: '',
|
||||
template: '<div class="popover" role="tooltip">' + '<h3 class="popover-title"></h3>' + '<div class="popover-content"></div></div>'
|
||||
template: '<div class="popover" role="tooltip">' + '<div class="arrow"></div>' + '<h3 class="popover-header"></h3>' + '<div class="popover-body"></div></div>'
|
||||
});
|
||||
|
||||
var DefaultType = $.extend({}, Tooltip.DefaultType, {
|
||||
@@ -46,8 +48,8 @@ var Popover = function ($) {
|
||||
};
|
||||
|
||||
var Selector = {
|
||||
TITLE: '.popover-title',
|
||||
CONTENT: '.popover-content'
|
||||
TITLE: '.popover-header',
|
||||
CONTENT: '.popover-body'
|
||||
};
|
||||
|
||||
var Event = {
|
||||
@@ -61,14 +63,14 @@ var Popover = function ($) {
|
||||
FOCUSOUT: 'focusout' + EVENT_KEY,
|
||||
MOUSEENTER: 'mouseenter' + EVENT_KEY,
|
||||
MOUSELEAVE: 'mouseleave' + EVENT_KEY
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------
|
||||
* Class Definition
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------
|
||||
* Class Definition
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
var Popover = function (_Tooltip) {
|
||||
_inherits(Popover, _Tooltip);
|
||||
|
||||
@@ -84,6 +86,10 @@ var Popover = function ($) {
|
||||
return this.getTitle() || this._getContent();
|
||||
};
|
||||
|
||||
Popover.prototype.addAttachmentClass = function addAttachmentClass(attachment) {
|
||||
$(this.getTipElement()).addClass(CLASS_PREFIX + '-' + attachment);
|
||||
};
|
||||
|
||||
Popover.prototype.getTipElement = function getTipElement() {
|
||||
return this.tip = this.tip || $(this.config.template)[0];
|
||||
};
|
||||
@@ -96,8 +102,6 @@ var Popover = function ($) {
|
||||
this.setElementContent($tip.find(Selector.CONTENT), this._getContent());
|
||||
|
||||
$tip.removeClass(ClassName.FADE + ' ' + ClassName.SHOW);
|
||||
|
||||
this.cleanupTether();
|
||||
};
|
||||
|
||||
// private
|
||||
@@ -106,6 +110,14 @@ var Popover = function ($) {
|
||||
return this.element.getAttribute('data-content') || (typeof this.config.content === 'function' ? this.config.content.call(this.element) : this.config.content);
|
||||
};
|
||||
|
||||
Popover.prototype._cleanTipClass = function _cleanTipClass() {
|
||||
var $tip = $(this.getTipElement());
|
||||
var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX);
|
||||
if (tabClass !== null && tabClass.length > 0) {
|
||||
$tip.removeClass(tabClass.join(''));
|
||||
}
|
||||
};
|
||||
|
||||
// static
|
||||
|
||||
Popover._jQueryInterface = function _jQueryInterface(config) {
|
||||
@@ -190,4 +202,4 @@ var Popover = function ($) {
|
||||
|
||||
return Popover;
|
||||
}(jQuery);
|
||||
//# sourceMappingURL=popover.js.map
|
||||
//# sourceMappingURL=popover.js.map
|
||||
+25
-23
@@ -6,7 +6,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v4.0.0-alpha.6): scrollspy.js
|
||||
* Bootstrap (v4.0.0-beta): scrollspy.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -20,7 +20,7 @@ var ScrollSpy = function ($) {
|
||||
*/
|
||||
|
||||
var NAME = 'scrollspy';
|
||||
var VERSION = '4.0.0-alpha.6';
|
||||
var VERSION = '4.0.0-beta';
|
||||
var DATA_KEY = 'bs.scrollspy';
|
||||
var EVENT_KEY = '.' + DATA_KEY;
|
||||
var DATA_API_KEY = '.data-api';
|
||||
@@ -47,18 +47,15 @@ var ScrollSpy = function ($) {
|
||||
var ClassName = {
|
||||
DROPDOWN_ITEM: 'dropdown-item',
|
||||
DROPDOWN_MENU: 'dropdown-menu',
|
||||
NAV_LINK: 'nav-link',
|
||||
NAV: 'nav',
|
||||
ACTIVE: 'active'
|
||||
};
|
||||
|
||||
var Selector = {
|
||||
DATA_SPY: '[data-spy="scroll"]',
|
||||
ACTIVE: '.active',
|
||||
LIST_ITEM: '.list-item',
|
||||
LI: 'li',
|
||||
LI_DROPDOWN: 'li.dropdown',
|
||||
NAV_LIST_GROUP: '.nav, .list-group',
|
||||
NAV_LINKS: '.nav-link',
|
||||
LIST_ITEMS: '.list-group-item',
|
||||
DROPDOWN: '.dropdown',
|
||||
DROPDOWN_ITEMS: '.dropdown-item',
|
||||
DROPDOWN_TOGGLE: '.dropdown-toggle'
|
||||
@@ -67,14 +64,14 @@ var ScrollSpy = function ($) {
|
||||
var OffsetMethod = {
|
||||
OFFSET: 'offset',
|
||||
POSITION: 'position'
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------
|
||||
* Class Definition
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------
|
||||
* Class Definition
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
var ScrollSpy = function () {
|
||||
function ScrollSpy(element, config) {
|
||||
var _this = this;
|
||||
@@ -84,7 +81,7 @@ var ScrollSpy = function ($) {
|
||||
this._element = element;
|
||||
this._scrollElement = element.tagName === 'BODY' ? window : element;
|
||||
this._config = this._getConfig(config);
|
||||
this._selector = this._config.target + ' ' + Selector.NAV_LINKS + ',' + (this._config.target + ' ' + Selector.DROPDOWN_ITEMS);
|
||||
this._selector = this._config.target + ' ' + Selector.NAV_LINKS + ',' + (this._config.target + ' ' + Selector.LIST_ITEMS + ',') + (this._config.target + ' ' + Selector.DROPDOWN_ITEMS);
|
||||
this._offsets = [];
|
||||
this._targets = [];
|
||||
this._activeTarget = null;
|
||||
@@ -126,9 +123,12 @@ var ScrollSpy = function ($) {
|
||||
target = $(targetSelector)[0];
|
||||
}
|
||||
|
||||
if (target && (target.offsetWidth || target.offsetHeight)) {
|
||||
// todo (fat): remove sketch reliance on jQuery position/offset
|
||||
return [$(target)[offsetMethod]().top + offsetBase, targetSelector];
|
||||
if (target) {
|
||||
var targetBCR = target.getBoundingClientRect();
|
||||
if (targetBCR.width || targetBCR.height) {
|
||||
// todo (fat): remove sketch reliance on jQuery position/offset
|
||||
return [$(target)[offsetMethod]().top + offsetBase, targetSelector];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}).filter(function (item) {
|
||||
@@ -183,7 +183,7 @@ var ScrollSpy = function ($) {
|
||||
};
|
||||
|
||||
ScrollSpy.prototype._getOffsetHeight = function _getOffsetHeight() {
|
||||
return this._scrollElement === window ? window.innerHeight : this._scrollElement.offsetHeight;
|
||||
return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height;
|
||||
};
|
||||
|
||||
ScrollSpy.prototype._process = function _process() {
|
||||
@@ -235,9 +235,11 @@ var ScrollSpy = function ($) {
|
||||
$link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);
|
||||
$link.addClass(ClassName.ACTIVE);
|
||||
} else {
|
||||
// todo (fat) this is kinda sus...
|
||||
// recursively add actives to tested nav-links
|
||||
$link.parents(Selector.LI).find('> ' + Selector.NAV_LINKS).addClass(ClassName.ACTIVE);
|
||||
// Set triggered link as active
|
||||
$link.addClass(ClassName.ACTIVE);
|
||||
// Set triggered links parents as active
|
||||
// With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
|
||||
$link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_LINKS + ', ' + Selector.LIST_ITEMS).addClass(ClassName.ACTIVE);
|
||||
}
|
||||
|
||||
$(this._scrollElement).trigger(Event.ACTIVATE, {
|
||||
@@ -315,4 +317,4 @@ var ScrollSpy = function ($) {
|
||||
|
||||
return ScrollSpy;
|
||||
}(jQuery);
|
||||
//# sourceMappingURL=scrollspy.js.map
|
||||
//# sourceMappingURL=scrollspy.js.map
|
||||
+16
-20
@@ -4,7 +4,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v4.0.0-alpha.6): tab.js
|
||||
* Bootstrap (v4.0.0-beta): tab.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -18,7 +18,7 @@ var Tab = function ($) {
|
||||
*/
|
||||
|
||||
var NAME = 'tab';
|
||||
var VERSION = '4.0.0-alpha.6';
|
||||
var VERSION = '4.0.0-beta';
|
||||
var DATA_KEY = 'bs.tab';
|
||||
var EVENT_KEY = '.' + DATA_KEY;
|
||||
var DATA_API_KEY = '.data-api';
|
||||
@@ -42,24 +42,20 @@ var Tab = function ($) {
|
||||
};
|
||||
|
||||
var Selector = {
|
||||
A: 'a',
|
||||
LI: 'li',
|
||||
DROPDOWN: '.dropdown',
|
||||
LIST: 'ul:not(.dropdown-menu), ol:not(.dropdown-menu), nav:not(.dropdown-menu)',
|
||||
FADE_CHILD: '> .nav-item .fade, > .fade',
|
||||
NAV_LIST_GROUP: '.nav, .list-group',
|
||||
ACTIVE: '.active',
|
||||
ACTIVE_CHILD: '> .nav-item > .active, > .active',
|
||||
DATA_TOGGLE: '[data-toggle="tab"], [data-toggle="pill"]',
|
||||
DATA_TOGGLE: '[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',
|
||||
DROPDOWN_TOGGLE: '.dropdown-toggle',
|
||||
DROPDOWN_ACTIVE_CHILD: '> .dropdown-menu .active'
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------
|
||||
* Class Definition
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------
|
||||
* Class Definition
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
var Tab = function () {
|
||||
function Tab(element) {
|
||||
_classCallCheck(this, Tab);
|
||||
@@ -80,7 +76,7 @@ var Tab = function ($) {
|
||||
|
||||
var target = void 0;
|
||||
var previous = void 0;
|
||||
var listElement = $(this._element).closest(Selector.LIST)[0];
|
||||
var listElement = $(this._element).closest(Selector.NAV_LIST_GROUP)[0];
|
||||
var selector = Util.getSelectorFromElement(this._element);
|
||||
|
||||
if (listElement) {
|
||||
@@ -133,7 +129,7 @@ var Tab = function ($) {
|
||||
};
|
||||
|
||||
Tab.prototype.dispose = function dispose() {
|
||||
$.removeClass(this._element, DATA_KEY);
|
||||
$.removeData(this._element, DATA_KEY);
|
||||
this._element = null;
|
||||
};
|
||||
|
||||
@@ -142,8 +138,8 @@ var Tab = function ($) {
|
||||
Tab.prototype._activate = function _activate(element, container, callback) {
|
||||
var _this2 = this;
|
||||
|
||||
var active = $(container).find(Selector.ACTIVE_CHILD)[0];
|
||||
var isTransitioning = callback && Util.supportsTransitionEnd() && (active && $(active).hasClass(ClassName.FADE) || Boolean($(container).find(Selector.FADE_CHILD)[0]));
|
||||
var active = $(container).find(Selector.ACTIVE)[0];
|
||||
var isTransitioning = callback && Util.supportsTransitionEnd() && active && $(active).hasClass(ClassName.FADE);
|
||||
|
||||
var complete = function complete() {
|
||||
return _this2._transitionComplete(element, active, isTransitioning, callback);
|
||||
@@ -255,4 +251,4 @@ var Tab = function ($) {
|
||||
|
||||
return Tab;
|
||||
}(jQuery);
|
||||
//# sourceMappingURL=tab.js.map
|
||||
//# sourceMappingURL=tab.js.map
|
||||
+141
-85
@@ -6,7 +6,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v4.0.0-alpha.6): tooltip.js
|
||||
* Bootstrap (v4.0.0-beta): tooltip.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -14,11 +14,11 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
|
||||
var Tooltip = function ($) {
|
||||
|
||||
/**
|
||||
* Check for Tether dependency
|
||||
* Tether - http://tether.io/
|
||||
* Check for Popper dependency
|
||||
* Popper - https://popper.js.org
|
||||
*/
|
||||
if (typeof Tether === 'undefined') {
|
||||
throw new Error('Bootstrap tooltips require Tether (http://tether.io/)');
|
||||
if (typeof Popper === 'undefined') {
|
||||
throw new Error('Bootstrap tooltips require Popper.js (https://popper.js.org)');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -28,26 +28,13 @@ var Tooltip = function ($) {
|
||||
*/
|
||||
|
||||
var NAME = 'tooltip';
|
||||
var VERSION = '4.0.0-alpha.6';
|
||||
var VERSION = '4.0.0-beta';
|
||||
var DATA_KEY = 'bs.tooltip';
|
||||
var EVENT_KEY = '.' + DATA_KEY;
|
||||
var JQUERY_NO_CONFLICT = $.fn[NAME];
|
||||
var TRANSITION_DURATION = 150;
|
||||
var CLASS_PREFIX = 'bs-tether';
|
||||
|
||||
var Default = {
|
||||
animation: true,
|
||||
template: '<div class="tooltip" role="tooltip">' + '<div class="tooltip-inner"></div></div>',
|
||||
trigger: 'hover focus',
|
||||
title: '',
|
||||
delay: 0,
|
||||
html: false,
|
||||
selector: false,
|
||||
placement: 'top',
|
||||
offset: '0 0',
|
||||
constraints: [],
|
||||
container: false
|
||||
};
|
||||
var CLASS_PREFIX = 'bs-tooltip';
|
||||
var BSCLS_PREFIX_REGEX = new RegExp('(^|\\s)' + CLASS_PREFIX + '\\S+', 'g');
|
||||
|
||||
var DefaultType = {
|
||||
animation: 'boolean',
|
||||
@@ -58,16 +45,31 @@ var Tooltip = function ($) {
|
||||
html: 'boolean',
|
||||
selector: '(string|boolean)',
|
||||
placement: '(string|function)',
|
||||
offset: 'string',
|
||||
constraints: 'array',
|
||||
container: '(string|element|boolean)'
|
||||
offset: '(number|string)',
|
||||
container: '(string|element|boolean)',
|
||||
fallbackPlacement: '(string|array)'
|
||||
};
|
||||
|
||||
var AttachmentMap = {
|
||||
TOP: 'bottom center',
|
||||
RIGHT: 'middle left',
|
||||
BOTTOM: 'top center',
|
||||
LEFT: 'middle right'
|
||||
AUTO: 'auto',
|
||||
TOP: 'top',
|
||||
RIGHT: 'right',
|
||||
BOTTOM: 'bottom',
|
||||
LEFT: 'left'
|
||||
};
|
||||
|
||||
var Default = {
|
||||
animation: true,
|
||||
template: '<div class="tooltip" role="tooltip">' + '<div class="arrow"></div>' + '<div class="tooltip-inner"></div></div>',
|
||||
trigger: 'hover focus',
|
||||
title: '',
|
||||
delay: 0,
|
||||
html: false,
|
||||
selector: false,
|
||||
placement: 'top',
|
||||
offset: 0,
|
||||
container: false,
|
||||
fallbackPlacement: 'flip'
|
||||
};
|
||||
|
||||
var HoverState = {
|
||||
@@ -95,12 +97,8 @@ var Tooltip = function ($) {
|
||||
|
||||
var Selector = {
|
||||
TOOLTIP: '.tooltip',
|
||||
TOOLTIP_INNER: '.tooltip-inner'
|
||||
};
|
||||
|
||||
var TetherClass = {
|
||||
element: false,
|
||||
enabled: false
|
||||
TOOLTIP_INNER: '.tooltip-inner',
|
||||
ARROW: '.arrow'
|
||||
};
|
||||
|
||||
var Trigger = {
|
||||
@@ -108,14 +106,14 @@ var Tooltip = function ($) {
|
||||
FOCUS: 'focus',
|
||||
CLICK: 'click',
|
||||
MANUAL: 'manual'
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------
|
||||
* Class Definition
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------
|
||||
* Class Definition
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
var Tooltip = function () {
|
||||
function Tooltip(element, config) {
|
||||
_classCallCheck(this, Tooltip);
|
||||
@@ -125,8 +123,7 @@ var Tooltip = function ($) {
|
||||
this._timeout = 0;
|
||||
this._hoverState = '';
|
||||
this._activeTrigger = {};
|
||||
this._isTransitioning = false;
|
||||
this._tether = null;
|
||||
this._popper = null;
|
||||
|
||||
// protected
|
||||
this.element = element;
|
||||
@@ -183,8 +180,6 @@ var Tooltip = function ($) {
|
||||
Tooltip.prototype.dispose = function dispose() {
|
||||
clearTimeout(this._timeout);
|
||||
|
||||
this.cleanupTether();
|
||||
|
||||
$.removeData(this.element, this.constructor.DATA_KEY);
|
||||
|
||||
$(this.element).off(this.constructor.EVENT_KEY);
|
||||
@@ -198,7 +193,10 @@ var Tooltip = function ($) {
|
||||
this._timeout = null;
|
||||
this._hoverState = null;
|
||||
this._activeTrigger = null;
|
||||
this._tether = null;
|
||||
if (this._popper !== null) {
|
||||
this._popper.destroy();
|
||||
}
|
||||
this._popper = null;
|
||||
|
||||
this.element = null;
|
||||
this.config = null;
|
||||
@@ -214,9 +212,6 @@ var Tooltip = function ($) {
|
||||
|
||||
var showEvent = $.Event(this.constructor.Event.SHOW);
|
||||
if (this.isWithContent() && this._isEnabled) {
|
||||
if (this._isTransitioning) {
|
||||
throw new Error('Tooltip is transitioning');
|
||||
}
|
||||
$(this.element).trigger(showEvent);
|
||||
|
||||
var isInTheDom = $.contains(this.element.ownerDocument.documentElement, this.element);
|
||||
@@ -240,33 +235,57 @@ var Tooltip = function ($) {
|
||||
var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement;
|
||||
|
||||
var attachment = this._getAttachment(placement);
|
||||
this.addAttachmentClass(attachment);
|
||||
|
||||
var container = this.config.container === false ? document.body : $(this.config.container);
|
||||
|
||||
$(tip).data(this.constructor.DATA_KEY, this).appendTo(container);
|
||||
$(tip).data(this.constructor.DATA_KEY, this);
|
||||
|
||||
if (!$.contains(this.element.ownerDocument.documentElement, this.tip)) {
|
||||
$(tip).appendTo(container);
|
||||
}
|
||||
|
||||
$(this.element).trigger(this.constructor.Event.INSERTED);
|
||||
|
||||
this._tether = new Tether({
|
||||
attachment: attachment,
|
||||
element: tip,
|
||||
target: this.element,
|
||||
classes: TetherClass,
|
||||
classPrefix: CLASS_PREFIX,
|
||||
offset: this.config.offset,
|
||||
constraints: this.config.constraints,
|
||||
addTargetClasses: false
|
||||
this._popper = new Popper(this.element, tip, {
|
||||
placement: attachment,
|
||||
modifiers: {
|
||||
offset: {
|
||||
offset: this.config.offset
|
||||
},
|
||||
flip: {
|
||||
behavior: this.config.fallbackPlacement
|
||||
},
|
||||
arrow: {
|
||||
element: Selector.ARROW
|
||||
}
|
||||
},
|
||||
onCreate: function onCreate(data) {
|
||||
if (data.originalPlacement !== data.placement) {
|
||||
_this._handlePopperPlacementChange(data);
|
||||
}
|
||||
},
|
||||
onUpdate: function onUpdate(data) {
|
||||
_this._handlePopperPlacementChange(data);
|
||||
}
|
||||
});
|
||||
|
||||
Util.reflow(tip);
|
||||
this._tether.position();
|
||||
|
||||
$(tip).addClass(ClassName.SHOW);
|
||||
|
||||
// if this is a touch-enabled device we add extra
|
||||
// empty mouseover listeners to the body's immediate children;
|
||||
// only needed because of broken event delegation on iOS
|
||||
// https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
|
||||
if ('ontouchstart' in document.documentElement) {
|
||||
$('body').children().on('mouseover', null, $.noop);
|
||||
}
|
||||
|
||||
var complete = function complete() {
|
||||
if (_this.config.animation) {
|
||||
_this._fixTransition();
|
||||
}
|
||||
var prevHoverState = _this._hoverState;
|
||||
_this._hoverState = null;
|
||||
_this._isTransitioning = false;
|
||||
|
||||
$(_this.element).trigger(_this.constructor.Event.SHOWN);
|
||||
|
||||
@@ -276,12 +295,10 @@ var Tooltip = function ($) {
|
||||
};
|
||||
|
||||
if (Util.supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) {
|
||||
this._isTransitioning = true;
|
||||
$(this.tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(Tooltip._TRANSITION_DURATION);
|
||||
return;
|
||||
} else {
|
||||
complete();
|
||||
}
|
||||
|
||||
complete();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -290,18 +307,17 @@ var Tooltip = function ($) {
|
||||
|
||||
var tip = this.getTipElement();
|
||||
var hideEvent = $.Event(this.constructor.Event.HIDE);
|
||||
if (this._isTransitioning) {
|
||||
throw new Error('Tooltip is transitioning');
|
||||
}
|
||||
var complete = function complete() {
|
||||
if (_this2._hoverState !== HoverState.SHOW && tip.parentNode) {
|
||||
tip.parentNode.removeChild(tip);
|
||||
}
|
||||
|
||||
_this2._cleanTipClass();
|
||||
_this2.element.removeAttribute('aria-describedby');
|
||||
$(_this2.element).trigger(_this2.constructor.Event.HIDDEN);
|
||||
_this2._isTransitioning = false;
|
||||
_this2.cleanupTether();
|
||||
if (_this2._popper !== null) {
|
||||
_this2._popper.destroy();
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
callback();
|
||||
@@ -316,12 +332,18 @@ var Tooltip = function ($) {
|
||||
|
||||
$(tip).removeClass(ClassName.SHOW);
|
||||
|
||||
// if this is a touch-enabled device we remove the extra
|
||||
// empty mouseover listeners we added for iOS support
|
||||
if ('ontouchstart' in document.documentElement) {
|
||||
$('body').children().off('mouseover', null, $.noop);
|
||||
}
|
||||
|
||||
this._activeTrigger[Trigger.CLICK] = false;
|
||||
this._activeTrigger[Trigger.FOCUS] = false;
|
||||
this._activeTrigger[Trigger.HOVER] = false;
|
||||
|
||||
if (Util.supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) {
|
||||
this._isTransitioning = true;
|
||||
|
||||
$(tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
|
||||
} else {
|
||||
complete();
|
||||
@@ -330,24 +352,30 @@ var Tooltip = function ($) {
|
||||
this._hoverState = '';
|
||||
};
|
||||
|
||||
Tooltip.prototype.update = function update() {
|
||||
if (this._popper !== null) {
|
||||
this._popper.scheduleUpdate();
|
||||
}
|
||||
};
|
||||
|
||||
// protected
|
||||
|
||||
Tooltip.prototype.isWithContent = function isWithContent() {
|
||||
return Boolean(this.getTitle());
|
||||
};
|
||||
|
||||
Tooltip.prototype.addAttachmentClass = function addAttachmentClass(attachment) {
|
||||
$(this.getTipElement()).addClass(CLASS_PREFIX + '-' + attachment);
|
||||
};
|
||||
|
||||
Tooltip.prototype.getTipElement = function getTipElement() {
|
||||
return this.tip = this.tip || $(this.config.template)[0];
|
||||
};
|
||||
|
||||
Tooltip.prototype.setContent = function setContent() {
|
||||
var $tip = $(this.getTipElement());
|
||||
|
||||
this.setElementContent($tip.find(Selector.TOOLTIP_INNER), this.getTitle());
|
||||
|
||||
$tip.removeClass(ClassName.FADE + ' ' + ClassName.SHOW);
|
||||
|
||||
this.cleanupTether();
|
||||
};
|
||||
|
||||
Tooltip.prototype.setElementContent = function setElementContent($element, content) {
|
||||
@@ -376,12 +404,6 @@ var Tooltip = function ($) {
|
||||
return title;
|
||||
};
|
||||
|
||||
Tooltip.prototype.cleanupTether = function cleanupTether() {
|
||||
if (this._tether) {
|
||||
this._tether.destroy();
|
||||
}
|
||||
};
|
||||
|
||||
// private
|
||||
|
||||
Tooltip.prototype._getAttachment = function _getAttachment(placement) {
|
||||
@@ -521,6 +543,14 @@ var Tooltip = function ($) {
|
||||
};
|
||||
}
|
||||
|
||||
if (config.title && typeof config.title === 'number') {
|
||||
config.title = config.title.toString();
|
||||
}
|
||||
|
||||
if (config.content && typeof config.content === 'number') {
|
||||
config.content = config.content.toString();
|
||||
}
|
||||
|
||||
Util.typeCheckConfig(NAME, config, this.constructor.DefaultType);
|
||||
|
||||
return config;
|
||||
@@ -540,6 +570,32 @@ var Tooltip = function ($) {
|
||||
return config;
|
||||
};
|
||||
|
||||
Tooltip.prototype._cleanTipClass = function _cleanTipClass() {
|
||||
var $tip = $(this.getTipElement());
|
||||
var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX);
|
||||
if (tabClass !== null && tabClass.length > 0) {
|
||||
$tip.removeClass(tabClass.join(''));
|
||||
}
|
||||
};
|
||||
|
||||
Tooltip.prototype._handlePopperPlacementChange = function _handlePopperPlacementChange(data) {
|
||||
this._cleanTipClass();
|
||||
this.addAttachmentClass(this._getAttachment(data.placement));
|
||||
};
|
||||
|
||||
Tooltip.prototype._fixTransition = function _fixTransition() {
|
||||
var tip = this.getTipElement();
|
||||
var initConfigAnimation = this.config.animation;
|
||||
if (tip.getAttribute('x-placement') !== null) {
|
||||
return;
|
||||
}
|
||||
$(tip).removeClass(ClassName.FADE);
|
||||
this.config.animation = false;
|
||||
this.hide();
|
||||
this.show();
|
||||
this.config.animation = initConfigAnimation;
|
||||
};
|
||||
|
||||
// static
|
||||
|
||||
Tooltip._jQueryInterface = function _jQueryInterface(config) {
|
||||
@@ -619,5 +675,5 @@ var Tooltip = function ($) {
|
||||
};
|
||||
|
||||
return Tooltip;
|
||||
}(jQuery); /* global Tether */
|
||||
//# sourceMappingURL=tooltip.js.map
|
||||
}(jQuery); /* global Popper */
|
||||
//# sourceMappingURL=tooltip.js.map
|
||||
+11
-9
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v4.0.0-alpha.6): util.js
|
||||
* Bootstrap (v4.0.0-beta): util.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -22,10 +22,9 @@ var Util = function ($) {
|
||||
MozTransition: 'transitionend',
|
||||
OTransition: 'oTransitionEnd otransitionend',
|
||||
transition: 'transitionend'
|
||||
};
|
||||
|
||||
// shoutout AngusCroll (https://goo.gl/pxwQGp)
|
||||
function toType(obj) {
|
||||
// shoutout AngusCroll (https://goo.gl/pxwQGp)
|
||||
};function toType(obj) {
|
||||
return {}.toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
|
||||
}
|
||||
|
||||
@@ -111,13 +110,16 @@ var Util = function ($) {
|
||||
},
|
||||
getSelectorFromElement: function getSelectorFromElement(element) {
|
||||
var selector = element.getAttribute('data-target');
|
||||
|
||||
if (!selector) {
|
||||
if (!selector || selector === '#') {
|
||||
selector = element.getAttribute('href') || '';
|
||||
selector = /^#[a-z]/i.test(selector) ? selector : null;
|
||||
}
|
||||
|
||||
return selector;
|
||||
try {
|
||||
var $selector = $(selector);
|
||||
return $selector.length > 0 ? selector : null;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
reflow: function reflow(element) {
|
||||
return element.offsetHeight;
|
||||
@@ -147,4 +149,4 @@ var Util = function ($) {
|
||||
|
||||
return Util;
|
||||
}(jQuery);
|
||||
//# sourceMappingURL=util.js.map
|
||||
//# sourceMappingURL=util.js.map
|
||||
+2
-2
@@ -3,7 +3,7 @@ import Util from './util'
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v4.0.0-alpha.6): alert.js
|
||||
* Bootstrap (v4.0.0-beta): alert.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -18,7 +18,7 @@ const Alert = (($) => {
|
||||
*/
|
||||
|
||||
const NAME = 'alert'
|
||||
const VERSION = '4.0.0-alpha.6'
|
||||
const VERSION = '4.0.0-beta'
|
||||
const DATA_KEY = 'bs.alert'
|
||||
const EVENT_KEY = `.${DATA_KEY}`
|
||||
const DATA_API_KEY = '.data-api'
|
||||
|
||||
+14
-4
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v4.0.0-alpha.6): button.js
|
||||
* Bootstrap (v4.0.0-beta): button.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -15,7 +15,7 @@ const Button = (($) => {
|
||||
*/
|
||||
|
||||
const NAME = 'button'
|
||||
const VERSION = '4.0.0-alpha.6'
|
||||
const VERSION = '4.0.0-beta'
|
||||
const DATA_KEY = 'bs.button'
|
||||
const EVENT_KEY = `.${DATA_KEY}`
|
||||
const DATA_API_KEY = '.data-api'
|
||||
@@ -66,6 +66,7 @@ const Button = (($) => {
|
||||
|
||||
toggle() {
|
||||
let triggerChangeEvent = true
|
||||
let addAriaPressed = true
|
||||
const rootElement = $(this._element).closest(
|
||||
Selector.DATA_TOGGLE
|
||||
)[0]
|
||||
@@ -89,17 +90,26 @@ const Button = (($) => {
|
||||
}
|
||||
|
||||
if (triggerChangeEvent) {
|
||||
if (input.hasAttribute('disabled') ||
|
||||
rootElement.hasAttribute('disabled') ||
|
||||
input.classList.contains('disabled') ||
|
||||
rootElement.classList.contains('disabled')) {
|
||||
return
|
||||
}
|
||||
input.checked = !$(this._element).hasClass(ClassName.ACTIVE)
|
||||
$(input).trigger('change')
|
||||
}
|
||||
|
||||
input.focus()
|
||||
addAriaPressed = false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this._element.setAttribute('aria-pressed',
|
||||
!$(this._element).hasClass(ClassName.ACTIVE))
|
||||
if (addAriaPressed) {
|
||||
this._element.setAttribute('aria-pressed',
|
||||
!$(this._element).hasClass(ClassName.ACTIVE))
|
||||
}
|
||||
|
||||
if (triggerChangeEvent) {
|
||||
$(this._element).toggleClass(ClassName.ACTIVE)
|
||||
|
||||
+48
-24
@@ -3,7 +3,7 @@ import Util from './util'
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v4.0.0-alpha.6): carousel.js
|
||||
* Bootstrap (v4.0.0-beta): carousel.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -17,15 +17,16 @@ const Carousel = (($) => {
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
const NAME = 'carousel'
|
||||
const VERSION = '4.0.0-alpha.6'
|
||||
const DATA_KEY = 'bs.carousel'
|
||||
const EVENT_KEY = `.${DATA_KEY}`
|
||||
const DATA_API_KEY = '.data-api'
|
||||
const JQUERY_NO_CONFLICT = $.fn[NAME]
|
||||
const TRANSITION_DURATION = 600
|
||||
const ARROW_LEFT_KEYCODE = 37 // KeyboardEvent.which value for left arrow key
|
||||
const ARROW_RIGHT_KEYCODE = 39 // KeyboardEvent.which value for right arrow key
|
||||
const NAME = 'carousel'
|
||||
const VERSION = '4.0.0-beta'
|
||||
const DATA_KEY = 'bs.carousel'
|
||||
const EVENT_KEY = `.${DATA_KEY}`
|
||||
const DATA_API_KEY = '.data-api'
|
||||
const JQUERY_NO_CONFLICT = $.fn[NAME]
|
||||
const TRANSITION_DURATION = 600
|
||||
const ARROW_LEFT_KEYCODE = 37 // KeyboardEvent.which value for left arrow key
|
||||
const ARROW_RIGHT_KEYCODE = 39 // KeyboardEvent.which value for right arrow key
|
||||
const TOUCHEVENT_COMPAT_WAIT = 500 // Time for mouse compat events to fire after touch
|
||||
|
||||
const Default = {
|
||||
interval : 5000,
|
||||
@@ -56,6 +57,7 @@ const Carousel = (($) => {
|
||||
KEYDOWN : `keydown${EVENT_KEY}`,
|
||||
MOUSEENTER : `mouseenter${EVENT_KEY}`,
|
||||
MOUSELEAVE : `mouseleave${EVENT_KEY}`,
|
||||
TOUCHEND : `touchend${EVENT_KEY}`,
|
||||
LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}`,
|
||||
CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`
|
||||
}
|
||||
@@ -98,6 +100,8 @@ const Carousel = (($) => {
|
||||
this._isPaused = false
|
||||
this._isSliding = false
|
||||
|
||||
this.touchTimeout = null
|
||||
|
||||
this._config = this._getConfig(config)
|
||||
this._element = $(element)[0]
|
||||
this._indicatorsElement = $(this._element).find(Selector.INDICATORS)[0]
|
||||
@@ -120,10 +124,9 @@ const Carousel = (($) => {
|
||||
// public
|
||||
|
||||
next() {
|
||||
if (this._isSliding) {
|
||||
throw new Error('Carousel is sliding')
|
||||
if (!this._isSliding) {
|
||||
this._slide(Direction.NEXT)
|
||||
}
|
||||
this._slide(Direction.NEXT)
|
||||
}
|
||||
|
||||
nextWhenVisible() {
|
||||
@@ -134,10 +137,9 @@ const Carousel = (($) => {
|
||||
}
|
||||
|
||||
prev() {
|
||||
if (this._isSliding) {
|
||||
throw new Error('Carousel is sliding')
|
||||
if (!this._isSliding) {
|
||||
this._slide(Direction.PREV)
|
||||
}
|
||||
this._slide(Direction.PREVIOUS)
|
||||
}
|
||||
|
||||
pause(event) {
|
||||
@@ -195,7 +197,7 @@ const Carousel = (($) => {
|
||||
|
||||
const direction = index > activeIndex ?
|
||||
Direction.NEXT :
|
||||
Direction.PREVIOUS
|
||||
Direction.PREV
|
||||
|
||||
this._slide(direction, this._items[index])
|
||||
}
|
||||
@@ -229,11 +231,26 @@ const Carousel = (($) => {
|
||||
.on(Event.KEYDOWN, (event) => this._keydown(event))
|
||||
}
|
||||
|
||||
if (this._config.pause === 'hover' &&
|
||||
!('ontouchstart' in document.documentElement)) {
|
||||
if (this._config.pause === 'hover') {
|
||||
$(this._element)
|
||||
.on(Event.MOUSEENTER, (event) => this.pause(event))
|
||||
.on(Event.MOUSELEAVE, (event) => this.cycle(event))
|
||||
if ('ontouchstart' in document.documentElement) {
|
||||
// if it's a touch-enabled device, mouseenter/leave are fired as
|
||||
// part of the mouse compatibility events on first tap - the carousel
|
||||
// would stop cycling until user tapped out of it;
|
||||
// here, we listen for touchend, explicitly pause the carousel
|
||||
// (as if it's the second time we tap on it, mouseenter compat event
|
||||
// is NOT fired) and after a timeout (to allow for mouse compatibility
|
||||
// events to fire) we explicitly restart cycling
|
||||
$(this._element).on(Event.TOUCHEND, () => {
|
||||
this.pause()
|
||||
if (this.touchTimeout) {
|
||||
clearTimeout(this.touchTimeout)
|
||||
}
|
||||
this.touchTimeout = setTimeout((event) => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,7 +280,7 @@ const Carousel = (($) => {
|
||||
|
||||
_getItemByDirection(direction, activeElement) {
|
||||
const isNextDirection = direction === Direction.NEXT
|
||||
const isPrevDirection = direction === Direction.PREVIOUS
|
||||
const isPrevDirection = direction === Direction.PREV
|
||||
const activeIndex = this._getItemIndex(activeElement)
|
||||
const lastItemIndex = this._items.length - 1
|
||||
const isGoingToWrap = isPrevDirection && activeIndex === 0 ||
|
||||
@@ -273,7 +290,7 @@ const Carousel = (($) => {
|
||||
return activeElement
|
||||
}
|
||||
|
||||
const delta = direction === Direction.PREVIOUS ? -1 : 1
|
||||
const delta = direction === Direction.PREV ? -1 : 1
|
||||
const itemIndex = (activeIndex + delta) % this._items.length
|
||||
|
||||
return itemIndex === -1 ?
|
||||
@@ -282,9 +299,13 @@ const Carousel = (($) => {
|
||||
|
||||
|
||||
_triggerSlideEvent(relatedTarget, eventDirectionName) {
|
||||
const targetIndex = this._getItemIndex(relatedTarget)
|
||||
const fromIndex = this._getItemIndex($(this._element).find(Selector.ACTIVE_ITEM)[0])
|
||||
const slideEvent = $.Event(Event.SLIDE, {
|
||||
relatedTarget,
|
||||
direction: eventDirectionName
|
||||
direction: eventDirectionName,
|
||||
from: fromIndex,
|
||||
to: targetIndex
|
||||
})
|
||||
|
||||
$(this._element).trigger(slideEvent)
|
||||
@@ -310,9 +331,10 @@ const Carousel = (($) => {
|
||||
|
||||
_slide(direction, element) {
|
||||
const activeElement = $(this._element).find(Selector.ACTIVE_ITEM)[0]
|
||||
const activeElementIndex = this._getItemIndex(activeElement)
|
||||
const nextElement = element || activeElement &&
|
||||
this._getItemByDirection(direction, activeElement)
|
||||
|
||||
const nextElementIndex = this._getItemIndex(nextElement)
|
||||
const isCycling = Boolean(this._interval)
|
||||
|
||||
let directionalClassName
|
||||
@@ -354,7 +376,9 @@ const Carousel = (($) => {
|
||||
|
||||
const slidEvent = $.Event(Event.SLID, {
|
||||
relatedTarget: nextElement,
|
||||
direction: eventDirectionName
|
||||
direction: eventDirectionName,
|
||||
from: activeElementIndex,
|
||||
to: nextElementIndex
|
||||
})
|
||||
|
||||
if (Util.supportsTransitionEnd() &&
|
||||
|
||||
+39
-30
@@ -3,7 +3,7 @@ import Util from './util'
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v4.0.0-alpha.6): collapse.js
|
||||
* Bootstrap (v4.0.0-beta): collapse.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -18,7 +18,7 @@ const Collapse = (($) => {
|
||||
*/
|
||||
|
||||
const NAME = 'collapse'
|
||||
const VERSION = '4.0.0-alpha.6'
|
||||
const VERSION = '4.0.0-beta'
|
||||
const DATA_KEY = 'bs.collapse'
|
||||
const EVENT_KEY = `.${DATA_KEY}`
|
||||
const DATA_API_KEY = '.data-api'
|
||||
@@ -56,7 +56,7 @@ const Collapse = (($) => {
|
||||
}
|
||||
|
||||
const Selector = {
|
||||
ACTIVES : '.card > .show, .card > .collapsing',
|
||||
ACTIVES : '.show, .collapsing',
|
||||
DATA_TOGGLE : '[data-toggle="collapse"]'
|
||||
}
|
||||
|
||||
@@ -77,6 +77,14 @@ const Collapse = (($) => {
|
||||
`[data-toggle="collapse"][href="#${element.id}"],` +
|
||||
`[data-toggle="collapse"][data-target="#${element.id}"]`
|
||||
))
|
||||
const tabToggles = $(Selector.DATA_TOGGLE)
|
||||
for (let i = 0; i < tabToggles.length; i++) {
|
||||
const elem = tabToggles[i]
|
||||
const selector = Util.getSelectorFromElement(elem)
|
||||
if (selector !== null && $(selector).filter(element).length > 0) {
|
||||
this._triggerArray.push(elem)
|
||||
}
|
||||
}
|
||||
|
||||
this._parent = this._config.parent ? this._getParent() : null
|
||||
|
||||
@@ -112,11 +120,8 @@ const Collapse = (($) => {
|
||||
}
|
||||
|
||||
show() {
|
||||
if (this._isTransitioning) {
|
||||
throw new Error('Collapse is transitioning')
|
||||
}
|
||||
|
||||
if ($(this._element).hasClass(ClassName.SHOW)) {
|
||||
if (this._isTransitioning ||
|
||||
$(this._element).hasClass(ClassName.SHOW)) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -124,7 +129,7 @@ const Collapse = (($) => {
|
||||
let activesData
|
||||
|
||||
if (this._parent) {
|
||||
actives = $.makeArray($(this._parent).find(Selector.ACTIVES))
|
||||
actives = $.makeArray($(this._parent).children().children(Selector.ACTIVES))
|
||||
if (!actives.length) {
|
||||
actives = null
|
||||
}
|
||||
@@ -157,7 +162,6 @@ const Collapse = (($) => {
|
||||
.addClass(ClassName.COLLAPSING)
|
||||
|
||||
this._element.style[dimension] = 0
|
||||
this._element.setAttribute('aria-expanded', true)
|
||||
|
||||
if (this._triggerArray.length) {
|
||||
$(this._triggerArray)
|
||||
@@ -196,11 +200,8 @@ const Collapse = (($) => {
|
||||
}
|
||||
|
||||
hide() {
|
||||
if (this._isTransitioning) {
|
||||
throw new Error('Collapse is transitioning')
|
||||
}
|
||||
|
||||
if (!$(this._element).hasClass(ClassName.SHOW)) {
|
||||
if (this._isTransitioning ||
|
||||
!$(this._element).hasClass(ClassName.SHOW)) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -211,10 +212,8 @@ const Collapse = (($) => {
|
||||
}
|
||||
|
||||
const dimension = this._getDimension()
|
||||
const offsetDimension = dimension === Dimension.WIDTH ?
|
||||
'offsetWidth' : 'offsetHeight'
|
||||
|
||||
this._element.style[dimension] = `${this._element[offsetDimension]}px`
|
||||
this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`
|
||||
|
||||
Util.reflow(this._element)
|
||||
|
||||
@@ -223,12 +222,18 @@ const Collapse = (($) => {
|
||||
.removeClass(ClassName.COLLAPSE)
|
||||
.removeClass(ClassName.SHOW)
|
||||
|
||||
this._element.setAttribute('aria-expanded', false)
|
||||
|
||||
if (this._triggerArray.length) {
|
||||
$(this._triggerArray)
|
||||
.addClass(ClassName.COLLAPSED)
|
||||
.attr('aria-expanded', false)
|
||||
for (let i = 0; i < this._triggerArray.length; i++) {
|
||||
const trigger = this._triggerArray[i]
|
||||
const selector = Util.getSelectorFromElement(trigger)
|
||||
if (selector !== null) {
|
||||
const $elem = $(selector)
|
||||
if (!$elem.hasClass(ClassName.SHOW)) {
|
||||
$(trigger).addClass(ClassName.COLLAPSED)
|
||||
.attr('aria-expanded', false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.setTransitioning(true)
|
||||
@@ -300,7 +305,6 @@ const Collapse = (($) => {
|
||||
_addAriaAndCollapsedClass(element, triggerArray) {
|
||||
if (element) {
|
||||
const isOpen = $(element).hasClass(ClassName.SHOW)
|
||||
element.setAttribute('aria-expanded', isOpen)
|
||||
|
||||
if (triggerArray.length) {
|
||||
$(triggerArray)
|
||||
@@ -357,13 +361,18 @@ const Collapse = (($) => {
|
||||
*/
|
||||
|
||||
$(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
|
||||
event.preventDefault()
|
||||
if (!/input|textarea/i.test(event.target.tagName)) {
|
||||
event.preventDefault()
|
||||
}
|
||||
|
||||
const target = Collapse._getTargetFromElement(this)
|
||||
const data = $(target).data(DATA_KEY)
|
||||
const config = data ? 'toggle' : $(this).data()
|
||||
|
||||
Collapse._jQueryInterface.call($(target), config)
|
||||
const $trigger = $(this)
|
||||
const selector = Util.getSelectorFromElement(this)
|
||||
$(selector).each(function () {
|
||||
const $target = $(this)
|
||||
const data = $target.data(DATA_KEY)
|
||||
const config = data ? 'toggle' : $trigger.data()
|
||||
Collapse._jQueryInterface.call($target, config)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
|
||||
+202
-55
@@ -1,15 +1,24 @@
|
||||
/* global Popper */
|
||||
|
||||
import Util from './util'
|
||||
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v4.0.0-alpha.6): dropdown.js
|
||||
* Bootstrap (v4.0.0-beta): dropdown.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
const Dropdown = (($) => {
|
||||
|
||||
/**
|
||||
* Check for Popper dependency
|
||||
* Popper - https://popper.js.org
|
||||
*/
|
||||
if (typeof Popper === 'undefined') {
|
||||
throw new Error('Bootstrap dropdown require Popper.js (https://popper.js.org)')
|
||||
}
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------
|
||||
@@ -18,15 +27,18 @@ const Dropdown = (($) => {
|
||||
*/
|
||||
|
||||
const NAME = 'dropdown'
|
||||
const VERSION = '4.0.0-alpha.6'
|
||||
const VERSION = '4.0.0-beta'
|
||||
const DATA_KEY = 'bs.dropdown'
|
||||
const EVENT_KEY = `.${DATA_KEY}`
|
||||
const DATA_API_KEY = '.data-api'
|
||||
const JQUERY_NO_CONFLICT = $.fn[NAME]
|
||||
const ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key
|
||||
const SPACE_KEYCODE = 32 // KeyboardEvent.which value for space key
|
||||
const TAB_KEYCODE = 9 // KeyboardEvent.which value for tab key
|
||||
const ARROW_UP_KEYCODE = 38 // KeyboardEvent.which value for up arrow key
|
||||
const ARROW_DOWN_KEYCODE = 40 // KeyboardEvent.which value for down arrow key
|
||||
const RIGHT_MOUSE_BUTTON_WHICH = 3 // MouseEvent.which value for the right button (assuming a right-handed mouse)
|
||||
const REGEXP_KEYDOWN = new RegExp(`${ARROW_UP_KEYCODE}|${ARROW_DOWN_KEYCODE}|${ESCAPE_KEYCODE}`)
|
||||
|
||||
const Event = {
|
||||
HIDE : `hide${EVENT_KEY}`,
|
||||
@@ -35,25 +47,43 @@ const Dropdown = (($) => {
|
||||
SHOWN : `shown${EVENT_KEY}`,
|
||||
CLICK : `click${EVENT_KEY}`,
|
||||
CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`,
|
||||
FOCUSIN_DATA_API : `focusin${EVENT_KEY}${DATA_API_KEY}`,
|
||||
KEYDOWN_DATA_API : `keydown${EVENT_KEY}${DATA_API_KEY}`
|
||||
KEYDOWN_DATA_API : `keydown${EVENT_KEY}${DATA_API_KEY}`,
|
||||
KEYUP_DATA_API : `keyup${EVENT_KEY}${DATA_API_KEY}`
|
||||
}
|
||||
|
||||
const ClassName = {
|
||||
BACKDROP : 'dropdown-backdrop',
|
||||
DISABLED : 'disabled',
|
||||
SHOW : 'show'
|
||||
DISABLED : 'disabled',
|
||||
SHOW : 'show',
|
||||
DROPUP : 'dropup',
|
||||
MENURIGHT : 'dropdown-menu-right',
|
||||
MENULEFT : 'dropdown-menu-left'
|
||||
}
|
||||
|
||||
const Selector = {
|
||||
BACKDROP : '.dropdown-backdrop',
|
||||
DATA_TOGGLE : '[data-toggle="dropdown"]',
|
||||
FORM_CHILD : '.dropdown form',
|
||||
ROLE_MENU : '[role="menu"]',
|
||||
ROLE_LISTBOX : '[role="listbox"]',
|
||||
MENU : '.dropdown-menu',
|
||||
NAVBAR_NAV : '.navbar-nav',
|
||||
VISIBLE_ITEMS : '[role="menu"] li:not(.disabled) a, '
|
||||
+ '[role="listbox"] li:not(.disabled) a'
|
||||
VISIBLE_ITEMS : '.dropdown-menu .dropdown-item:not(.disabled)'
|
||||
}
|
||||
|
||||
const AttachmentMap = {
|
||||
TOP : 'top-start',
|
||||
TOPEND : 'top-end',
|
||||
BOTTOM : 'bottom-start',
|
||||
BOTTOMEND : 'bottom-end'
|
||||
}
|
||||
|
||||
const Default = {
|
||||
placement : AttachmentMap.BOTTOM,
|
||||
offset : 0,
|
||||
flip : true
|
||||
}
|
||||
|
||||
const DefaultType = {
|
||||
placement : 'string',
|
||||
offset : '(number|string)',
|
||||
flip : 'boolean'
|
||||
}
|
||||
|
||||
|
||||
@@ -65,8 +95,12 @@ const Dropdown = (($) => {
|
||||
|
||||
class Dropdown {
|
||||
|
||||
constructor(element) {
|
||||
this._element = element
|
||||
constructor(element, config) {
|
||||
this._element = element
|
||||
this._popper = null
|
||||
this._config = this._getConfig(config)
|
||||
this._menu = this._getMenuElement()
|
||||
this._inNavbar = this._detectNavbar()
|
||||
|
||||
this._addEventListeners()
|
||||
}
|
||||
@@ -78,75 +112,177 @@ const Dropdown = (($) => {
|
||||
return VERSION
|
||||
}
|
||||
|
||||
static get Default() {
|
||||
return Default
|
||||
}
|
||||
|
||||
static get DefaultType() {
|
||||
return DefaultType
|
||||
}
|
||||
|
||||
// public
|
||||
|
||||
toggle() {
|
||||
if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {
|
||||
return false
|
||||
if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED)) {
|
||||
return
|
||||
}
|
||||
|
||||
const parent = Dropdown._getParentFromElement(this)
|
||||
const isActive = $(parent).hasClass(ClassName.SHOW)
|
||||
const parent = Dropdown._getParentFromElement(this._element)
|
||||
const isActive = $(this._menu).hasClass(ClassName.SHOW)
|
||||
|
||||
Dropdown._clearMenus()
|
||||
|
||||
if (isActive) {
|
||||
return false
|
||||
}
|
||||
|
||||
if ('ontouchstart' in document.documentElement &&
|
||||
!$(parent).closest(Selector.NAVBAR_NAV).length) {
|
||||
|
||||
// if mobile we use a backdrop because click events don't delegate
|
||||
const dropdown = document.createElement('div')
|
||||
dropdown.className = ClassName.BACKDROP
|
||||
$(dropdown).insertBefore(this)
|
||||
$(dropdown).on('click', Dropdown._clearMenus)
|
||||
return
|
||||
}
|
||||
|
||||
const relatedTarget = {
|
||||
relatedTarget : this
|
||||
relatedTarget : this._element
|
||||
}
|
||||
const showEvent = $.Event(Event.SHOW, relatedTarget)
|
||||
const showEvent = $.Event(Event.SHOW, relatedTarget)
|
||||
|
||||
$(parent).trigger(showEvent)
|
||||
|
||||
if (showEvent.isDefaultPrevented()) {
|
||||
return false
|
||||
return
|
||||
}
|
||||
|
||||
this.focus()
|
||||
this.setAttribute('aria-expanded', true)
|
||||
let element = this._element
|
||||
// for dropup with alignment we use the parent as popper container
|
||||
if ($(parent).hasClass(ClassName.DROPUP)) {
|
||||
if ($(this._menu).hasClass(ClassName.MENULEFT) || $(this._menu).hasClass(ClassName.MENURIGHT)) {
|
||||
element = parent
|
||||
}
|
||||
}
|
||||
this._popper = new Popper(element, this._menu, this._getPopperConfig())
|
||||
|
||||
$(parent).toggleClass(ClassName.SHOW)
|
||||
$(parent).trigger($.Event(Event.SHOWN, relatedTarget))
|
||||
// if this is a touch-enabled device we add extra
|
||||
// empty mouseover listeners to the body's immediate children;
|
||||
// only needed because of broken event delegation on iOS
|
||||
// https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
|
||||
if ('ontouchstart' in document.documentElement &&
|
||||
!$(parent).closest(Selector.NAVBAR_NAV).length) {
|
||||
$('body').children().on('mouseover', null, $.noop)
|
||||
}
|
||||
|
||||
return false
|
||||
this._element.focus()
|
||||
this._element.setAttribute('aria-expanded', true)
|
||||
|
||||
$(this._menu).toggleClass(ClassName.SHOW)
|
||||
$(parent)
|
||||
.toggleClass(ClassName.SHOW)
|
||||
.trigger($.Event(Event.SHOWN, relatedTarget))
|
||||
}
|
||||
|
||||
dispose() {
|
||||
$.removeData(this._element, DATA_KEY)
|
||||
$(this._element).off(EVENT_KEY)
|
||||
this._element = null
|
||||
this._menu = null
|
||||
if (this._popper !== null) {
|
||||
this._popper.destroy()
|
||||
}
|
||||
this._popper = null
|
||||
}
|
||||
|
||||
update() {
|
||||
this._inNavbar = this._detectNavbar()
|
||||
if (this._popper !== null) {
|
||||
this._popper.scheduleUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
// private
|
||||
|
||||
_addEventListeners() {
|
||||
$(this._element).on(Event.CLICK, this.toggle)
|
||||
$(this._element).on(Event.CLICK, (event) => {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
this.toggle()
|
||||
})
|
||||
}
|
||||
|
||||
_getConfig(config) {
|
||||
const elementData = $(this._element).data()
|
||||
if (elementData.placement !== undefined) {
|
||||
elementData.placement = AttachmentMap[elementData.placement.toUpperCase()]
|
||||
}
|
||||
|
||||
config = $.extend(
|
||||
{},
|
||||
this.constructor.Default,
|
||||
$(this._element).data(),
|
||||
config
|
||||
)
|
||||
|
||||
Util.typeCheckConfig(
|
||||
NAME,
|
||||
config,
|
||||
this.constructor.DefaultType
|
||||
)
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
_getMenuElement() {
|
||||
if (!this._menu) {
|
||||
const parent = Dropdown._getParentFromElement(this._element)
|
||||
this._menu = $(parent).find(Selector.MENU)[0]
|
||||
}
|
||||
return this._menu
|
||||
}
|
||||
|
||||
_getPlacement() {
|
||||
const $parentDropdown = $(this._element).parent()
|
||||
let placement = this._config.placement
|
||||
|
||||
// Handle dropup
|
||||
if ($parentDropdown.hasClass(ClassName.DROPUP) || this._config.placement === AttachmentMap.TOP) {
|
||||
placement = AttachmentMap.TOP
|
||||
if ($(this._menu).hasClass(ClassName.MENURIGHT)) {
|
||||
placement = AttachmentMap.TOPEND
|
||||
}
|
||||
} else if ($(this._menu).hasClass(ClassName.MENURIGHT)) {
|
||||
placement = AttachmentMap.BOTTOMEND
|
||||
}
|
||||
return placement
|
||||
}
|
||||
|
||||
_detectNavbar() {
|
||||
return $(this._element).closest('.navbar').length > 0
|
||||
}
|
||||
|
||||
_getPopperConfig() {
|
||||
const popperConfig = {
|
||||
placement : this._getPlacement(),
|
||||
modifiers : {
|
||||
offset : {
|
||||
offset : this._config.offset
|
||||
},
|
||||
flip : {
|
||||
enabled : this._config.flip
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Disable Popper.js for Dropdown in Navbar
|
||||
if (this._inNavbar) {
|
||||
popperConfig.modifiers.applyStyle = {
|
||||
enabled: !this._inNavbar
|
||||
}
|
||||
}
|
||||
return popperConfig
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
static _jQueryInterface(config) {
|
||||
return this.each(function () {
|
||||
let data = $(this).data(DATA_KEY)
|
||||
const _config = typeof config === 'object' ? config : null
|
||||
|
||||
if (!data) {
|
||||
data = new Dropdown(this)
|
||||
data = new Dropdown(this, _config)
|
||||
$(this).data(DATA_KEY, data)
|
||||
}
|
||||
|
||||
@@ -154,35 +290,36 @@ const Dropdown = (($) => {
|
||||
if (data[config] === undefined) {
|
||||
throw new Error(`No method named "${config}"`)
|
||||
}
|
||||
data[config].call(this)
|
||||
data[config]()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
static _clearMenus(event) {
|
||||
if (event && event.which === RIGHT_MOUSE_BUTTON_WHICH) {
|
||||
if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH ||
|
||||
event.type === 'keyup' && event.which !== TAB_KEYCODE)) {
|
||||
return
|
||||
}
|
||||
|
||||
const backdrop = $(Selector.BACKDROP)[0]
|
||||
if (backdrop) {
|
||||
backdrop.parentNode.removeChild(backdrop)
|
||||
}
|
||||
|
||||
const toggles = $.makeArray($(Selector.DATA_TOGGLE))
|
||||
|
||||
for (let i = 0; i < toggles.length; i++) {
|
||||
const parent = Dropdown._getParentFromElement(toggles[i])
|
||||
const context = $(toggles[i]).data(DATA_KEY)
|
||||
const relatedTarget = {
|
||||
relatedTarget : toggles[i]
|
||||
}
|
||||
|
||||
if (!context) {
|
||||
continue
|
||||
}
|
||||
|
||||
const dropdownMenu = context._menu
|
||||
if (!$(parent).hasClass(ClassName.SHOW)) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (event && (event.type === 'click' &&
|
||||
/input|textarea/i.test(event.target.tagName) || event.type === 'focusin')
|
||||
/input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE)
|
||||
&& $.contains(parent, event.target)) {
|
||||
continue
|
||||
}
|
||||
@@ -193,8 +330,15 @@ const Dropdown = (($) => {
|
||||
continue
|
||||
}
|
||||
|
||||
// if this is a touch-enabled device we remove the extra
|
||||
// empty mouseover listeners we added for iOS support
|
||||
if ('ontouchstart' in document.documentElement) {
|
||||
$('body').children().off('mouseover', null, $.noop)
|
||||
}
|
||||
|
||||
toggles[i].setAttribute('aria-expanded', 'false')
|
||||
|
||||
$(dropdownMenu).removeClass(ClassName.SHOW)
|
||||
$(parent)
|
||||
.removeClass(ClassName.SHOW)
|
||||
.trigger($.Event(Event.HIDDEN, relatedTarget))
|
||||
@@ -213,7 +357,7 @@ const Dropdown = (($) => {
|
||||
}
|
||||
|
||||
static _dataApiKeydownHandler(event) {
|
||||
if (!/(38|40|27|32)/.test(event.which) ||
|
||||
if (!REGEXP_KEYDOWN.test(event.which) || /button/i.test(event.target.tagName) && event.which === SPACE_KEYCODE ||
|
||||
/input|textarea/i.test(event.target.tagName)) {
|
||||
return
|
||||
}
|
||||
@@ -228,8 +372,8 @@ const Dropdown = (($) => {
|
||||
const parent = Dropdown._getParentFromElement(this)
|
||||
const isActive = $(parent).hasClass(ClassName.SHOW)
|
||||
|
||||
if (!isActive && event.which !== ESCAPE_KEYCODE ||
|
||||
isActive && event.which === ESCAPE_KEYCODE) {
|
||||
if (!isActive && (event.which !== ESCAPE_KEYCODE || event.which !== SPACE_KEYCODE) ||
|
||||
isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) {
|
||||
|
||||
if (event.which === ESCAPE_KEYCODE) {
|
||||
const toggle = $(parent).find(Selector.DATA_TOGGLE)[0]
|
||||
@@ -274,10 +418,13 @@ const Dropdown = (($) => {
|
||||
|
||||
$(document)
|
||||
.on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler)
|
||||
.on(Event.KEYDOWN_DATA_API, Selector.ROLE_MENU, Dropdown._dataApiKeydownHandler)
|
||||
.on(Event.KEYDOWN_DATA_API, Selector.ROLE_LISTBOX, Dropdown._dataApiKeydownHandler)
|
||||
.on(`${Event.CLICK_DATA_API} ${Event.FOCUSIN_DATA_API}`, Dropdown._clearMenus)
|
||||
.on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, Dropdown.prototype.toggle)
|
||||
.on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler)
|
||||
.on(`${Event.CLICK_DATA_API} ${Event.KEYUP_DATA_API}`, Dropdown._clearMenus)
|
||||
.on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
Dropdown._jQueryInterface.call($(this), 'toggle')
|
||||
})
|
||||
.on(Event.CLICK_DATA_API, Selector.FORM_CHILD, (e) => {
|
||||
e.stopPropagation()
|
||||
})
|
||||
|
||||
+62
-29
@@ -3,7 +3,7 @@ import Util from './util'
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v4.0.0-alpha.6): modal.js
|
||||
* Bootstrap (v4.0.0-beta): modal.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -18,7 +18,7 @@ const Modal = (($) => {
|
||||
*/
|
||||
|
||||
const NAME = 'modal'
|
||||
const VERSION = '4.0.0-alpha.6'
|
||||
const VERSION = '4.0.0-beta'
|
||||
const DATA_KEY = 'bs.modal'
|
||||
const EVENT_KEY = `.${DATA_KEY}`
|
||||
const DATA_API_KEY = '.data-api'
|
||||
@@ -67,7 +67,8 @@ const Modal = (($) => {
|
||||
DIALOG : '.modal-dialog',
|
||||
DATA_TOGGLE : '[data-toggle="modal"]',
|
||||
DATA_DISMISS : '[data-dismiss="modal"]',
|
||||
FIXED_CONTENT : '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top'
|
||||
FIXED_CONTENT : '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top',
|
||||
NAVBAR_TOGGLER : '.navbar-toggler'
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +88,6 @@ const Modal = (($) => {
|
||||
this._isShown = false
|
||||
this._isBodyOverflowing = false
|
||||
this._ignoreBackdropClick = false
|
||||
this._isTransitioning = false
|
||||
this._originalBodyPadding = 0
|
||||
this._scrollbarWidth = 0
|
||||
}
|
||||
@@ -112,13 +112,13 @@ const Modal = (($) => {
|
||||
|
||||
show(relatedTarget) {
|
||||
if (this._isTransitioning) {
|
||||
throw new Error('Modal is transitioning')
|
||||
return
|
||||
}
|
||||
|
||||
if (Util.supportsTransitionEnd() &&
|
||||
$(this._element).hasClass(ClassName.FADE)) {
|
||||
if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE)) {
|
||||
this._isTransitioning = true
|
||||
}
|
||||
|
||||
const showEvent = $.Event(Event.SHOW, {
|
||||
relatedTarget
|
||||
})
|
||||
@@ -161,17 +161,18 @@ const Modal = (($) => {
|
||||
event.preventDefault()
|
||||
}
|
||||
|
||||
if (this._isTransitioning) {
|
||||
throw new Error('Modal is transitioning')
|
||||
if (this._isTransitioning || !this._isShown) {
|
||||
return
|
||||
}
|
||||
|
||||
const transition = Util.supportsTransitionEnd() &&
|
||||
$(this._element).hasClass(ClassName.FADE)
|
||||
const transition = Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE)
|
||||
|
||||
if (transition) {
|
||||
this._isTransitioning = true
|
||||
}
|
||||
|
||||
const hideEvent = $.Event(Event.HIDE)
|
||||
|
||||
$(this._element).trigger(hideEvent)
|
||||
|
||||
if (!this._isShown || hideEvent.isDefaultPrevented()) {
|
||||
@@ -191,6 +192,7 @@ const Modal = (($) => {
|
||||
$(this._dialog).off(Event.MOUSEDOWN_DISMISS)
|
||||
|
||||
if (transition) {
|
||||
|
||||
$(this._element)
|
||||
.one(Util.TRANSITION_END, (event) => this._hideModal(event))
|
||||
.emulateTransitionEnd(TRANSITION_DURATION)
|
||||
@@ -211,10 +213,12 @@ const Modal = (($) => {
|
||||
this._isShown = null
|
||||
this._isBodyOverflowing = null
|
||||
this._ignoreBackdropClick = null
|
||||
this._originalBodyPadding = null
|
||||
this._scrollbarWidth = null
|
||||
}
|
||||
|
||||
handleUpdate() {
|
||||
this._adjustDialog()
|
||||
}
|
||||
|
||||
// private
|
||||
|
||||
@@ -285,6 +289,7 @@ const Modal = (($) => {
|
||||
if (this._isShown && this._config.keyboard) {
|
||||
$(this._element).on(Event.KEYDOWN_DISMISS, (event) => {
|
||||
if (event.which === ESCAPE_KEYCODE) {
|
||||
event.preventDefault()
|
||||
this.hide()
|
||||
}
|
||||
})
|
||||
@@ -296,7 +301,7 @@ const Modal = (($) => {
|
||||
|
||||
_setResizeEvent() {
|
||||
if (this._isShown) {
|
||||
$(window).on(Event.RESIZE, (event) => this._handleUpdate(event))
|
||||
$(window).on(Event.RESIZE, (event) => this.handleUpdate(event))
|
||||
} else {
|
||||
$(window).off(Event.RESIZE)
|
||||
}
|
||||
@@ -304,7 +309,7 @@ const Modal = (($) => {
|
||||
|
||||
_hideModal() {
|
||||
this._element.style.display = 'none'
|
||||
this._element.setAttribute('aria-hidden', 'true')
|
||||
this._element.setAttribute('aria-hidden', true)
|
||||
this._isTransitioning = false
|
||||
this._showBackdrop(() => {
|
||||
$(document.body).removeClass(ClassName.OPEN)
|
||||
@@ -401,10 +406,6 @@ const Modal = (($) => {
|
||||
// todo (fat): these should probably be refactored out of modal.js
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
_handleUpdate() {
|
||||
this._adjustDialog()
|
||||
}
|
||||
|
||||
_adjustDialog() {
|
||||
const isModalOverflowing =
|
||||
this._element.scrollHeight > document.documentElement.clientHeight
|
||||
@@ -429,28 +430,60 @@ const Modal = (($) => {
|
||||
}
|
||||
|
||||
_setScrollbar() {
|
||||
const bodyPadding = parseInt(
|
||||
$(Selector.FIXED_CONTENT).css('padding-right') || 0,
|
||||
10
|
||||
)
|
||||
|
||||
this._originalBodyPadding = document.body.style.paddingRight || ''
|
||||
|
||||
if (this._isBodyOverflowing) {
|
||||
document.body.style.paddingRight =
|
||||
`${bodyPadding + this._scrollbarWidth}px`
|
||||
// Note: DOMNode.style.paddingRight returns the actual value or '' if not set
|
||||
// while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set
|
||||
|
||||
// Adjust fixed content padding
|
||||
$(Selector.FIXED_CONTENT).each((index, element) => {
|
||||
const actualPadding = $(element)[0].style.paddingRight
|
||||
const calculatedPadding = $(element).css('padding-right')
|
||||
$(element).data('padding-right', actualPadding).css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`)
|
||||
})
|
||||
|
||||
// Adjust navbar-toggler margin
|
||||
$(Selector.NAVBAR_TOGGLER).each((index, element) => {
|
||||
const actualMargin = $(element)[0].style.marginRight
|
||||
const calculatedMargin = $(element).css('margin-right')
|
||||
$(element).data('margin-right', actualMargin).css('margin-right', `${parseFloat(calculatedMargin) + this._scrollbarWidth}px`)
|
||||
})
|
||||
|
||||
// Adjust body padding
|
||||
const actualPadding = document.body.style.paddingRight
|
||||
const calculatedPadding = $('body').css('padding-right')
|
||||
$('body').data('padding-right', actualPadding).css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`)
|
||||
}
|
||||
}
|
||||
|
||||
_resetScrollbar() {
|
||||
document.body.style.paddingRight = this._originalBodyPadding
|
||||
// Restore fixed content padding
|
||||
$(Selector.FIXED_CONTENT).each((index, element) => {
|
||||
const padding = $(element).data('padding-right')
|
||||
if (typeof padding !== 'undefined') {
|
||||
$(element).css('padding-right', padding).removeData('padding-right')
|
||||
}
|
||||
})
|
||||
|
||||
// Restore navbar-toggler margin
|
||||
$(Selector.NAVBAR_TOGGLER).each((index, element) => {
|
||||
const margin = $(element).data('margin-right')
|
||||
if (typeof margin !== 'undefined') {
|
||||
$(element).css('margin-right', margin).removeData('margin-right')
|
||||
}
|
||||
})
|
||||
|
||||
// Restore body padding
|
||||
const padding = $('body').data('padding-right')
|
||||
if (typeof padding !== 'undefined') {
|
||||
$('body').css('padding-right', padding).removeData('padding-right')
|
||||
}
|
||||
}
|
||||
|
||||
_getScrollbarWidth() { // thx d.walsh
|
||||
const scrollDiv = document.createElement('div')
|
||||
scrollDiv.className = ClassName.SCROLLBAR_MEASURER
|
||||
document.body.appendChild(scrollDiv)
|
||||
const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
|
||||
const scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth
|
||||
document.body.removeChild(scrollDiv)
|
||||
return scrollbarWidth
|
||||
}
|
||||
|
||||
+21
-8
@@ -3,7 +3,7 @@ import Tooltip from './tooltip'
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v4.0.0-alpha.6): popover.js
|
||||
* Bootstrap (v4.0.0-beta): popover.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -18,18 +18,21 @@ const Popover = (($) => {
|
||||
*/
|
||||
|
||||
const NAME = 'popover'
|
||||
const VERSION = '4.0.0-alpha.6'
|
||||
const VERSION = '4.0.0-beta'
|
||||
const DATA_KEY = 'bs.popover'
|
||||
const EVENT_KEY = `.${DATA_KEY}`
|
||||
const JQUERY_NO_CONFLICT = $.fn[NAME]
|
||||
const CLASS_PREFIX = 'bs-popover'
|
||||
const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g')
|
||||
|
||||
const Default = $.extend({}, Tooltip.Default, {
|
||||
placement : 'right',
|
||||
trigger : 'click',
|
||||
content : '',
|
||||
template : '<div class="popover" role="tooltip">'
|
||||
+ '<h3 class="popover-title"></h3>'
|
||||
+ '<div class="popover-content"></div></div>'
|
||||
+ '<div class="arrow"></div>'
|
||||
+ '<h3 class="popover-header"></h3>'
|
||||
+ '<div class="popover-body"></div></div>'
|
||||
})
|
||||
|
||||
const DefaultType = $.extend({}, Tooltip.DefaultType, {
|
||||
@@ -42,8 +45,8 @@ const Popover = (($) => {
|
||||
}
|
||||
|
||||
const Selector = {
|
||||
TITLE : '.popover-title',
|
||||
CONTENT : '.popover-content'
|
||||
TITLE : '.popover-header',
|
||||
CONTENT : '.popover-body'
|
||||
}
|
||||
|
||||
const Event = {
|
||||
@@ -106,6 +109,10 @@ const Popover = (($) => {
|
||||
return this.getTitle() || this._getContent()
|
||||
}
|
||||
|
||||
addAttachmentClass(attachment) {
|
||||
$(this.getTipElement()).addClass(`${CLASS_PREFIX}-${attachment}`)
|
||||
}
|
||||
|
||||
getTipElement() {
|
||||
return this.tip = this.tip || $(this.config.template)[0]
|
||||
}
|
||||
@@ -118,8 +125,6 @@ const Popover = (($) => {
|
||||
this.setElementContent($tip.find(Selector.CONTENT), this._getContent())
|
||||
|
||||
$tip.removeClass(`${ClassName.FADE} ${ClassName.SHOW}`)
|
||||
|
||||
this.cleanupTether()
|
||||
}
|
||||
|
||||
// private
|
||||
@@ -131,6 +136,14 @@ const Popover = (($) => {
|
||||
this.config.content)
|
||||
}
|
||||
|
||||
_cleanTipClass() {
|
||||
const $tip = $(this.getTipElement())
|
||||
const tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX)
|
||||
if (tabClass !== null && tabClass.length > 0) {
|
||||
$tip.removeClass(tabClass.join(''))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
|
||||
|
||||
+20
-17
@@ -3,7 +3,7 @@ import Util from './util'
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v4.0.0-alpha.6): scrollspy.js
|
||||
* Bootstrap (v4.0.0-beta): scrollspy.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -18,7 +18,7 @@ const ScrollSpy = (($) => {
|
||||
*/
|
||||
|
||||
const NAME = 'scrollspy'
|
||||
const VERSION = '4.0.0-alpha.6'
|
||||
const VERSION = '4.0.0-beta'
|
||||
const DATA_KEY = 'bs.scrollspy'
|
||||
const EVENT_KEY = `.${DATA_KEY}`
|
||||
const DATA_API_KEY = '.data-api'
|
||||
@@ -45,18 +45,15 @@ const ScrollSpy = (($) => {
|
||||
const ClassName = {
|
||||
DROPDOWN_ITEM : 'dropdown-item',
|
||||
DROPDOWN_MENU : 'dropdown-menu',
|
||||
NAV_LINK : 'nav-link',
|
||||
NAV : 'nav',
|
||||
ACTIVE : 'active'
|
||||
}
|
||||
|
||||
const Selector = {
|
||||
DATA_SPY : '[data-spy="scroll"]',
|
||||
ACTIVE : '.active',
|
||||
LIST_ITEM : '.list-item',
|
||||
LI : 'li',
|
||||
LI_DROPDOWN : 'li.dropdown',
|
||||
NAV_LIST_GROUP : '.nav, .list-group',
|
||||
NAV_LINKS : '.nav-link',
|
||||
LIST_ITEMS : '.list-group-item',
|
||||
DROPDOWN : '.dropdown',
|
||||
DROPDOWN_ITEMS : '.dropdown-item',
|
||||
DROPDOWN_TOGGLE : '.dropdown-toggle'
|
||||
@@ -81,6 +78,7 @@ const ScrollSpy = (($) => {
|
||||
this._scrollElement = element.tagName === 'BODY' ? window : element
|
||||
this._config = this._getConfig(config)
|
||||
this._selector = `${this._config.target} ${Selector.NAV_LINKS},`
|
||||
+ `${this._config.target} ${Selector.LIST_ITEMS},`
|
||||
+ `${this._config.target} ${Selector.DROPDOWN_ITEMS}`
|
||||
this._offsets = []
|
||||
this._targets = []
|
||||
@@ -133,12 +131,15 @@ const ScrollSpy = (($) => {
|
||||
target = $(targetSelector)[0]
|
||||
}
|
||||
|
||||
if (target && (target.offsetWidth || target.offsetHeight)) {
|
||||
// todo (fat): remove sketch reliance on jQuery position/offset
|
||||
return [
|
||||
$(target)[offsetMethod]().top + offsetBase,
|
||||
targetSelector
|
||||
]
|
||||
if (target) {
|
||||
const targetBCR = target.getBoundingClientRect()
|
||||
if (targetBCR.width || targetBCR.height) {
|
||||
// todo (fat): remove sketch reliance on jQuery position/offset
|
||||
return [
|
||||
$(target)[offsetMethod]().top + offsetBase,
|
||||
targetSelector
|
||||
]
|
||||
}
|
||||
}
|
||||
return null
|
||||
})
|
||||
@@ -198,7 +199,7 @@ const ScrollSpy = (($) => {
|
||||
|
||||
_getOffsetHeight() {
|
||||
return this._scrollElement === window ?
|
||||
window.innerHeight : this._scrollElement.offsetHeight
|
||||
window.innerHeight : this._scrollElement.getBoundingClientRect().height
|
||||
}
|
||||
|
||||
_process() {
|
||||
@@ -256,9 +257,11 @@ const ScrollSpy = (($) => {
|
||||
$link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE)
|
||||
$link.addClass(ClassName.ACTIVE)
|
||||
} else {
|
||||
// todo (fat) this is kinda sus...
|
||||
// recursively add actives to tested nav-links
|
||||
$link.parents(Selector.LI).find(`> ${Selector.NAV_LINKS}`).addClass(ClassName.ACTIVE)
|
||||
// Set triggered link as active
|
||||
$link.addClass(ClassName.ACTIVE)
|
||||
// Set triggered links parents as active
|
||||
// With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
|
||||
$link.parents(Selector.NAV_LIST_GROUP).prev(`${Selector.NAV_LINKS}, ${Selector.LIST_ITEMS}`).addClass(ClassName.ACTIVE)
|
||||
}
|
||||
|
||||
$(this._scrollElement).trigger(Event.ACTIVATE, {
|
||||
|
||||
+8
-13
@@ -3,7 +3,7 @@ import Util from './util'
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v4.0.0-alpha.6): tab.js
|
||||
* Bootstrap (v4.0.0-beta): tab.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -18,7 +18,7 @@ const Tab = (($) => {
|
||||
*/
|
||||
|
||||
const NAME = 'tab'
|
||||
const VERSION = '4.0.0-alpha.6'
|
||||
const VERSION = '4.0.0-beta'
|
||||
const DATA_KEY = 'bs.tab'
|
||||
const EVENT_KEY = `.${DATA_KEY}`
|
||||
const DATA_API_KEY = '.data-api'
|
||||
@@ -42,14 +42,10 @@ const Tab = (($) => {
|
||||
}
|
||||
|
||||
const Selector = {
|
||||
A : 'a',
|
||||
LI : 'li',
|
||||
DROPDOWN : '.dropdown',
|
||||
LIST : 'ul:not(.dropdown-menu), ol:not(.dropdown-menu), nav:not(.dropdown-menu)',
|
||||
FADE_CHILD : '> .nav-item .fade, > .fade',
|
||||
NAV_LIST_GROUP : '.nav, .list-group',
|
||||
ACTIVE : '.active',
|
||||
ACTIVE_CHILD : '> .nav-item > .active, > .active',
|
||||
DATA_TOGGLE : '[data-toggle="tab"], [data-toggle="pill"]',
|
||||
DATA_TOGGLE : '[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',
|
||||
DROPDOWN_TOGGLE : '.dropdown-toggle',
|
||||
DROPDOWN_ACTIVE_CHILD : '> .dropdown-menu .active'
|
||||
}
|
||||
@@ -87,7 +83,7 @@ const Tab = (($) => {
|
||||
|
||||
let target
|
||||
let previous
|
||||
const listElement = $(this._element).closest(Selector.LIST)[0]
|
||||
const listElement = $(this._element).closest(Selector.NAV_LIST_GROUP)[0]
|
||||
const selector = Util.getSelectorFromElement(this._element)
|
||||
|
||||
if (listElement) {
|
||||
@@ -144,7 +140,7 @@ const Tab = (($) => {
|
||||
}
|
||||
|
||||
dispose() {
|
||||
$.removeClass(this._element, DATA_KEY)
|
||||
$.removeData(this._element, DATA_KEY)
|
||||
this._element = null
|
||||
}
|
||||
|
||||
@@ -152,11 +148,10 @@ const Tab = (($) => {
|
||||
// private
|
||||
|
||||
_activate(element, container, callback) {
|
||||
const active = $(container).find(Selector.ACTIVE_CHILD)[0]
|
||||
const active = $(container).find(Selector.ACTIVE)[0]
|
||||
const isTransitioning = callback
|
||||
&& Util.supportsTransitionEnd()
|
||||
&& (active && $(active).hasClass(ClassName.FADE)
|
||||
|| Boolean($(container).find(Selector.FADE_CHILD)[0]))
|
||||
&& (active && $(active).hasClass(ClassName.FADE))
|
||||
|
||||
const complete = () => this._transitionComplete(
|
||||
element,
|
||||
|
||||
+147
-93
@@ -1,11 +1,11 @@
|
||||
/* global Tether */
|
||||
/* global Popper */
|
||||
|
||||
import Util from './util'
|
||||
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v4.0.0-alpha.6): tooltip.js
|
||||
* Bootstrap (v4.0.0-beta): tooltip.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -13,11 +13,11 @@ import Util from './util'
|
||||
const Tooltip = (($) => {
|
||||
|
||||
/**
|
||||
* Check for Tether dependency
|
||||
* Tether - http://tether.io/
|
||||
* Check for Popper dependency
|
||||
* Popper - https://popper.js.org
|
||||
*/
|
||||
if (typeof Tether === 'undefined') {
|
||||
throw new Error('Bootstrap tooltips require Tether (http://tether.io/)')
|
||||
if (typeof Popper === 'undefined') {
|
||||
throw new Error('Bootstrap tooltips require Popper.js (https://popper.js.org)')
|
||||
}
|
||||
|
||||
|
||||
@@ -28,47 +28,50 @@ const Tooltip = (($) => {
|
||||
*/
|
||||
|
||||
const NAME = 'tooltip'
|
||||
const VERSION = '4.0.0-alpha.6'
|
||||
const VERSION = '4.0.0-beta'
|
||||
const DATA_KEY = 'bs.tooltip'
|
||||
const EVENT_KEY = `.${DATA_KEY}`
|
||||
const JQUERY_NO_CONFLICT = $.fn[NAME]
|
||||
const TRANSITION_DURATION = 150
|
||||
const CLASS_PREFIX = 'bs-tether'
|
||||
|
||||
const Default = {
|
||||
animation : true,
|
||||
template : '<div class="tooltip" role="tooltip">'
|
||||
+ '<div class="tooltip-inner"></div></div>',
|
||||
trigger : 'hover focus',
|
||||
title : '',
|
||||
delay : 0,
|
||||
html : false,
|
||||
selector : false,
|
||||
placement : 'top',
|
||||
offset : '0 0',
|
||||
constraints : [],
|
||||
container : false
|
||||
}
|
||||
const CLASS_PREFIX = 'bs-tooltip'
|
||||
const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g')
|
||||
|
||||
const DefaultType = {
|
||||
animation : 'boolean',
|
||||
template : 'string',
|
||||
title : '(string|element|function)',
|
||||
trigger : 'string',
|
||||
delay : '(number|object)',
|
||||
html : 'boolean',
|
||||
selector : '(string|boolean)',
|
||||
placement : '(string|function)',
|
||||
offset : 'string',
|
||||
constraints : 'array',
|
||||
container : '(string|element|boolean)'
|
||||
animation : 'boolean',
|
||||
template : 'string',
|
||||
title : '(string|element|function)',
|
||||
trigger : 'string',
|
||||
delay : '(number|object)',
|
||||
html : 'boolean',
|
||||
selector : '(string|boolean)',
|
||||
placement : '(string|function)',
|
||||
offset : '(number|string)',
|
||||
container : '(string|element|boolean)',
|
||||
fallbackPlacement : '(string|array)'
|
||||
}
|
||||
|
||||
const AttachmentMap = {
|
||||
TOP : 'bottom center',
|
||||
RIGHT : 'middle left',
|
||||
BOTTOM : 'top center',
|
||||
LEFT : 'middle right'
|
||||
AUTO : 'auto',
|
||||
TOP : 'top',
|
||||
RIGHT : 'right',
|
||||
BOTTOM : 'bottom',
|
||||
LEFT : 'left'
|
||||
}
|
||||
|
||||
const Default = {
|
||||
animation : true,
|
||||
template : '<div class="tooltip" role="tooltip">'
|
||||
+ '<div class="arrow"></div>'
|
||||
+ '<div class="tooltip-inner"></div></div>',
|
||||
trigger : 'hover focus',
|
||||
title : '',
|
||||
delay : 0,
|
||||
html : false,
|
||||
selector : false,
|
||||
placement : 'top',
|
||||
offset : 0,
|
||||
container : false,
|
||||
fallbackPlacement : 'flip'
|
||||
}
|
||||
|
||||
const HoverState = {
|
||||
@@ -96,12 +99,8 @@ const Tooltip = (($) => {
|
||||
|
||||
const Selector = {
|
||||
TOOLTIP : '.tooltip',
|
||||
TOOLTIP_INNER : '.tooltip-inner'
|
||||
}
|
||||
|
||||
const TetherClass = {
|
||||
element : false,
|
||||
enabled : false
|
||||
TOOLTIP_INNER : '.tooltip-inner',
|
||||
ARROW : '.arrow'
|
||||
}
|
||||
|
||||
const Trigger = {
|
||||
@@ -123,12 +122,11 @@ const Tooltip = (($) => {
|
||||
constructor(element, config) {
|
||||
|
||||
// private
|
||||
this._isEnabled = true
|
||||
this._timeout = 0
|
||||
this._hoverState = ''
|
||||
this._activeTrigger = {}
|
||||
this._isTransitioning = false
|
||||
this._tether = null
|
||||
this._isEnabled = true
|
||||
this._timeout = 0
|
||||
this._hoverState = ''
|
||||
this._activeTrigger = {}
|
||||
this._popper = null
|
||||
|
||||
// protected
|
||||
this.element = element
|
||||
@@ -220,8 +218,6 @@ const Tooltip = (($) => {
|
||||
dispose() {
|
||||
clearTimeout(this._timeout)
|
||||
|
||||
this.cleanupTether()
|
||||
|
||||
$.removeData(this.element, this.constructor.DATA_KEY)
|
||||
|
||||
$(this.element).off(this.constructor.EVENT_KEY)
|
||||
@@ -235,7 +231,10 @@ const Tooltip = (($) => {
|
||||
this._timeout = null
|
||||
this._hoverState = null
|
||||
this._activeTrigger = null
|
||||
this._tether = null
|
||||
if (this._popper !== null) {
|
||||
this._popper.destroy()
|
||||
}
|
||||
this._popper = null
|
||||
|
||||
this.element = null
|
||||
this.config = null
|
||||
@@ -249,9 +248,6 @@ const Tooltip = (($) => {
|
||||
|
||||
const showEvent = $.Event(this.constructor.Event.SHOW)
|
||||
if (this.isWithContent() && this._isEnabled) {
|
||||
if (this._isTransitioning) {
|
||||
throw new Error('Tooltip is transitioning')
|
||||
}
|
||||
$(this.element).trigger(showEvent)
|
||||
|
||||
const isInTheDom = $.contains(
|
||||
@@ -280,35 +276,57 @@ const Tooltip = (($) => {
|
||||
this.config.placement
|
||||
|
||||
const attachment = this._getAttachment(placement)
|
||||
this.addAttachmentClass(attachment)
|
||||
|
||||
const container = this.config.container === false ? document.body : $(this.config.container)
|
||||
|
||||
$(tip)
|
||||
.data(this.constructor.DATA_KEY, this)
|
||||
.appendTo(container)
|
||||
$(tip).data(this.constructor.DATA_KEY, this)
|
||||
|
||||
if (!$.contains(this.element.ownerDocument.documentElement, this.tip)) {
|
||||
$(tip).appendTo(container)
|
||||
}
|
||||
|
||||
$(this.element).trigger(this.constructor.Event.INSERTED)
|
||||
|
||||
this._tether = new Tether({
|
||||
attachment,
|
||||
element : tip,
|
||||
target : this.element,
|
||||
classes : TetherClass,
|
||||
classPrefix : CLASS_PREFIX,
|
||||
offset : this.config.offset,
|
||||
constraints : this.config.constraints,
|
||||
addTargetClasses: false
|
||||
this._popper = new Popper(this.element, tip, {
|
||||
placement: attachment,
|
||||
modifiers: {
|
||||
offset: {
|
||||
offset: this.config.offset
|
||||
},
|
||||
flip: {
|
||||
behavior: this.config.fallbackPlacement
|
||||
},
|
||||
arrow: {
|
||||
element: Selector.ARROW
|
||||
}
|
||||
},
|
||||
onCreate: (data) => {
|
||||
if (data.originalPlacement !== data.placement) {
|
||||
this._handlePopperPlacementChange(data)
|
||||
}
|
||||
},
|
||||
onUpdate : (data) => {
|
||||
this._handlePopperPlacementChange(data)
|
||||
}
|
||||
})
|
||||
|
||||
Util.reflow(tip)
|
||||
this._tether.position()
|
||||
|
||||
$(tip).addClass(ClassName.SHOW)
|
||||
|
||||
// if this is a touch-enabled device we add extra
|
||||
// empty mouseover listeners to the body's immediate children;
|
||||
// only needed because of broken event delegation on iOS
|
||||
// https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
|
||||
if ('ontouchstart' in document.documentElement) {
|
||||
$('body').children().on('mouseover', null, $.noop)
|
||||
}
|
||||
|
||||
const complete = () => {
|
||||
if (this.config.animation) {
|
||||
this._fixTransition()
|
||||
}
|
||||
const prevHoverState = this._hoverState
|
||||
this._hoverState = null
|
||||
this._isTransitioning = false
|
||||
this._hoverState = null
|
||||
|
||||
$(this.element).trigger(this.constructor.Event.SHOWN)
|
||||
|
||||
@@ -318,32 +336,29 @@ const Tooltip = (($) => {
|
||||
}
|
||||
|
||||
if (Util.supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) {
|
||||
this._isTransitioning = true
|
||||
$(this.tip)
|
||||
.one(Util.TRANSITION_END, complete)
|
||||
.emulateTransitionEnd(Tooltip._TRANSITION_DURATION)
|
||||
return
|
||||
} else {
|
||||
complete()
|
||||
}
|
||||
|
||||
complete()
|
||||
}
|
||||
}
|
||||
|
||||
hide(callback) {
|
||||
const tip = this.getTipElement()
|
||||
const hideEvent = $.Event(this.constructor.Event.HIDE)
|
||||
if (this._isTransitioning) {
|
||||
throw new Error('Tooltip is transitioning')
|
||||
}
|
||||
const complete = () => {
|
||||
if (this._hoverState !== HoverState.SHOW && tip.parentNode) {
|
||||
tip.parentNode.removeChild(tip)
|
||||
}
|
||||
|
||||
this._cleanTipClass()
|
||||
this.element.removeAttribute('aria-describedby')
|
||||
$(this.element).trigger(this.constructor.Event.HIDDEN)
|
||||
this._isTransitioning = false
|
||||
this.cleanupTether()
|
||||
if (this._popper !== null) {
|
||||
this._popper.destroy()
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
callback()
|
||||
@@ -358,13 +373,19 @@ const Tooltip = (($) => {
|
||||
|
||||
$(tip).removeClass(ClassName.SHOW)
|
||||
|
||||
// if this is a touch-enabled device we remove the extra
|
||||
// empty mouseover listeners we added for iOS support
|
||||
if ('ontouchstart' in document.documentElement) {
|
||||
$('body').children().off('mouseover', null, $.noop)
|
||||
}
|
||||
|
||||
this._activeTrigger[Trigger.CLICK] = false
|
||||
this._activeTrigger[Trigger.FOCUS] = false
|
||||
this._activeTrigger[Trigger.HOVER] = false
|
||||
|
||||
if (Util.supportsTransitionEnd() &&
|
||||
$(this.tip).hasClass(ClassName.FADE)) {
|
||||
this._isTransitioning = true
|
||||
|
||||
$(tip)
|
||||
.one(Util.TRANSITION_END, complete)
|
||||
.emulateTransitionEnd(TRANSITION_DURATION)
|
||||
@@ -374,8 +395,14 @@ const Tooltip = (($) => {
|
||||
}
|
||||
|
||||
this._hoverState = ''
|
||||
|
||||
}
|
||||
|
||||
update() {
|
||||
if (this._popper !== null) {
|
||||
this._popper.scheduleUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
// protected
|
||||
|
||||
@@ -383,18 +410,18 @@ const Tooltip = (($) => {
|
||||
return Boolean(this.getTitle())
|
||||
}
|
||||
|
||||
addAttachmentClass(attachment) {
|
||||
$(this.getTipElement()).addClass(`${CLASS_PREFIX}-${attachment}`)
|
||||
}
|
||||
|
||||
getTipElement() {
|
||||
return this.tip = this.tip || $(this.config.template)[0]
|
||||
}
|
||||
|
||||
setContent() {
|
||||
const $tip = $(this.getTipElement())
|
||||
|
||||
this.setElementContent($tip.find(Selector.TOOLTIP_INNER), this.getTitle())
|
||||
|
||||
$tip.removeClass(`${ClassName.FADE} ${ClassName.SHOW}`)
|
||||
|
||||
this.cleanupTether()
|
||||
}
|
||||
|
||||
setElementContent($element, content) {
|
||||
@@ -425,12 +452,6 @@ const Tooltip = (($) => {
|
||||
return title
|
||||
}
|
||||
|
||||
cleanupTether() {
|
||||
if (this._tether) {
|
||||
this._tether.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// private
|
||||
|
||||
@@ -603,6 +624,14 @@ const Tooltip = (($) => {
|
||||
}
|
||||
}
|
||||
|
||||
if (config.title && typeof config.title === 'number') {
|
||||
config.title = config.title.toString()
|
||||
}
|
||||
|
||||
if (config.content && typeof config.content === 'number') {
|
||||
config.content = config.content.toString()
|
||||
}
|
||||
|
||||
Util.typeCheckConfig(
|
||||
NAME,
|
||||
config,
|
||||
@@ -626,6 +655,31 @@ const Tooltip = (($) => {
|
||||
return config
|
||||
}
|
||||
|
||||
_cleanTipClass() {
|
||||
const $tip = $(this.getTipElement())
|
||||
const tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX)
|
||||
if (tabClass !== null && tabClass.length > 0) {
|
||||
$tip.removeClass(tabClass.join(''))
|
||||
}
|
||||
}
|
||||
|
||||
_handlePopperPlacementChange(data) {
|
||||
this._cleanTipClass()
|
||||
this.addAttachmentClass(this._getAttachment(data.placement))
|
||||
}
|
||||
|
||||
_fixTransition() {
|
||||
const tip = this.getTipElement()
|
||||
const initConfigAnimation = this.config.animation
|
||||
if (tip.getAttribute('x-placement') !== null) {
|
||||
return
|
||||
}
|
||||
$(tip).removeClass(ClassName.FADE)
|
||||
this.config.animation = false
|
||||
this.hide()
|
||||
this.show()
|
||||
this.config.animation = initConfigAnimation
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
|
||||
+8
-5
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v4.0.0-alpha.6): util.js
|
||||
* Bootstrap (v4.0.0-beta): util.js
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -112,13 +112,16 @@ const Util = (($) => {
|
||||
|
||||
getSelectorFromElement(element) {
|
||||
let selector = element.getAttribute('data-target')
|
||||
|
||||
if (!selector) {
|
||||
if (!selector || selector === '#') {
|
||||
selector = element.getAttribute('href') || ''
|
||||
selector = /^#[a-z]/i.test(selector) ? selector : null
|
||||
}
|
||||
|
||||
return selector
|
||||
try {
|
||||
const $selector = $(selector)
|
||||
return $selector.length > 0 ? selector : null
|
||||
} catch (error) {
|
||||
return null
|
||||
}
|
||||
},
|
||||
|
||||
reflow(element) {
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ Bootstrap uses [QUnit](https://qunitjs.com/), a powerful, easy-to-use JavaScript
|
||||
* `vendor/` contains third-party testing-related code (QUnit and jQuery).
|
||||
* `visual/` contains "visual" tests which are run interactively in real browsers and require manual verification by humans.
|
||||
|
||||
To run the unit test suite via [PhantomJS](http://phantomjs.org/), run `grunt test-js`.
|
||||
To run the unit test suite via [PhantomJS](http://phantomjs.org/), run `npm run js-test`.
|
||||
|
||||
To run the unit test suite via a real web browser, open `index.html` in the browser.
|
||||
|
||||
@@ -16,7 +16,7 @@ To run the unit test suite via a real web browser, open `index.html` in the brow
|
||||
1. Locate and open the file dedicated to the plugin which you need to add tests to (`unit/<plugin-name>.js`).
|
||||
2. Review the [QUnit API Documentation](https://api.qunitjs.com/) and use the existing tests as references for how to structure your new tests.
|
||||
3. Write the necessary unit test(s) for the new or revised functionality.
|
||||
4. Run `grunt test-js` to see the results of your newly-added test(s).
|
||||
4. Run `npm run js-test` to see the results of your newly-added test(s).
|
||||
|
||||
**Note:** Your new unit tests should fail before your changes are applied to the plugin, and should pass after your changes are applied to the plugin.
|
||||
|
||||
|
||||
+35
@@ -138,4 +138,39 @@ $(function () {
|
||||
assert.ok($btn2.find('input').prop('checked'), 'btn2 is checked')
|
||||
})
|
||||
|
||||
QUnit.test('should not add aria-pressed on labels for radio/checkbox inputs in a data-toggle="buttons" group', function (assert) {
|
||||
assert.expect(2)
|
||||
var groupHTML = '<div class="btn-group" data-toggle="buttons">'
|
||||
+ '<label class="btn btn-primary"><input type="checkbox" autocomplete="off"> Checkbox</label>'
|
||||
+ '<label class="btn btn-primary"><input type="radio" name="options" autocomplete="off"> Radio</label>'
|
||||
+ '</div>'
|
||||
var $group = $(groupHTML).appendTo('#qunit-fixture')
|
||||
|
||||
var $btn1 = $group.children().eq(0)
|
||||
var $btn2 = $group.children().eq(1)
|
||||
|
||||
$btn1.find('input').trigger('click')
|
||||
assert.ok($btn1.is(':not([aria-pressed])'), 'label for nested checkbox input has not been given an aria-pressed attribute')
|
||||
|
||||
$btn2.find('input').trigger('click')
|
||||
assert.ok($btn2.is(':not([aria-pressed])'), 'label for nested radio input has not been given an aria-pressed attribute')
|
||||
})
|
||||
|
||||
QUnit.test('should handle disabled attribute on non-button elements', function (assert) {
|
||||
assert.expect(2)
|
||||
var groupHTML = ' <div class="btn-group disabled" data-toggle="buttons" aria-disabled="true" disabled>'
|
||||
+ '<label class="btn btn-danger disabled" aria-disabled="true" disabled>'
|
||||
+ '<input type="checkbox" aria-disabled="true" autocomplete="off" disabled class="disabled"/>'
|
||||
+ '</label>'
|
||||
+ '</div>'
|
||||
var $group = $(groupHTML).appendTo('#qunit-fixture')
|
||||
|
||||
var $btn = $group.children().eq(0)
|
||||
var $input = $btn.children().eq(0)
|
||||
|
||||
$btn.trigger('click')
|
||||
assert.ok($btn.is(':not(.active)'), 'button did not become active')
|
||||
assert.ok(!$input.is(':checked'), 'checkbox did not get checked')
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
+43
-23
@@ -341,6 +341,49 @@ $(function () {
|
||||
.bootstrapCarousel('next')
|
||||
})
|
||||
|
||||
QUnit.test('should fire slid and slide events with from and to', function (assert) {
|
||||
assert.expect(4)
|
||||
var template = '<div id="myCarousel" class="carousel slide">'
|
||||
+ '<div class="carousel-inner">'
|
||||
+ '<div class="carousel-item active">'
|
||||
+ '<img alt="">'
|
||||
+ '<div class="carousel-caption">'
|
||||
+ '<h4>First Thumbnail label</h4>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '<div class="carousel-item">'
|
||||
+ '<img alt="">'
|
||||
+ '<div class="carousel-caption">'
|
||||
+ '<h4>Second Thumbnail label</h4>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '<div class="carousel-item">'
|
||||
+ '<img alt="">'
|
||||
+ '<div class="carousel-caption">'
|
||||
+ '<h4>Third Thumbnail label</h4>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '<a class="left carousel-control" href="#myCarousel" data-slide="prev">‹</a>'
|
||||
+ '<a class="right carousel-control" href="#myCarousel" data-slide="next">›</a>'
|
||||
+ '</div>'
|
||||
|
||||
var done = assert.async()
|
||||
$(template)
|
||||
.on('slid.bs.carousel', function (e) {
|
||||
assert.ok(e.from !== undefined, 'from present')
|
||||
assert.ok(e.to !== undefined, 'to present')
|
||||
$(this).off()
|
||||
done()
|
||||
})
|
||||
.on('slide.bs.carousel', function (e) {
|
||||
assert.ok(e.from !== undefined, 'from present')
|
||||
assert.ok(e.to !== undefined, 'to present')
|
||||
$(this).off('slide.bs.carousel')
|
||||
})
|
||||
.bootstrapCarousel('next')
|
||||
})
|
||||
|
||||
QUnit.test('should set interval from data attribute', function (assert) {
|
||||
assert.expect(4)
|
||||
var templateHTML = '<div id="myCarousel" class="carousel slide">'
|
||||
@@ -611,29 +654,6 @@ $(function () {
|
||||
assert.strictEqual($template.find('.carousel-item')[0], $template.find('.active')[0], 'first item still active after left arrow press in <textarea>')
|
||||
})
|
||||
|
||||
QUnit.test('should only add mouseenter and mouseleave listeners when not on mobile', function (assert) {
|
||||
assert.expect(2)
|
||||
var isMobile = 'ontouchstart' in document.documentElement
|
||||
var templateHTML = '<div id="myCarousel" class="carousel" data-interval="false" data-pause="hover">'
|
||||
+ '<div class="carousel-inner">'
|
||||
+ '<div id="first" class="carousel-item active">'
|
||||
+ '<img alt="">'
|
||||
+ '</div>'
|
||||
+ '<div id="second" class="carousel-item">'
|
||||
+ '<img alt="">'
|
||||
+ '</div>'
|
||||
+ '<div id="third" class="carousel-item">'
|
||||
+ '<img alt="">'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
var $template = $(templateHTML).bootstrapCarousel()
|
||||
|
||||
$.each(['mouseover', 'mouseout'], function (i, type) {
|
||||
assert.strictEqual(type in $._data($template[0], 'events'), !isMobile, 'does' + (isMobile ? ' not' : '') + ' listen for ' + type + ' events')
|
||||
})
|
||||
})
|
||||
|
||||
QUnit.test('should wrap around from end to start when wrap option is true', function (assert) {
|
||||
assert.expect(3)
|
||||
var carouselHTML = '<div id="carousel-example-generic" class="carousel slide" data-wrap="true">'
|
||||
|
||||
+219
-36
@@ -52,8 +52,28 @@ $(function () {
|
||||
assert.ok(!/height/i.test($el.attr('style')), 'has height reset')
|
||||
})
|
||||
|
||||
|
||||
QUnit.test('should show multiple collapsed elements', function (assert) {
|
||||
assert.expect(4)
|
||||
var done = assert.async()
|
||||
var $target = $('<a role="button" data-toggle="collapse" class="collapsed" href=".multi"/>').appendTo('#qunit-fixture')
|
||||
var $el = $('<div class="collapse multi"/>').appendTo('#qunit-fixture')
|
||||
var $el2 = $('<div class="collapse multi"/>').appendTo('#qunit-fixture')
|
||||
$el.one('shown.bs.collapse', function () {
|
||||
assert.ok($el.hasClass('show'), 'has class "show"')
|
||||
assert.ok(!/height/i.test($el.attr('style')), 'has height reset')
|
||||
})
|
||||
$el2.one('shown.bs.collapse', function () {
|
||||
assert.ok($el2.hasClass('show'), 'has class "show"')
|
||||
assert.ok(!/height/i.test($el2.attr('style')), 'has height reset')
|
||||
done()
|
||||
})
|
||||
$target.trigger('click')
|
||||
})
|
||||
|
||||
QUnit.test('should collapse only the first collapse', function (assert) {
|
||||
assert.expect(2)
|
||||
var done = assert.async()
|
||||
var html = [
|
||||
'<div class="panel-group" id="accordion1">',
|
||||
'<div class="panel">',
|
||||
@@ -69,10 +89,11 @@ $(function () {
|
||||
$(html).appendTo('#qunit-fixture')
|
||||
var $el1 = $('#collapse1')
|
||||
var $el2 = $('#collapse2')
|
||||
$el1.bootstrapCollapse('show')
|
||||
|
||||
assert.ok($el1.hasClass('show'))
|
||||
assert.ok($el2.hasClass('show'))
|
||||
$el1.one('shown.bs.collapse', function () {
|
||||
assert.ok($el1.hasClass('show'))
|
||||
assert.ok($el2.hasClass('show'))
|
||||
done()
|
||||
}).bootstrapCollapse('show')
|
||||
})
|
||||
|
||||
QUnit.test('should hide a collapsed element', function (assert) {
|
||||
@@ -265,17 +286,17 @@ $(function () {
|
||||
+ '</div>'
|
||||
var $groups = $(accordionHTML).appendTo('#qunit-fixture').find('.card')
|
||||
|
||||
var $target1 = $('<a role="button" data-toggle="collapse" href="#body1" data-parent="#accordion"/>').appendTo($groups.eq(0))
|
||||
var $target1 = $('<a role="button" data-toggle="collapse" href="#body1" />').appendTo($groups.eq(0))
|
||||
|
||||
$('<div id="body1" class="show"/>').appendTo($groups.eq(0))
|
||||
$('<div id="body1" class="show" data-parent="#accordion"/>').appendTo($groups.eq(0))
|
||||
|
||||
var $target2 = $('<a class="collapsed" data-toggle="collapse" role="button" href="#body2" data-parent="#accordion"/>').appendTo($groups.eq(1))
|
||||
var $target2 = $('<a class="collapsed" data-toggle="collapse" role="button" href="#body2" />').appendTo($groups.eq(1))
|
||||
|
||||
$('<div id="body2"/>').appendTo($groups.eq(1))
|
||||
$('<div id="body2" data-parent="#accordion"/>').appendTo($groups.eq(1))
|
||||
|
||||
var $target3 = $('<a class="collapsed" data-toggle="collapse" role="button" href="#body3" data-parent="#accordion"/>').appendTo($groups.eq(2))
|
||||
var $target3 = $('<a class="collapsed" data-toggle="collapse" role="button" href="#body3" />').appendTo($groups.eq(2))
|
||||
|
||||
$('<div id="body3"/>')
|
||||
$('<div id="body3" data-parent="#accordion"/>')
|
||||
.appendTo($groups.eq(2))
|
||||
.on('shown.bs.collapse', function () {
|
||||
assert.ok($target1.hasClass('collapsed'), 'inactive target 1 does have class "collapsed"')
|
||||
@@ -299,17 +320,17 @@ $(function () {
|
||||
+ '</div>'
|
||||
var $groups = $(accordionHTML).appendTo('#qunit-fixture').find('.card')
|
||||
|
||||
var $target1 = $('<a role="button" data-toggle="collapse" href="#body1" data-parent=".accordion"/>').appendTo($groups.eq(0))
|
||||
var $target1 = $('<a role="button" data-toggle="collapse" href="#body1"/>').appendTo($groups.eq(0))
|
||||
|
||||
$('<div id="body1" class="show"/>').appendTo($groups.eq(0))
|
||||
$('<div id="body1" class="show" data-parent=".accordion"/>').appendTo($groups.eq(0))
|
||||
|
||||
var $target2 = $('<a class="collapsed" data-toggle="collapse" role="button" href="#body2" data-parent=".accordion"/>').appendTo($groups.eq(1))
|
||||
var $target2 = $('<a class="collapsed" data-toggle="collapse" role="button" href="#body2"/>').appendTo($groups.eq(1))
|
||||
|
||||
$('<div id="body2"/>').appendTo($groups.eq(1))
|
||||
$('<div id="body2" data-parent=".accordion"/>').appendTo($groups.eq(1))
|
||||
|
||||
var $target3 = $('<a class="collapsed" data-toggle="collapse" role="button" href="#body3" data-parent=".accordion"/>').appendTo($groups.eq(2))
|
||||
var $target3 = $('<a class="collapsed" data-toggle="collapse" role="button" href="#body3"/>').appendTo($groups.eq(2))
|
||||
|
||||
$('<div id="body3"/>')
|
||||
$('<div id="body3" data-parent=".accordion"/>')
|
||||
.appendTo($groups.eq(2))
|
||||
.on('shown.bs.collapse', function () {
|
||||
assert.ok($target1.hasClass('collapsed'), 'inactive target 1 does have class "collapsed"')
|
||||
@@ -322,7 +343,7 @@ $(function () {
|
||||
$target3.trigger('click')
|
||||
})
|
||||
|
||||
QUnit.test('should set aria-expanded="true" on target when collapse is shown', function (assert) {
|
||||
QUnit.test('should set aria-expanded="true" on trigger/control when collapse is shown', function (assert) {
|
||||
assert.expect(1)
|
||||
var done = assert.async()
|
||||
|
||||
@@ -338,7 +359,7 @@ $(function () {
|
||||
$target.trigger('click')
|
||||
})
|
||||
|
||||
QUnit.test('should set aria-expanded="false" on target when collapse is hidden', function (assert) {
|
||||
QUnit.test('should set aria-expanded="false" on trigger/control when collapse is hidden', function (assert) {
|
||||
assert.expect(1)
|
||||
var done = assert.async()
|
||||
|
||||
@@ -364,8 +385,8 @@ $(function () {
|
||||
$('<div id="test1"/>')
|
||||
.appendTo('#qunit-fixture')
|
||||
.on('shown.bs.collapse', function () {
|
||||
assert.strictEqual($target.attr('aria-expanded'), 'true', 'aria-expanded on target is "true"')
|
||||
assert.strictEqual($alt.attr('aria-expanded'), 'true', 'aria-expanded on alt is "true"')
|
||||
assert.strictEqual($target.attr('aria-expanded'), 'true', 'aria-expanded on trigger/control is "true"')
|
||||
assert.strictEqual($alt.attr('aria-expanded'), 'true', 'aria-expanded on alternative trigger/control is "true"')
|
||||
done()
|
||||
})
|
||||
|
||||
@@ -382,15 +403,15 @@ $(function () {
|
||||
$('<div id="test1" class="show"/>')
|
||||
.appendTo('#qunit-fixture')
|
||||
.on('hidden.bs.collapse', function () {
|
||||
assert.strictEqual($target.attr('aria-expanded'), 'false', 'aria-expanded on target is "false"')
|
||||
assert.strictEqual($alt.attr('aria-expanded'), 'false', 'aria-expanded on alt is "false"')
|
||||
assert.strictEqual($target.attr('aria-expanded'), 'false', 'aria-expanded on trigger/control is "false"')
|
||||
assert.strictEqual($alt.attr('aria-expanded'), 'false', 'aria-expanded on alternative trigger/control is "false"')
|
||||
done()
|
||||
})
|
||||
|
||||
$target.trigger('click')
|
||||
})
|
||||
|
||||
QUnit.test('should change aria-expanded from active accordion target to "false" and set the newly active one to "true"', function (assert) {
|
||||
QUnit.test('should change aria-expanded from active accordion trigger/control to "false" and set the trigger/control for the newly active one to "true"', function (assert) {
|
||||
assert.expect(3)
|
||||
var done = assert.async()
|
||||
|
||||
@@ -401,22 +422,22 @@ $(function () {
|
||||
+ '</div>'
|
||||
var $groups = $(accordionHTML).appendTo('#qunit-fixture').find('.card')
|
||||
|
||||
var $target1 = $('<a role="button" data-toggle="collapse" href="#body1" data-parent="#accordion"/>').appendTo($groups.eq(0))
|
||||
var $target1 = $('<a role="button" data-toggle="collapse" aria-expanded="true" href="#body1"/>').appendTo($groups.eq(0))
|
||||
|
||||
$('<div id="body1" aria-expanded="true" class="show"/>').appendTo($groups.eq(0))
|
||||
$('<div id="body1" class="show" data-parent="#accordion"/>').appendTo($groups.eq(0))
|
||||
|
||||
var $target2 = $('<a role="button" data-toggle="collapse" href="#body2" data-parent="#accordion" class="collapsed" />').appendTo($groups.eq(1))
|
||||
var $target2 = $('<a role="button" data-toggle="collapse" aria-expanded="false" href="#body2" class="collapsed" aria-expanded="false" />').appendTo($groups.eq(1))
|
||||
|
||||
$('<div id="body2" aria-expanded="false"/>').appendTo($groups.eq(1))
|
||||
$('<div id="body2" data-parent="#accordion"/>').appendTo($groups.eq(1))
|
||||
|
||||
var $target3 = $('<a class="collapsed" data-toggle="collapse" role="button" href="#body3" data-parent="#accordion"/>').appendTo($groups.eq(2))
|
||||
var $target3 = $('<a class="collapsed" data-toggle="collapse" aria-expanded="false" role="button" href="#body3"/>').appendTo($groups.eq(2))
|
||||
|
||||
$('<div id="body3" aria-expanded="false"/>')
|
||||
$('<div id="body3" data-parent="#accordion"/>')
|
||||
.appendTo($groups.eq(2))
|
||||
.on('shown.bs.collapse', function () {
|
||||
assert.strictEqual($target1.attr('aria-expanded'), 'false', 'inactive target 1 has aria-expanded="false"')
|
||||
assert.strictEqual($target2.attr('aria-expanded'), 'false', 'inactive target 2 has aria-expanded="false"')
|
||||
assert.strictEqual($target3.attr('aria-expanded'), 'true', 'active target 3 has aria-expanded="false"')
|
||||
assert.strictEqual($target1.attr('aria-expanded'), 'false', 'inactive trigger/control 1 has aria-expanded="false"')
|
||||
assert.strictEqual($target2.attr('aria-expanded'), 'false', 'inactive trigger/control 2 has aria-expanded="false"')
|
||||
assert.strictEqual($target3.attr('aria-expanded'), 'true', 'active trigger/control 3 has aria-expanded="true"')
|
||||
|
||||
done()
|
||||
})
|
||||
@@ -435,16 +456,16 @@ $(function () {
|
||||
var showFired = false
|
||||
var $groups = $(accordionHTML).appendTo('#qunit-fixture').find('.card')
|
||||
|
||||
var $target1 = $('<a role="button" data-toggle="collapse" href="#body1" data-parent="#accordion"/>').appendTo($groups.eq(0))
|
||||
var $target1 = $('<a role="button" data-toggle="collapse" href="#body1"/>').appendTo($groups.eq(0))
|
||||
|
||||
$('<div id="body1" class="collapse"/>')
|
||||
$('<div id="body1" class="collapse" data-parent="#accordion"/>')
|
||||
.appendTo($groups.eq(0))
|
||||
.on('show.bs.collapse', function () {
|
||||
showFired = true
|
||||
})
|
||||
|
||||
var $target2 = $('<a role="button" data-toggle="collapse" href="#body2" data-parent="#accordion"/>').appendTo($groups.eq(1))
|
||||
var $body2 = $('<div id="body2" class="collapse"/>').appendTo($groups.eq(1))
|
||||
var $target2 = $('<a role="button" data-toggle="collapse" href="#body2"/>').appendTo($groups.eq(1))
|
||||
var $body2 = $('<div id="body2" class="collapse" data-parent="#accordion"/>').appendTo($groups.eq(1))
|
||||
|
||||
$target2.trigger('click')
|
||||
|
||||
@@ -490,4 +511,166 @@ $(function () {
|
||||
.bootstrapCollapse('show')
|
||||
})
|
||||
|
||||
QUnit.test('should allow accordion to use children other than card', function (assert) {
|
||||
assert.expect(4)
|
||||
var done = assert.async()
|
||||
var accordionHTML = '<div id="accordion">'
|
||||
+ '<div class="item">'
|
||||
+ '<a id="linkTrigger" data-parent="#accordion" data-toggle="collapse" href="#collapseOne" aria-expanded="false" aria-controls="collapseOne"></a>'
|
||||
+ '<div id="collapseOne" class="collapse" role="tabpanel" aria-labelledby="headingThree"></div>'
|
||||
+ '</div>'
|
||||
+ '<div class="item">'
|
||||
+ '<a id="linkTriggerTwo" data-toggle="collapse" data-parent="#accordion" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"></a>'
|
||||
+ '<div id="collapseTwo" class="collapse show" role="tabpanel" aria-labelledby="headingTwo"></div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
|
||||
$(accordionHTML).appendTo('#qunit-fixture')
|
||||
var $trigger = $('#linkTrigger')
|
||||
var $triggerTwo = $('#linkTriggerTwo')
|
||||
var $collapseOne = $('#collapseOne')
|
||||
var $collapseTwo = $('#collapseTwo')
|
||||
$collapseOne.on('shown.bs.collapse', function () {
|
||||
assert.ok($collapseOne.hasClass('show'), '#collapseOne is shown')
|
||||
assert.ok(!$collapseTwo.hasClass('show'), '#collapseTwo is not shown')
|
||||
$collapseTwo.on('shown.bs.collapse', function () {
|
||||
assert.ok(!$collapseOne.hasClass('show'), '#collapseOne is not shown')
|
||||
assert.ok($collapseTwo.hasClass('show'), '#collapseTwo is shown')
|
||||
done()
|
||||
})
|
||||
$triggerTwo.trigger($.Event('click'))
|
||||
})
|
||||
$trigger.trigger($.Event('click'))
|
||||
})
|
||||
|
||||
QUnit.test('should collapse accordion children but not nested accordion children', function (assert) {
|
||||
assert.expect(9)
|
||||
var done = assert.async()
|
||||
$('<div id="accordion">'
|
||||
+ '<div class="item">'
|
||||
+ '<a id="linkTrigger" data-parent="#accordion" data-toggle="collapse" href="#collapseOne" aria-expanded="false" aria-controls="collapseOne"></a>'
|
||||
+ '<div id="collapseOne" class="collapse" role="tabpanel" aria-labelledby="headingThree">'
|
||||
+ '<div id="nestedAccordion">'
|
||||
+ '<div class="item">'
|
||||
+ '<a id="nestedLinkTrigger" data-parent="#nestedAccordion" data-toggle="collapse" href="#nestedCollapseOne" aria-expanded="false" aria-controls="nestedCollapseOne"></a>'
|
||||
+ '<div id="nestedCollapseOne" class="collapse" role="tabpanel" aria-labelledby="headingThree">'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '<div class="item">'
|
||||
+ '<a id="linkTriggerTwo" data-toggle="collapse" data-parent="#accordion" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"></a>'
|
||||
+ '<div id="collapseTwo" class="collapse show" role="tabpanel" aria-labelledby="headingTwo"></div>'
|
||||
+ '</div>'
|
||||
+ '</div>').appendTo('#qunit-fixture')
|
||||
var $trigger = $('#linkTrigger')
|
||||
var $triggerTwo = $('#linkTriggerTwo')
|
||||
var $nestedTrigger = $('#nestedLinkTrigger')
|
||||
var $collapseOne = $('#collapseOne')
|
||||
var $collapseTwo = $('#collapseTwo')
|
||||
var $nestedCollapseOne = $('#nestedCollapseOne')
|
||||
|
||||
|
||||
$collapseOne.one('shown.bs.collapse', function () {
|
||||
assert.ok($collapseOne.hasClass('show'), '#collapseOne is shown')
|
||||
assert.ok(!$collapseTwo.hasClass('show'), '#collapseTwo is not shown')
|
||||
assert.ok(!$('#nestedCollapseOne').hasClass('show'), '#nestedCollapseOne is not shown')
|
||||
$nestedCollapseOne.one('shown.bs.collapse', function () {
|
||||
assert.ok($collapseOne.hasClass('show'), '#collapseOne is shown')
|
||||
assert.ok(!$collapseTwo.hasClass('show'), '#collapseTwo is not shown')
|
||||
assert.ok($nestedCollapseOne.hasClass('show'), '#nestedCollapseOne is shown')
|
||||
$collapseTwo.one('shown.bs.collapse', function () {
|
||||
assert.ok(!$collapseOne.hasClass('show'), '#collapseOne is not shown')
|
||||
assert.ok($collapseTwo.hasClass('show'), '#collapseTwo is shown')
|
||||
assert.ok($nestedCollapseOne.hasClass('show'), '#nestedCollapseOne is shown')
|
||||
done()
|
||||
})
|
||||
$triggerTwo.trigger($.Event('click'))
|
||||
})
|
||||
$nestedTrigger.trigger($.Event('click'))
|
||||
})
|
||||
$trigger.trigger($.Event('click'))
|
||||
})
|
||||
|
||||
QUnit.test('should not prevent event for input', function (assert) {
|
||||
assert.expect(3)
|
||||
var done = assert.async()
|
||||
var $target = $('<input type="checkbox" data-toggle="collapse" data-target="#collapsediv1" />').appendTo('#qunit-fixture')
|
||||
|
||||
$('<div id="collapsediv1"/>')
|
||||
.appendTo('#qunit-fixture')
|
||||
.on('shown.bs.collapse', function () {
|
||||
assert.ok($(this).hasClass('show'))
|
||||
assert.ok($target.attr('aria-expanded') === 'true')
|
||||
assert.ok($target.prop('checked'))
|
||||
done()
|
||||
})
|
||||
|
||||
$target.trigger($.Event('click'))
|
||||
})
|
||||
|
||||
QUnit.test('should add "collapsed" class to triggers only when all the targeted collapse are hidden', function (assert) {
|
||||
assert.expect(9)
|
||||
var done = assert.async()
|
||||
|
||||
var $trigger1 = $('<a role="button" data-toggle="collapse" href="#test1"/>').appendTo('#qunit-fixture')
|
||||
var $trigger2 = $('<a role="button" data-toggle="collapse" href="#test2"/>').appendTo('#qunit-fixture')
|
||||
var $trigger3 = $('<a role="button" data-toggle="collapse" href=".multi"/>').appendTo('#qunit-fixture')
|
||||
|
||||
var $target1 = $('<div id="test1" class="multi"/>').appendTo('#qunit-fixture')
|
||||
var $target2 = $('<div id="test2" class="multi"/>').appendTo('#qunit-fixture')
|
||||
|
||||
$target2.one('shown.bs.collapse', function () {
|
||||
assert.ok(!$trigger1.hasClass('collapsed'), 'trigger1 does not have collapsed class')
|
||||
assert.ok(!$trigger2.hasClass('collapsed'), 'trigger2 does not have collapsed class')
|
||||
assert.ok(!$trigger3.hasClass('collapsed'), 'trigger3 does not have collapsed class')
|
||||
$target2.one('hidden.bs.collapse', function () {
|
||||
assert.ok(!$trigger1.hasClass('collapsed'), 'trigger1 does not have collapsed class')
|
||||
assert.ok($trigger2.hasClass('collapsed'), 'trigger2 has collapsed class')
|
||||
assert.ok(!$trigger3.hasClass('collapsed'), 'trigger3 does not have collapsed class')
|
||||
$target1.one('hidden.bs.collapse', function () {
|
||||
assert.ok($trigger1.hasClass('collapsed'), 'trigger1 has collapsed class')
|
||||
assert.ok($trigger2.hasClass('collapsed'), 'trigger2 has collapsed class')
|
||||
assert.ok($trigger3.hasClass('collapsed'), 'trigger3 has collapsed class')
|
||||
done()
|
||||
})
|
||||
$trigger1.trigger('click')
|
||||
})
|
||||
$trigger2.trigger('click')
|
||||
})
|
||||
$trigger3.trigger('click')
|
||||
})
|
||||
|
||||
QUnit.test('should set aria-expanded="true" to triggers targetting shown collaspe and aria-expanded="false" only when all the targeted collapses are shown', function (assert) {
|
||||
assert.expect(9)
|
||||
var done = assert.async()
|
||||
|
||||
var $trigger1 = $('<a role="button" data-toggle="collapse" href="#test1"/>').appendTo('#qunit-fixture')
|
||||
var $trigger2 = $('<a role="button" data-toggle="collapse" href="#test2"/>').appendTo('#qunit-fixture')
|
||||
var $trigger3 = $('<a role="button" data-toggle="collapse" href=".multi"/>').appendTo('#qunit-fixture')
|
||||
|
||||
var $target1 = $('<div id="test1" class="multi collapse"/>').appendTo('#qunit-fixture')
|
||||
var $target2 = $('<div id="test2" class="multi collapse"/>').appendTo('#qunit-fixture')
|
||||
|
||||
$target2.one('shown.bs.collapse', function () {
|
||||
assert.strictEqual($trigger1.attr('aria-expanded'), 'true', 'aria-expanded on trigger1 is "true"')
|
||||
assert.strictEqual($trigger2.attr('aria-expanded'), 'true', 'aria-expanded on trigger2 is "true"')
|
||||
assert.strictEqual($trigger3.attr('aria-expanded'), 'true', 'aria-expanded on trigger3 is "true"')
|
||||
$target2.one('hidden.bs.collapse', function () {
|
||||
assert.strictEqual($trigger1.attr('aria-expanded'), 'true', 'aria-expanded on trigger1 is "true"')
|
||||
assert.strictEqual($trigger2.attr('aria-expanded'), 'false', 'aria-expanded on trigger2 is "false"')
|
||||
assert.strictEqual($trigger3.attr('aria-expanded'), 'true', 'aria-expanded on trigger3 is "true"')
|
||||
$target1.one('hidden.bs.collapse', function () {
|
||||
assert.strictEqual($trigger1.attr('aria-expanded'), 'false', 'aria-expanded on trigger1 is "fasle"')
|
||||
assert.strictEqual($trigger2.attr('aria-expanded'), 'false', 'aria-expanded on trigger2 is "false"')
|
||||
assert.strictEqual($trigger3.attr('aria-expanded'), 'false', 'aria-expanded on trigger3 is "false"')
|
||||
done()
|
||||
})
|
||||
$trigger1.trigger('click')
|
||||
})
|
||||
$trigger2.trigger('click')
|
||||
})
|
||||
$trigger3.trigger('click')
|
||||
})
|
||||
})
|
||||
|
||||
+357
-200
@@ -46,57 +46,68 @@ $(function () {
|
||||
|
||||
QUnit.test('should not open dropdown if target is disabled via attribute', function (assert) {
|
||||
assert.expect(1)
|
||||
var dropdownHTML = '<ul class="tabs">'
|
||||
+ '<li class="dropdown">'
|
||||
var done = assert.async()
|
||||
var dropdownHTML = '<div class="tabs">'
|
||||
+ '<div class="dropdown">'
|
||||
+ '<button disabled href="#" class="btn dropdown-toggle" data-toggle="dropdown">Dropdown</button>'
|
||||
+ '<ul class="dropdown-menu">'
|
||||
+ '<li><a href="#">Secondary link</a></li>'
|
||||
+ '<li><a href="#">Something else here</a></li>'
|
||||
+ '<li class="divider"/>'
|
||||
+ '<li><a href="#">Another link</a></li>'
|
||||
+ '</ul>'
|
||||
+ '</li>'
|
||||
+ '</ul>'
|
||||
var $dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown().trigger('click')
|
||||
|
||||
assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click')
|
||||
+ '<div class="dropdown-menu">'
|
||||
+ '<a class="dropdown-item" href="#">Secondary link</a>'
|
||||
+ '<a class="dropdown-item" href="#">Something else here</a>'
|
||||
+ '<div class="divider"/>'
|
||||
+ '<a class="dropdown-item" href="#">Another link</a>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
$(dropdownHTML).appendTo('#qunit-fixture')
|
||||
var $dropdown = $('#qunit-fixture').find('[data-toggle="dropdown"]').bootstrapDropdown()
|
||||
$dropdown.on('click', function () {
|
||||
assert.ok(!$dropdown.parent('.dropdown').hasClass('show'))
|
||||
done()
|
||||
})
|
||||
$dropdown.trigger($.Event('click'))
|
||||
})
|
||||
|
||||
QUnit.test('should set aria-expanded="true" on target when dropdown menu is shown', function (assert) {
|
||||
assert.expect(1)
|
||||
var dropdownHTML = '<ul class="tabs">'
|
||||
+ '<li class="dropdown">'
|
||||
var done = assert.async()
|
||||
var dropdownHTML = '<div class="tabs">'
|
||||
+ '<div class="dropdown">'
|
||||
+ '<a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false">Dropdown</a>'
|
||||
+ '<ul class="dropdown-menu">'
|
||||
+ '<li><a href="#">Secondary link</a></li>'
|
||||
+ '<li><a href="#">Something else here</a></li>'
|
||||
+ '<li class="divider"/>'
|
||||
+ '<li><a href="#">Another link</a></li>'
|
||||
+ '</ul>'
|
||||
+ '</li>'
|
||||
+ '</ul>'
|
||||
+ '<div class="dropdown-menu">'
|
||||
+ '<a class="dropdown-item" href="#">Secondary link</a>'
|
||||
+ '<a class="dropdown-item" href="#">Something else here</a>'
|
||||
+ '<div class="divider"/>'
|
||||
+ '<a class="dropdown-item" href="#">Another link</a>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
var $dropdown = $(dropdownHTML)
|
||||
.find('[data-toggle="dropdown"]')
|
||||
.bootstrapDropdown()
|
||||
.trigger('click')
|
||||
|
||||
assert.strictEqual($dropdown.attr('aria-expanded'), 'true', 'aria-expanded is set to string "true" on click')
|
||||
.appendTo('#qunit-fixture')
|
||||
.find('[data-toggle="dropdown"]')
|
||||
.bootstrapDropdown()
|
||||
$dropdown
|
||||
.parent('.dropdown')
|
||||
.on('shown.bs.dropdown', function () {
|
||||
assert.strictEqual($dropdown.attr('aria-expanded'), 'true', 'aria-expanded is set to string "true" on click')
|
||||
done()
|
||||
})
|
||||
$dropdown.trigger('click')
|
||||
})
|
||||
|
||||
QUnit.test('should set aria-expanded="false" on target when dropdown menu is hidden', function (assert) {
|
||||
assert.expect(1)
|
||||
var done = assert.async()
|
||||
var dropdownHTML = '<ul class="tabs">'
|
||||
+ '<li class="dropdown">'
|
||||
var dropdownHTML = '<div class="tabs">'
|
||||
+ '<div class="dropdown">'
|
||||
+ '<a href="#" class="dropdown-toggle" aria-expanded="false" data-toggle="dropdown">Dropdown</a>'
|
||||
+ '<ul class="dropdown-menu">'
|
||||
+ '<li><a href="#">Secondary link</a></li>'
|
||||
+ '<li><a href="#">Something else here</a></li>'
|
||||
+ '<li class="divider"/>'
|
||||
+ '<li><a href="#">Another link</a></li>'
|
||||
+ '</ul>'
|
||||
+ '</li>'
|
||||
+ '</ul>'
|
||||
+ '<div class="dropdown-menu">'
|
||||
+ '<a class="dropdown-item" href="#">Secondary link</a>'
|
||||
+ '<a class="dropdown-item" href="#">Something else here</a>'
|
||||
+ '<div class="divider"/>'
|
||||
+ '<a class="dropdown-item" href="#">Another link</a>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
var $dropdown = $(dropdownHTML)
|
||||
.appendTo('#qunit-fixture')
|
||||
.find('[data-toggle="dropdown"]')
|
||||
@@ -115,85 +126,111 @@ $(function () {
|
||||
|
||||
QUnit.test('should not open dropdown if target is disabled via class', function (assert) {
|
||||
assert.expect(1)
|
||||
var dropdownHTML = '<ul class="tabs">'
|
||||
+ '<li class="dropdown">'
|
||||
var done = assert.async()
|
||||
var dropdownHTML = '<div class="tabs">'
|
||||
+ '<div class="dropdown">'
|
||||
+ '<button href="#" class="btn dropdown-toggle disabled" data-toggle="dropdown">Dropdown</button>'
|
||||
+ '<ul class="dropdown-menu">'
|
||||
+ '<li><a href="#">Secondary link</a></li>'
|
||||
+ '<li><a href="#">Something else here</a></li>'
|
||||
+ '<li class="divider"/>'
|
||||
+ '<li><a href="#">Another link</a></li>'
|
||||
+ '</ul>'
|
||||
+ '</li>'
|
||||
+ '</ul>'
|
||||
var $dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown().trigger('click')
|
||||
+ '<div class="dropdown-menu">'
|
||||
+ '<a class="dropdown-item" href="#">Secondary link</a>'
|
||||
+ '<a class="dropdown-item" href="#">Something else here</a>'
|
||||
+ '<div class="divider"/>'
|
||||
+ '<a class="dropdown-item" href="#">Another link</a>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
|
||||
assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click')
|
||||
$(dropdownHTML).appendTo('#qunit-fixture')
|
||||
var $dropdown = $('#qunit-fixture').find('[data-toggle="dropdown"]').bootstrapDropdown()
|
||||
$dropdown.on('click', function () {
|
||||
assert.ok(!$dropdown.parent('.dropdown').hasClass('show'))
|
||||
done()
|
||||
})
|
||||
$dropdown.trigger($.Event('click'))
|
||||
})
|
||||
|
||||
QUnit.test('should add class show to menu if clicked', function (assert) {
|
||||
assert.expect(1)
|
||||
var dropdownHTML = '<ul class="tabs">'
|
||||
+ '<li class="dropdown">'
|
||||
var done = assert.async()
|
||||
var dropdownHTML = '<div class="tabs">'
|
||||
+ '<div class="dropdown">'
|
||||
+ '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>'
|
||||
+ '<ul class="dropdown-menu">'
|
||||
+ '<li><a href="#">Secondary link</a></li>'
|
||||
+ '<li><a href="#">Something else here</a></li>'
|
||||
+ '<li class="divider"/>'
|
||||
+ '<li><a href="#">Another link</a></li>'
|
||||
+ '</ul>'
|
||||
+ '</li>'
|
||||
+ '</ul>'
|
||||
var $dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown().trigger('click')
|
||||
|
||||
assert.ok($dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click')
|
||||
+ '<div class="dropdown-menu">'
|
||||
+ '<a class="dropdown-item" href="#">Secondary link</a>'
|
||||
+ '<a class="dropdown-item" href="#">Something else here</a>'
|
||||
+ '<div class="divider"/>'
|
||||
+ '<a class="dropdown-item" href="#">Another link</a>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
var $dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown()
|
||||
$dropdown
|
||||
.parent('.dropdown')
|
||||
.on('shown.bs.dropdown', function () {
|
||||
assert.ok($dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click')
|
||||
done()
|
||||
})
|
||||
$dropdown.trigger('click')
|
||||
})
|
||||
|
||||
QUnit.test('should test if element has a # before assuming it\'s a selector', function (assert) {
|
||||
assert.expect(1)
|
||||
var dropdownHTML = '<ul class="tabs">'
|
||||
+ '<li class="dropdown">'
|
||||
var done = assert.async()
|
||||
var dropdownHTML = '<div class="tabs">'
|
||||
+ '<div class="dropdown">'
|
||||
+ '<a href="/foo/" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>'
|
||||
+ '<ul class="dropdown-menu">'
|
||||
+ '<li><a href="#">Secondary link</a></li>'
|
||||
+ '<li><a href="#">Something else here</a></li>'
|
||||
+ '<li class="divider"/>'
|
||||
+ '<li><a href="#">Another link</a></li>'
|
||||
+ '</ul>'
|
||||
+ '</li>'
|
||||
+ '</ul>'
|
||||
var $dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown().trigger('click')
|
||||
|
||||
assert.ok($dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click')
|
||||
+ '<div class="dropdown-menu">'
|
||||
+ '<a class="dropdown-item" href="#">Secondary link</a>'
|
||||
+ '<a class="dropdown-item" href="#">Something else here</a>'
|
||||
+ '<div class="divider"/>'
|
||||
+ '<a class="dropdown-item" href="#">Another link</a>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
var $dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown()
|
||||
$dropdown
|
||||
.parent('.dropdown')
|
||||
.on('shown.bs.dropdown', function () {
|
||||
assert.ok($dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click')
|
||||
done()
|
||||
})
|
||||
$dropdown.trigger('click')
|
||||
})
|
||||
|
||||
|
||||
QUnit.test('should remove "show" class if body is clicked', function (assert) {
|
||||
assert.expect(2)
|
||||
var dropdownHTML = '<ul class="tabs">'
|
||||
+ '<li class="dropdown">'
|
||||
var done = assert.async()
|
||||
var dropdownHTML = '<div class="tabs">'
|
||||
+ '<div class="dropdown">'
|
||||
+ '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>'
|
||||
+ '<ul class="dropdown-menu">'
|
||||
+ '<li><a href="#">Secondary link</a></li>'
|
||||
+ '<li><a href="#">Something else here</a></li>'
|
||||
+ '<li class="divider"/>'
|
||||
+ '<li><a href="#">Another link</a></li>'
|
||||
+ '</ul>'
|
||||
+ '</li>'
|
||||
+ '</ul>'
|
||||
+ '<div class="dropdown-menu">'
|
||||
+ '<a class="dropdown-item" href="#">Secondary link</a>'
|
||||
+ '<a class="dropdown-item" href="#">Something else here</a>'
|
||||
+ '<div class="divider"/>'
|
||||
+ '<a class="dropdown-item" href="#">Another link</a>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
var $dropdown = $(dropdownHTML)
|
||||
.appendTo('#qunit-fixture')
|
||||
.find('[data-toggle="dropdown"]')
|
||||
.bootstrapDropdown()
|
||||
.trigger('click')
|
||||
|
||||
assert.ok($dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click')
|
||||
$(document.body).trigger('click')
|
||||
assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), '"show" class removed')
|
||||
$dropdown
|
||||
.parent('.dropdown')
|
||||
.on('shown.bs.dropdown', function () {
|
||||
assert.ok($dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click')
|
||||
$(document.body).trigger('click')
|
||||
}).on('hidden.bs.dropdown', function () {
|
||||
assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), '"show" class removed')
|
||||
done()
|
||||
})
|
||||
$dropdown.trigger('click')
|
||||
})
|
||||
|
||||
QUnit.test('should remove "show" class if body is focused', function (assert) {
|
||||
QUnit.test('should remove "show" class if tabbing outside of menu', function (assert) {
|
||||
assert.expect(2)
|
||||
var done = assert.async()
|
||||
var dropdownHTML = '<div class="tabs">'
|
||||
+ '<div class="dropdown">'
|
||||
+ '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>'
|
||||
@@ -209,30 +246,37 @@ $(function () {
|
||||
.appendTo('#qunit-fixture')
|
||||
.find('[data-toggle="dropdown"]')
|
||||
.bootstrapDropdown()
|
||||
.trigger('click')
|
||||
|
||||
assert.ok($dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click')
|
||||
$(document.body).trigger('focusin')
|
||||
assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), '"show" class removed')
|
||||
$dropdown
|
||||
.parent('.dropdown')
|
||||
.on('shown.bs.dropdown', function () {
|
||||
assert.ok($dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click')
|
||||
var e = $.Event('keyup')
|
||||
e.which = 9 // Tab
|
||||
$(document.body).trigger(e)
|
||||
}).on('hidden.bs.dropdown', function () {
|
||||
assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), '"show" class removed')
|
||||
done()
|
||||
})
|
||||
$dropdown.trigger('click')
|
||||
})
|
||||
|
||||
QUnit.test('should remove "show" class if body is clicked, with multiple dropdowns', function (assert) {
|
||||
assert.expect(7)
|
||||
var dropdownHTML = '<ul class="nav">'
|
||||
+ '<li><a href="#menu1">Menu 1</a></li>'
|
||||
+ '<li class="dropdown" id="testmenu">'
|
||||
var done = assert.async()
|
||||
var dropdownHTML = '<div class="nav">'
|
||||
+ '<div class="dropdown" id="testmenu">'
|
||||
+ '<a class="dropdown-toggle" data-toggle="dropdown" href="#testmenu">Test menu <span class="caret"/></a>'
|
||||
+ '<ul class="dropdown-menu">'
|
||||
+ '<li><a href="#sub1">Submenu 1</a></li>'
|
||||
+ '</ul>'
|
||||
+ '</li>'
|
||||
+ '</ul>'
|
||||
+ '<div class="dropdown-menu">'
|
||||
+ '<a class="dropdown-item" href="#sub1">Submenu 1</a>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '<div class="btn-group">'
|
||||
+ '<button class="btn">Actions</button>'
|
||||
+ '<button class="btn dropdown-toggle" data-toggle="dropdown"><span class="caret"/></button>'
|
||||
+ '<ul class="dropdown-menu">'
|
||||
+ '<li><a href="#">Action 1</a></li>'
|
||||
+ '</ul>'
|
||||
+ '<button class="btn dropdown-toggle" data-toggle="dropdown"></button>'
|
||||
+ '<div class="dropdown-menu">'
|
||||
+ '<a class="dropdown-item" href="#">Action 1</a>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
var $dropdowns = $(dropdownHTML).appendTo('#qunit-fixture').find('[data-toggle="dropdown"]')
|
||||
var $first = $dropdowns.first()
|
||||
@@ -240,21 +284,31 @@ $(function () {
|
||||
|
||||
assert.strictEqual($dropdowns.length, 2, 'two dropdowns')
|
||||
|
||||
$first.trigger('click')
|
||||
assert.strictEqual($first.parents('.show').length, 1, '"show" class added on click')
|
||||
assert.strictEqual($('#qunit-fixture .show').length, 1, 'only one dropdown is shown')
|
||||
$(document.body).trigger('click')
|
||||
assert.strictEqual($('#qunit-fixture .show').length, 0, '"show" class removed')
|
||||
$first.parent('.dropdown')
|
||||
.on('shown.bs.dropdown', function () {
|
||||
assert.strictEqual($first.parents('.show').length, 1, '"show" class added on click')
|
||||
assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 1, 'only one dropdown is shown')
|
||||
$(document.body).trigger('click')
|
||||
}).on('hidden.bs.dropdown', function () {
|
||||
assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 0, '"show" class removed')
|
||||
$last.trigger('click')
|
||||
})
|
||||
|
||||
$last.trigger('click')
|
||||
assert.strictEqual($last.parent('.show').length, 1, '"show" class added on click')
|
||||
assert.strictEqual($('#qunit-fixture .show').length, 1, 'only one dropdown is shown')
|
||||
$(document.body).trigger('click')
|
||||
assert.strictEqual($('#qunit-fixture .show').length, 0, '"show" class removed')
|
||||
$last.parent('.btn-group')
|
||||
.on('shown.bs.dropdown', function () {
|
||||
assert.strictEqual($last.parent('.show').length, 1, '"show" class added on click')
|
||||
assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 1, 'only one dropdown is shown')
|
||||
$(document.body).trigger('click')
|
||||
}).on('hidden.bs.dropdown', function () {
|
||||
assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 0, '"show" class removed')
|
||||
done()
|
||||
})
|
||||
$first.trigger('click')
|
||||
})
|
||||
|
||||
QUnit.test('should remove "show" class if body is focused, with multiple dropdowns', function (assert) {
|
||||
QUnit.test('should remove "show" class if body if tabbing outside of menu, with multiple dropdowns', function (assert) {
|
||||
assert.expect(7)
|
||||
var done = assert.async()
|
||||
var dropdownHTML = '<div class="nav">'
|
||||
+ '<div class="dropdown" id="testmenu">'
|
||||
+ '<a class="dropdown-toggle" data-toggle="dropdown" href="#testmenu">Test menu <span class="caret"/></a>'
|
||||
@@ -276,32 +330,45 @@ $(function () {
|
||||
|
||||
assert.strictEqual($dropdowns.length, 2, 'two dropdowns')
|
||||
|
||||
$first.trigger('click')
|
||||
assert.strictEqual($first.parents('.show').length, 1, '"show" class added on click')
|
||||
assert.strictEqual($('#qunit-fixture .show').length, 1, 'only one dropdown is show')
|
||||
$(document.body).trigger('focusin')
|
||||
assert.strictEqual($('#qunit-fixture .show').length, 0, '"show" class removed')
|
||||
$first.parent('.dropdown')
|
||||
.on('shown.bs.dropdown', function () {
|
||||
assert.strictEqual($first.parents('.show').length, 1, '"show" class added on click')
|
||||
assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 1, 'only one dropdown is shown')
|
||||
var e = $.Event('keyup')
|
||||
e.which = 9 // Tab
|
||||
$(document.body).trigger(e)
|
||||
}).on('hidden.bs.dropdown', function () {
|
||||
assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 0, '"show" class removed')
|
||||
$last.trigger('click')
|
||||
})
|
||||
|
||||
$last.trigger('click')
|
||||
assert.strictEqual($last.parent('.show').length, 1, '"show" class added on click')
|
||||
assert.strictEqual($('#qunit-fixture .show').length, 1, 'only one dropdown is show')
|
||||
$(document.body).trigger('focusin')
|
||||
assert.strictEqual($('#qunit-fixture .show').length, 0, '"show" class removed')
|
||||
$last.parent('.btn-group')
|
||||
.on('shown.bs.dropdown', function () {
|
||||
assert.strictEqual($last.parent('.show').length, 1, '"show" class added on click')
|
||||
assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 1, 'only one dropdown is shown')
|
||||
var e = $.Event('keyup')
|
||||
e.which = 9 // Tab
|
||||
$(document.body).trigger(e)
|
||||
}).on('hidden.bs.dropdown', function () {
|
||||
assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 0, '"show" class removed')
|
||||
done()
|
||||
})
|
||||
$first.trigger('click')
|
||||
})
|
||||
|
||||
QUnit.test('should fire show and hide event', function (assert) {
|
||||
assert.expect(2)
|
||||
var dropdownHTML = '<ul class="tabs">'
|
||||
+ '<li class="dropdown">'
|
||||
var dropdownHTML = '<div class="tabs">'
|
||||
+ '<div class="dropdown">'
|
||||
+ '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>'
|
||||
+ '<ul class="dropdown-menu">'
|
||||
+ '<li><a href="#">Secondary link</a></li>'
|
||||
+ '<li><a href="#">Something else here</a></li>'
|
||||
+ '<li class="divider"/>'
|
||||
+ '<li><a href="#">Another link</a></li>'
|
||||
+ '</ul>'
|
||||
+ '</li>'
|
||||
+ '</ul>'
|
||||
+ '<div class="dropdown-menu">'
|
||||
+ '<a class="dropdown-item" href="#">Secondary link</a>'
|
||||
+ '<a class="dropdown-item" href="#">Something else here</a>'
|
||||
+ '<div class="divider"/>'
|
||||
+ '<a class="dropdown-item" href="#">Another link</a>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
var $dropdown = $(dropdownHTML)
|
||||
.appendTo('#qunit-fixture')
|
||||
.find('[data-toggle="dropdown"]')
|
||||
@@ -326,17 +393,17 @@ $(function () {
|
||||
|
||||
QUnit.test('should fire shown and hidden event', function (assert) {
|
||||
assert.expect(2)
|
||||
var dropdownHTML = '<ul class="tabs">'
|
||||
+ '<li class="dropdown">'
|
||||
var dropdownHTML = '<div class="tabs">'
|
||||
+ '<div class="dropdown">'
|
||||
+ '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>'
|
||||
+ '<ul class="dropdown-menu">'
|
||||
+ '<li><a href="#">Secondary link</a></li>'
|
||||
+ '<li><a href="#">Something else here</a></li>'
|
||||
+ '<li class="divider"/>'
|
||||
+ '<li><a href="#">Another link</a></li>'
|
||||
+ '</ul>'
|
||||
+ '</li>'
|
||||
+ '</ul>'
|
||||
+ '<div class="dropdown-menu">'
|
||||
+ '<a class="dropdown-item" href="#">Secondary link</a>'
|
||||
+ '<a class="dropdown-item" href="#">Something else here</a>'
|
||||
+ '<div class="divider"/>'
|
||||
+ '<a class="dropdown-item" href="#">Another link</a>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
var $dropdown = $(dropdownHTML)
|
||||
.appendTo('#qunit-fixture')
|
||||
.find('[data-toggle="dropdown"]')
|
||||
@@ -360,17 +427,17 @@ $(function () {
|
||||
|
||||
QUnit.test('should fire shown and hidden event with a relatedTarget', function (assert) {
|
||||
assert.expect(2)
|
||||
var dropdownHTML = '<ul class="tabs">'
|
||||
+ '<li class="dropdown">'
|
||||
var dropdownHTML = '<div class="tabs">'
|
||||
+ '<div class="dropdown">'
|
||||
+ '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>'
|
||||
+ '<ul class="dropdown-menu">'
|
||||
+ '<li><a href="#">Secondary link</a></li>'
|
||||
+ '<li><a href="#">Something else here</a></li>'
|
||||
+ '<li class="divider"/>'
|
||||
+ '<li><a href="#">Another link</a></li>'
|
||||
+ '</ul>'
|
||||
+ '</li>'
|
||||
+ '</ul>'
|
||||
+ '<div class="dropdown-menu">'
|
||||
+ '<a class="dropdown-item" href="#">Secondary link</a>'
|
||||
+ '<a class="dropdown-item" href="#">Something else here</a>'
|
||||
+ '<div class="divider"/>'
|
||||
+ '<a class="dropdown-item" href="#">Another link</a>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
var $dropdown = $(dropdownHTML)
|
||||
.appendTo('#qunit-fixture')
|
||||
.find('[data-toggle="dropdown"]')
|
||||
@@ -394,19 +461,19 @@ $(function () {
|
||||
assert.expect(3)
|
||||
var done = assert.async()
|
||||
|
||||
var dropdownHTML = '<ul class="tabs">'
|
||||
+ '<li class="dropdown">'
|
||||
var dropdownHTML = '<div class="tabs">'
|
||||
+ '<div class="dropdown">'
|
||||
+ '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>'
|
||||
+ '<ul class="dropdown-menu">'
|
||||
+ '<li><a href="#">Secondary link</a></li>'
|
||||
+ '<li><a href="#">Something else here</a></li>'
|
||||
+ '<li class="divider"/>'
|
||||
+ '<li><a href="#">Another link</a></li>'
|
||||
+ '<li><input type="text" id="input"></li>'
|
||||
+ '<li><textarea id="textarea"/></li>'
|
||||
+ '</ul>'
|
||||
+ '</li>'
|
||||
+ '</ul>'
|
||||
+ '<div class="dropdown-menu">'
|
||||
+ '<a class="dropdown-item" href="#">Secondary link</a>'
|
||||
+ '<a class="dropdown-item" href="#">Something else here</a>'
|
||||
+ '<div class="divider"/>'
|
||||
+ '<a class="dropdown-item" href="#">Another link</a>'
|
||||
+ '<input type="text" id="input">'
|
||||
+ '<textarea id="textarea"/>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
var $dropdown = $(dropdownHTML)
|
||||
.appendTo('#qunit-fixture')
|
||||
.find('[data-toggle="dropdown"]')
|
||||
@@ -433,63 +500,153 @@ $(function () {
|
||||
})
|
||||
|
||||
QUnit.test('should skip disabled element when using keyboard navigation', function (assert) {
|
||||
assert.expect(1)
|
||||
var dropdownHTML = '<ul class="tabs">'
|
||||
+ '<li class="dropdown">'
|
||||
assert.expect(2)
|
||||
var done = assert.async()
|
||||
var dropdownHTML = '<div class="tabs">'
|
||||
+ '<div class="dropdown">'
|
||||
+ '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>'
|
||||
+ '<ul class="dropdown-menu">'
|
||||
+ '<li class="disabled"><a href="#">Disabled link</a></li>'
|
||||
+ '<li><a href="#">Another link</a></li>'
|
||||
+ '</ul>'
|
||||
+ '</li>'
|
||||
+ '</ul>'
|
||||
+ '<div class="dropdown-menu">'
|
||||
+ '<a class="dropdown-item disabled" href="#">Disabled link</a>'
|
||||
+ '<a class="dropdown-item" href="#">Another link</a>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
var $dropdown = $(dropdownHTML)
|
||||
.appendTo('#qunit-fixture')
|
||||
.find('[data-toggle="dropdown"]')
|
||||
.bootstrapDropdown()
|
||||
.trigger('click')
|
||||
|
||||
$dropdown.trigger($.Event('keydown', { which: 40 }))
|
||||
$dropdown.trigger($.Event('keydown', { which: 40 }))
|
||||
$dropdown
|
||||
.parent('.dropdown')
|
||||
.on('shown.bs.dropdown', function () {
|
||||
assert.ok(true, 'shown was fired')
|
||||
$dropdown.trigger($.Event('keydown', { which: 40 }))
|
||||
$dropdown.trigger($.Event('keydown', { which: 40 }))
|
||||
assert.ok(!$(document.activeElement).is('.disabled'), '.disabled is not focused')
|
||||
done()
|
||||
})
|
||||
$dropdown.trigger('click')
|
||||
})
|
||||
|
||||
QUnit.test('should focus next/previous element when using keyboard navigation', function (assert) {
|
||||
assert.expect(4)
|
||||
var done = assert.async()
|
||||
var dropdownHTML = '<div class="tabs">'
|
||||
+ '<div class="dropdown">'
|
||||
+ '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>'
|
||||
+ '<div class="dropdown-menu">'
|
||||
+ '<a id="item1" class="dropdown-item" href="#">A link</a>'
|
||||
+ '<a id="item2" class="dropdown-item" href="#">Another link</a>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
var $dropdown = $(dropdownHTML)
|
||||
.appendTo('#qunit-fixture')
|
||||
.find('[data-toggle="dropdown"]')
|
||||
.bootstrapDropdown()
|
||||
|
||||
$dropdown
|
||||
.parent('.dropdown')
|
||||
.on('shown.bs.dropdown', function () {
|
||||
assert.ok(true, 'shown was fired')
|
||||
$dropdown.trigger($.Event('keydown', { which: 40 }))
|
||||
assert.ok($(document.activeElement).is($('#item1')), 'item1 is focused')
|
||||
|
||||
$(document.activeElement).trigger($.Event('keydown', { which: 40 }))
|
||||
assert.ok($(document.activeElement).is($('#item2')), 'item2 is focused')
|
||||
|
||||
$(document.activeElement).trigger($.Event('keydown', { which: 38 }))
|
||||
assert.ok($(document.activeElement).is($('#item1')), 'item1 is focused')
|
||||
done()
|
||||
})
|
||||
$dropdown.trigger('click')
|
||||
|
||||
assert.ok(!$(document.activeElement).parent().is('.disabled'), '.disabled is not focused')
|
||||
})
|
||||
|
||||
QUnit.test('should not close the dropdown if the user clicks on a text field', function (assert) {
|
||||
assert.expect(1)
|
||||
var dropdownHTML = '<div class="btn-group">'
|
||||
assert.expect(2)
|
||||
var done = assert.async()
|
||||
var dropdownHTML = '<div class="dropdown">'
|
||||
+ '<button type="button" data-toggle="dropdown">Dropdown</button>'
|
||||
+ '<ul class="dropdown-menu">'
|
||||
+ '<li><input id="textField" type="text" /></li>'
|
||||
+ '</ul>'
|
||||
+ '<div class="dropdown-menu">'
|
||||
+ '<input id="textField" type="text" />'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
var $dropdown = $(dropdownHTML)
|
||||
.appendTo('#qunit-fixture')
|
||||
.find('[data-toggle="dropdown"]')
|
||||
.bootstrapDropdown()
|
||||
.trigger('click')
|
||||
|
||||
$('#textField').trigger('click')
|
||||
var $textfield = $('#textField')
|
||||
$textfield.on('click', function () {
|
||||
assert.ok($dropdown.parent('.dropdown').hasClass('show'), 'dropdown menu is shown')
|
||||
done()
|
||||
})
|
||||
|
||||
assert.ok($dropdown.parent('.btn-group').hasClass('show'), 'dropdown menu is shown')
|
||||
$dropdown
|
||||
.parent('.dropdown')
|
||||
.on('shown.bs.dropdown', function () {
|
||||
assert.ok($dropdown.parent('.dropdown').hasClass('show'), 'dropdown menu is shown')
|
||||
$textfield.trigger($.Event('click'))
|
||||
})
|
||||
$dropdown.trigger('click')
|
||||
})
|
||||
|
||||
QUnit.test('should not close the dropdown if the user clicks on a textarea', function (assert) {
|
||||
assert.expect(1)
|
||||
var dropdownHTML = '<div class="btn-group">'
|
||||
assert.expect(2)
|
||||
var done = assert.async()
|
||||
var dropdownHTML = '<div class="dropdown">'
|
||||
+ '<button type="button" data-toggle="dropdown">Dropdown</button>'
|
||||
+ '<ul class="dropdown-menu">'
|
||||
+ '<li><textarea id="textArea"></textarea></li>'
|
||||
+ '</ul>'
|
||||
+ '<div class="dropdown-menu">'
|
||||
+ '<textarea id="textArea"></textarea>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
var $dropdown = $(dropdownHTML)
|
||||
.appendTo('#qunit-fixture')
|
||||
.find('[data-toggle="dropdown"]')
|
||||
.bootstrapDropdown()
|
||||
.trigger('click')
|
||||
|
||||
$('#textArea').trigger('click')
|
||||
var $textarea = $('#textArea')
|
||||
$textarea.on('click', function () {
|
||||
assert.ok($dropdown.parent('.dropdown').hasClass('show'), 'dropdown menu is shown')
|
||||
done()
|
||||
})
|
||||
|
||||
assert.ok($dropdown.parent('.btn-group').hasClass('show'), 'dropdown menu is shown')
|
||||
$dropdown
|
||||
.parent('.dropdown')
|
||||
.on('shown.bs.dropdown', function () {
|
||||
assert.ok($dropdown.parent('.dropdown').hasClass('show'), 'dropdown menu is shown')
|
||||
$textarea.trigger($.Event('click'))
|
||||
})
|
||||
$dropdown.trigger('click')
|
||||
})
|
||||
|
||||
QUnit.test('Dropdown should not use Popper.js in navbar', function (assert) {
|
||||
assert.expect(1)
|
||||
var done = assert.async()
|
||||
var html = '<nav class="navbar navbar-expand-md navbar-light bg-light">'
|
||||
+ '<div class="dropdown">'
|
||||
+ ' <a class="nav-link dropdown-toggle" href="#" id="dropdown" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Dropdown</a>'
|
||||
+ ' <div class="dropdown-menu" aria-labelledby="dropdown">'
|
||||
+ ' <a class="dropdown-item" href="#">Action</a>'
|
||||
+ ' <a class="dropdown-item" href="#">Another action</a>'
|
||||
+ ' <a class="dropdown-item" href="#">Something else here</a>'
|
||||
+ ' </div>'
|
||||
+ '</div>'
|
||||
+ '</nav>'
|
||||
|
||||
$(html).appendTo('#qunit-fixture')
|
||||
var $triggerDropdown = $('#qunit-fixture')
|
||||
.find('[data-toggle="dropdown"]')
|
||||
.bootstrapDropdown()
|
||||
var $dropdownMenu = $triggerDropdown.next()
|
||||
|
||||
$triggerDropdown
|
||||
.parent('.dropdown')
|
||||
.on('shown.bs.dropdown', function () {
|
||||
assert.ok($dropdownMenu.attr('style') === undefined, 'No inline style applied by Popper.js')
|
||||
done()
|
||||
})
|
||||
$triggerDropdown.trigger($.Event('click'))
|
||||
})
|
||||
})
|
||||
|
||||
+124
-45
@@ -9,6 +9,19 @@ $(function () {
|
||||
})
|
||||
|
||||
QUnit.module('modal', {
|
||||
before: function () {
|
||||
// Enable the scrollbar measurer
|
||||
$('<style type="text/css"> .modal-scrollbar-measure { position: absolute; top: -9999px; width: 50px; height: 50px; overflow: scroll; } </style>').appendTo('head')
|
||||
// Function to calculate the scrollbar width which is then compared to the padding or margin changes
|
||||
$.fn.getScrollbarWidth = function () {
|
||||
var scrollDiv = document.createElement('div')
|
||||
scrollDiv.className = 'modal-scrollbar-measure'
|
||||
document.body.appendChild(scrollDiv)
|
||||
var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
|
||||
document.body.removeChild(scrollDiv)
|
||||
return scrollbarWidth
|
||||
}
|
||||
},
|
||||
beforeEach: function () {
|
||||
// Run all tests in noConflict mode -- it's the only way to ensure that the plugin works in noConflict mode
|
||||
$.fn.bootstrapModal = $.fn.modal.noConflict()
|
||||
@@ -336,23 +349,127 @@ $(function () {
|
||||
$toggleBtn.trigger('click')
|
||||
})
|
||||
|
||||
QUnit.test('should restore inline body padding after closing', function (assert) {
|
||||
QUnit.test('should adjust the inline body padding when opening and restore when closing', function (assert) {
|
||||
assert.expect(2)
|
||||
var done = assert.async()
|
||||
var originalBodyPad = 0
|
||||
var $body = $(document.body)
|
||||
|
||||
$body.css('padding-right', originalBodyPad)
|
||||
var originalPadding = $body.css('padding-right')
|
||||
|
||||
$('<div id="modal-test"/>')
|
||||
.on('hidden.bs.modal', function () {
|
||||
var currentBodyPad = parseInt($body.css('padding-right'), 10)
|
||||
assert.notStrictEqual($body.attr('style'), '', 'body has non-empty style attribute')
|
||||
assert.strictEqual(currentBodyPad, originalBodyPad, 'original body padding was not changed')
|
||||
var currentPadding = $body.css('padding-right')
|
||||
assert.strictEqual(currentPadding, originalPadding, 'body padding should be reset after closing')
|
||||
$body.removeAttr('style')
|
||||
done()
|
||||
})
|
||||
.on('shown.bs.modal', function () {
|
||||
var expectedPadding = parseFloat(originalPadding) + $(this).getScrollbarWidth() + 'px'
|
||||
var currentPadding = $body.css('padding-right')
|
||||
assert.strictEqual(currentPadding, expectedPadding, 'body padding should be adjusted while opening')
|
||||
$(this).bootstrapModal('hide')
|
||||
})
|
||||
.bootstrapModal('show')
|
||||
})
|
||||
|
||||
QUnit.test('should store the original body padding in data-padding-right before showing', function (assert) {
|
||||
assert.expect(2)
|
||||
var done = assert.async()
|
||||
var $body = $(document.body)
|
||||
var originalPadding = '0px'
|
||||
$body.css('padding-right', originalPadding)
|
||||
|
||||
$('<div id="modal-test"/>')
|
||||
.on('hidden.bs.modal', function () {
|
||||
assert.strictEqual($body.data('padding-right'), undefined, 'data-padding-right should be cleared after closing')
|
||||
$body.removeAttr('style')
|
||||
done()
|
||||
})
|
||||
.on('shown.bs.modal', function () {
|
||||
assert.strictEqual($body.data('padding-right'), originalPadding, 'original body padding should be stored in data-padding-right')
|
||||
$(this).bootstrapModal('hide')
|
||||
})
|
||||
.bootstrapModal('show')
|
||||
})
|
||||
|
||||
QUnit.test('should adjust the inline padding of fixed elements when opening and restore when closing', function (assert) {
|
||||
assert.expect(2)
|
||||
var done = assert.async()
|
||||
var $element = $('<div class="fixed-top"></div>').appendTo('#qunit-fixture')
|
||||
var originalPadding = $element.css('padding-right')
|
||||
|
||||
$('<div id="modal-test"/>')
|
||||
.on('hidden.bs.modal', function () {
|
||||
var currentPadding = $element.css('padding-right')
|
||||
assert.strictEqual(currentPadding, originalPadding, 'fixed element padding should be reset after closing')
|
||||
$element.remove()
|
||||
done()
|
||||
})
|
||||
.on('shown.bs.modal', function () {
|
||||
var expectedPadding = parseFloat(originalPadding) + $(this).getScrollbarWidth() + 'px'
|
||||
var currentPadding = $element.css('padding-right')
|
||||
assert.strictEqual(currentPadding, expectedPadding, 'fixed element padding should be adjusted while opening')
|
||||
$(this).bootstrapModal('hide')
|
||||
})
|
||||
.bootstrapModal('show')
|
||||
})
|
||||
|
||||
QUnit.test('should store the original padding of fixed elements in data-padding-right before showing', function (assert) {
|
||||
assert.expect(2)
|
||||
var done = assert.async()
|
||||
var $element = $('<div class="fixed-top"></div>').appendTo('#qunit-fixture')
|
||||
var originalPadding = '0px'
|
||||
$element.css('padding-right', originalPadding)
|
||||
|
||||
$('<div id="modal-test"/>')
|
||||
.on('hidden.bs.modal', function () {
|
||||
assert.strictEqual($element.data('padding-right'), undefined, 'data-padding-right should be cleared after closing')
|
||||
$element.remove()
|
||||
done()
|
||||
})
|
||||
.on('shown.bs.modal', function () {
|
||||
assert.strictEqual($element.data('padding-right'), originalPadding, 'original fixed element padding should be stored in data-padding-right')
|
||||
$(this).bootstrapModal('hide')
|
||||
})
|
||||
.bootstrapModal('show')
|
||||
})
|
||||
|
||||
QUnit.test('should adjust the inline margin of the navbar-toggler when opening and restore when closing', function (assert) {
|
||||
assert.expect(2)
|
||||
var done = assert.async()
|
||||
var $element = $('<div class="navbar-toggler"></div>').appendTo('#qunit-fixture')
|
||||
var originalMargin = $element.css('margin-right')
|
||||
|
||||
$('<div id="modal-test"/>')
|
||||
.on('hidden.bs.modal', function () {
|
||||
var currentMargin = $element.css('margin-right')
|
||||
assert.strictEqual(currentMargin, originalMargin, 'navbar-toggler margin should be reset after closing')
|
||||
$element.remove()
|
||||
done()
|
||||
})
|
||||
.on('shown.bs.modal', function () {
|
||||
var expectedMargin = parseFloat(originalMargin) + $(this).getScrollbarWidth() + 'px'
|
||||
var currentMargin = $element.css('margin-right')
|
||||
assert.strictEqual(currentMargin, expectedMargin, 'navbar-toggler margin should be adjusted while opening')
|
||||
$(this).bootstrapModal('hide')
|
||||
})
|
||||
.bootstrapModal('show')
|
||||
})
|
||||
|
||||
QUnit.test('should store the original margin of the navbar-toggler in data-margin-right before showing', function (assert) {
|
||||
assert.expect(2)
|
||||
var done = assert.async()
|
||||
var $element = $('<div class="navbar-toggler"></div>').appendTo('#qunit-fixture')
|
||||
var originalMargin = '0px'
|
||||
$element.css('margin-right', originalMargin)
|
||||
|
||||
$('<div id="modal-test"/>')
|
||||
.on('hidden.bs.modal', function () {
|
||||
assert.strictEqual($element.data('margin-right'), undefined, 'data-margin-right should be cleared after closing')
|
||||
$element.remove()
|
||||
done()
|
||||
})
|
||||
.on('shown.bs.modal', function () {
|
||||
assert.strictEqual($element.data('margin-right'), originalMargin, 'original navbar-toggler margin should be stored in data-margin-right')
|
||||
$(this).bootstrapModal('hide')
|
||||
})
|
||||
.bootstrapModal('show')
|
||||
@@ -376,44 +493,6 @@ $(function () {
|
||||
.bootstrapModal('show')
|
||||
})
|
||||
|
||||
QUnit.test('should have a paddingRight when the modal is taller than the viewport', function (assert) {
|
||||
assert.expect(2)
|
||||
var done = assert.async()
|
||||
$('<div class="fixed-top fixed-bottom sticky-top is-fixed">@Johann-S</div>').appendTo('#qunit-fixture')
|
||||
$('.fixed-top, .fixed-bottom, .is-fixed, .sticky-top').css('padding-right', '10px')
|
||||
|
||||
$('<div id="modal-test"/>')
|
||||
.on('shown.bs.modal', function () {
|
||||
var paddingRight = parseInt($(document.body).css('padding-right'), 10)
|
||||
assert.strictEqual(isNaN(paddingRight), false)
|
||||
assert.strictEqual(paddingRight !== 0, true)
|
||||
$(document.body).css('padding-right', '') // Because test case "should ignore other inline styles when trying to restore body padding after closing" fail if not
|
||||
done()
|
||||
})
|
||||
.bootstrapModal('show')
|
||||
})
|
||||
|
||||
QUnit.test('should remove padding-right on modal after closing', function (assert) {
|
||||
assert.expect(3)
|
||||
var done = assert.async()
|
||||
$('<div class="fixed-top fixed-bottom is-fixed sticky-top">@Johann-S</div>').appendTo('#qunit-fixture')
|
||||
$('.fixed-top, .fixed-bottom, .is-fixed, .sticky-top').css('padding-right', '10px')
|
||||
|
||||
$('<div id="modal-test"/>')
|
||||
.on('shown.bs.modal', function () {
|
||||
var paddingRight = parseInt($(document.body).css('padding-right'), 10)
|
||||
assert.strictEqual(isNaN(paddingRight), false)
|
||||
assert.strictEqual(paddingRight !== 0, true)
|
||||
$(this).bootstrapModal('hide')
|
||||
})
|
||||
.on('hidden.bs.modal', function () {
|
||||
var paddingRight = parseInt($(document.body).css('padding-right'), 10)
|
||||
assert.strictEqual(paddingRight, 0)
|
||||
done()
|
||||
})
|
||||
.bootstrapModal('show')
|
||||
})
|
||||
|
||||
QUnit.test('should ignore other inline styles when trying to restore body padding after closing', function (assert) {
|
||||
assert.expect(2)
|
||||
var done = assert.async()
|
||||
|
||||
-72
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* grunt-contrib-qunit
|
||||
* http://gruntjs.com/
|
||||
*
|
||||
* Copyright (c) 2014 "Cowboy" Ben Alman, contributors
|
||||
* Licensed under the MIT license.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict'
|
||||
|
||||
// Don't re-order tests.
|
||||
QUnit.config.reorder = false
|
||||
// Run tests serially, not in parallel.
|
||||
QUnit.config.autorun = false
|
||||
|
||||
// Send messages to the parent PhantomJS process via alert! Good times!!
|
||||
function sendMessage() {
|
||||
var args = [].slice.call(arguments)
|
||||
alert(JSON.stringify(args))
|
||||
}
|
||||
|
||||
// These methods connect QUnit to PhantomJS.
|
||||
QUnit.log(function (obj) {
|
||||
// What is this I don’t even
|
||||
if (obj.message === '[object Object], undefined:undefined') { return }
|
||||
|
||||
// Parse some stuff before sending it.
|
||||
var actual
|
||||
var expected
|
||||
if (!obj.result) {
|
||||
// Dumping large objects can be very slow, and the dump isn't used for
|
||||
// passing tests, so only dump if the test failed.
|
||||
actual = QUnit.dump.parse(obj.actual)
|
||||
expected = QUnit.dump.parse(obj.expected)
|
||||
}
|
||||
// Send it.
|
||||
sendMessage('qunit.log', obj.result, actual, expected, obj.message, obj.source)
|
||||
})
|
||||
|
||||
QUnit.testStart(function (obj) {
|
||||
sendMessage('qunit.testStart', obj.name)
|
||||
})
|
||||
|
||||
QUnit.testDone(function (obj) {
|
||||
sendMessage('qunit.testDone', obj.name, obj.failed, obj.passed, obj.total, obj.duration)
|
||||
})
|
||||
|
||||
QUnit.moduleStart(function (obj) {
|
||||
sendMessage('qunit.moduleStart', obj.name)
|
||||
})
|
||||
|
||||
QUnit.moduleDone(function (obj) {
|
||||
if (obj.failed === 0) {
|
||||
console.log('\r\u221A All tests passed in "' + obj.name + '" module')
|
||||
} else {
|
||||
console.log('\u00D7 ' + obj.failed + ' tests failed in "' + obj.name + '" module')
|
||||
}
|
||||
sendMessage('qunit.moduleDone', obj.name, obj.failed, obj.passed, obj.total)
|
||||
})
|
||||
|
||||
QUnit.begin(function () {
|
||||
sendMessage('qunit.begin')
|
||||
console.log('\n\nStarting test suite')
|
||||
console.log('================================================\n')
|
||||
})
|
||||
|
||||
QUnit.done(function (obj) {
|
||||
sendMessage('qunit.done', obj.failed, obj.passed, obj.total, obj.runtime)
|
||||
})
|
||||
|
||||
}())
|
||||
+40
-17
@@ -47,13 +47,18 @@ $(function () {
|
||||
|
||||
QUnit.test('should render popover element', function (assert) {
|
||||
assert.expect(2)
|
||||
var $popover = $('<a href="#" title="mdo" data-content="https://twitter.com/mdo">@mdo</a>')
|
||||
var done = assert.async()
|
||||
$('<a href="#" title="mdo" data-content="https://twitter.com/mdo">@mdo</a>')
|
||||
.appendTo('#qunit-fixture')
|
||||
.on('shown.bs.popover', function () {
|
||||
assert.notEqual($('.popover').length, 0, 'popover was inserted')
|
||||
$(this).bootstrapPopover('hide')
|
||||
})
|
||||
.on('hidden.bs.popover', function () {
|
||||
assert.strictEqual($('.popover').length, 0, 'popover removed')
|
||||
done()
|
||||
})
|
||||
.bootstrapPopover('show')
|
||||
|
||||
assert.notEqual($('.popover').length, 0, 'popover was inserted')
|
||||
$popover.bootstrapPopover('hide')
|
||||
assert.strictEqual($('.popover').length, 0, 'popover removed')
|
||||
})
|
||||
|
||||
QUnit.test('should store popover instance in popover data object', function (assert) {
|
||||
@@ -90,8 +95,8 @@ $(function () {
|
||||
$popover.bootstrapPopover('show')
|
||||
|
||||
assert.notEqual($('.popover').length, 0, 'popover was inserted')
|
||||
assert.strictEqual($('.popover .popover-title').text(), '@fat', 'title correctly inserted')
|
||||
assert.strictEqual($('.popover .popover-content').text(), 'loves writing tests (╯°□°)╯︵ ┻━┻', 'content correctly inserted')
|
||||
assert.strictEqual($('.popover .popover-header').text(), '@fat', 'title correctly inserted')
|
||||
assert.strictEqual($('.popover .popover-body').text(), 'loves writing tests (╯°□°)╯︵ ┻━┻', 'content correctly inserted')
|
||||
|
||||
$popover.bootstrapPopover('hide')
|
||||
|
||||
@@ -109,10 +114,10 @@ $(function () {
|
||||
$popover.bootstrapPopover('show')
|
||||
|
||||
assert.notEqual($('.popover').length, 0, 'popover inserted')
|
||||
assert.strictEqual($('.popover .popover-title').text(), '@glebm <3 writing tests', 'title inserted')
|
||||
assert.strictEqual($('.popover .popover-header').text(), '@glebm <3 writing tests', 'title inserted')
|
||||
assert.ok($.contains($('.popover').get(0), title), 'title node moved, not copied')
|
||||
// toLowerCase because IE8 will return <I>...</I>
|
||||
assert.strictEqual($('.popover .popover-content').html().toLowerCase(), '<i>¯\\_(ツ)_/¯</i>', 'content inserted')
|
||||
assert.strictEqual($('.popover .popover-body').html().toLowerCase(), '<i>¯\\_(ツ)_/¯</i>', 'content inserted')
|
||||
assert.ok($.contains($('.popover').get(0), content), 'content node moved, not copied')
|
||||
})
|
||||
|
||||
@@ -127,9 +132,9 @@ $(function () {
|
||||
$popover.bootstrapPopover('show')
|
||||
|
||||
assert.notEqual($('.popover').length, 0, 'popover inserted')
|
||||
assert.strictEqual($('.popover .popover-title').text(), '@glebm <3 writing tests', 'title inserted')
|
||||
assert.strictEqual($('.popover .popover-header').text(), '@glebm <3 writing tests', 'title inserted')
|
||||
assert.ok(!$.contains($('.popover').get(0), title), 'title node copied, not moved')
|
||||
assert.strictEqual($('.popover .popover-content').html(), '¯\\_(ツ)_/¯', 'content inserted')
|
||||
assert.strictEqual($('.popover .popover-body').html(), '¯\\_(ツ)_/¯', 'content inserted')
|
||||
assert.ok(!$.contains($('.popover').get(0), content), 'content node copied, not moved')
|
||||
})
|
||||
|
||||
@@ -149,14 +154,14 @@ $(function () {
|
||||
|
||||
$popover.bootstrapPopover('show')
|
||||
assert.notEqual($('.popover').length, 0, 'popover was inserted')
|
||||
assert.equal($('.popover .popover-content').html(), $div[0].outerHTML, 'content correctly inserted')
|
||||
assert.equal($('.popover .popover-body').html(), $div[0].outerHTML, 'content correctly inserted')
|
||||
|
||||
$popover.bootstrapPopover('hide')
|
||||
assert.strictEqual($('.popover').length, 0, 'popover was removed')
|
||||
|
||||
$popover.bootstrapPopover('show')
|
||||
assert.notEqual($('.popover').length, 0, 'popover was inserted')
|
||||
assert.equal($('.popover .popover-content').html(), $div[0].outerHTML, 'content correctly inserted')
|
||||
assert.equal($('.popover .popover-body').html(), $div[0].outerHTML, 'content correctly inserted')
|
||||
|
||||
$popover.bootstrapPopover('hide')
|
||||
assert.strictEqual($('.popover').length, 0, 'popover was removed')
|
||||
@@ -170,8 +175,8 @@ $(function () {
|
||||
.bootstrapPopover('show')
|
||||
|
||||
assert.notEqual($('.popover').length, 0, 'popover was inserted')
|
||||
assert.strictEqual($('.popover .popover-title').text(), '@mdo', 'title correctly inserted')
|
||||
assert.strictEqual($('.popover .popover-content').text(), 'loves data attributes (づ。◕‿‿◕。)づ ︵ ┻━┻', 'content correctly inserted')
|
||||
assert.strictEqual($('.popover .popover-header').text(), '@mdo', 'title correctly inserted')
|
||||
assert.strictEqual($('.popover .popover-body').text(), 'loves data attributes (づ。◕‿‿◕。)づ ︵ ┻━┻', 'content correctly inserted')
|
||||
|
||||
$popover.bootstrapPopover('hide')
|
||||
assert.strictEqual($('.popover').length, 0, 'popover was removed')
|
||||
@@ -188,8 +193,8 @@ $(function () {
|
||||
.bootstrapPopover('show')
|
||||
|
||||
assert.notEqual($('.popover').length, 0, 'popover was inserted')
|
||||
assert.strictEqual($('.popover .popover-title').text(), '@mdo', 'title correctly inserted')
|
||||
assert.strictEqual($('.popover .popover-content').text(), 'loves data attributes (づ。◕‿‿◕。)づ ︵ ┻━┻', 'content correctly inserted')
|
||||
assert.strictEqual($('.popover .popover-header').text(), '@mdo', 'title correctly inserted')
|
||||
assert.strictEqual($('.popover .popover-body').text(), 'loves data attributes (づ。◕‿‿◕。)づ ︵ ┻━┻', 'content correctly inserted')
|
||||
|
||||
$popover.bootstrapPopover('hide')
|
||||
assert.strictEqual($('.popover').length, 0, 'popover was removed')
|
||||
@@ -364,4 +369,22 @@ $(function () {
|
||||
})
|
||||
.modal('show')
|
||||
})
|
||||
|
||||
QUnit.test('should convert number to string without error for content and title', function (assert) {
|
||||
assert.expect(2)
|
||||
var done = assert.async()
|
||||
var $popover = $('<a href="#">@mdo</a>')
|
||||
.appendTo('#qunit-fixture')
|
||||
.bootstrapPopover({
|
||||
title: 5,
|
||||
content: 7
|
||||
})
|
||||
.on('shown.bs.popover', function () {
|
||||
assert.strictEqual($('.popover .popover-header').text(), '5')
|
||||
assert.strictEqual($('.popover .popover-body').text(), '7')
|
||||
done()
|
||||
})
|
||||
|
||||
$popover.bootstrapPopover('show')
|
||||
})
|
||||
})
|
||||
|
||||
+188
-34
@@ -26,7 +26,7 @@ $(function () {
|
||||
|
||||
QUnit.test('should throw explicit error on undefined method', function (assert) {
|
||||
assert.expect(1)
|
||||
var $el = $('<div/>')
|
||||
var $el = $('<div/>').appendTo('#qunit-fixture')
|
||||
$el.bootstrapScrollspy()
|
||||
try {
|
||||
$el.bootstrapScrollspy('noMethod')
|
||||
@@ -38,7 +38,7 @@ $(function () {
|
||||
|
||||
QUnit.test('should return jquery collection containing the element', function (assert) {
|
||||
assert.expect(2)
|
||||
var $el = $('<div/>')
|
||||
var $el = $('<div/>').appendTo('#qunit-fixture')
|
||||
var $scrollspy = $el.bootstrapScrollspy()
|
||||
assert.ok($scrollspy instanceof $, 'returns jquery collection')
|
||||
assert.strictEqual($scrollspy[0], $el[0], 'collection contains element')
|
||||
@@ -53,8 +53,8 @@ $(function () {
|
||||
+ '<div class="topbar-inner">'
|
||||
+ '<div class="container" id="ss-target">'
|
||||
+ '<ul class="nav">'
|
||||
+ '<li><a href="#masthead">Overview</a></li>'
|
||||
+ '<li><a href="#detail">Detail</a></li>'
|
||||
+ '<li class="nav-item"><a href="#masthead">Overview</a></li>'
|
||||
+ '<li class="nav-item"><a href="#detail">Detail</a></li>'
|
||||
+ '</ul>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
@@ -98,8 +98,8 @@ $(function () {
|
||||
+ '<div class="topbar-inner">'
|
||||
+ '<div class="container" id="ss-target">'
|
||||
+ '<ul class="nav">'
|
||||
+ '<li><a href="#masthead">Overview</a></li>'
|
||||
+ '<li><a href="#detail">Detail</a></li>'
|
||||
+ '<li class="nav-item"><a href="#masthead">Overview</a></li>'
|
||||
+ '<li class="nav-item"><a href="#detail">Detail</a></li>'
|
||||
+ '</ul>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
@@ -140,10 +140,10 @@ $(function () {
|
||||
|
||||
var sectionHTML = '<div id="header" style="height: 500px;"></div>'
|
||||
+ '<nav id="navigation" class="navbar">'
|
||||
+ '<ul class="nav navbar-nav">'
|
||||
+ '<li class="active"><a class="nav-link" id="one-link" href="#one">One</a></li>'
|
||||
+ '<li><a class="nav-link" id="two-link" href="#two">Two</a></li>'
|
||||
+ '<li><a class="nav-link" id="three-link" href="#three">Three</a></li>'
|
||||
+ '<ul class="navbar-nav">'
|
||||
+ '<li class="nav-item active"><a class="nav-link" id="one-link" href="#one">One</a></li>'
|
||||
+ '<li class="nav-item"><a class="nav-link" id="two-link" href="#two">Two</a></li>'
|
||||
+ '<li class="nav-item"><a class="nav-link" id="three-link" href="#three">Three</a></li>'
|
||||
+ '</ul>'
|
||||
+ '</nav>'
|
||||
+ '<div id="content" style="height: 200px; overflow-y: auto;">'
|
||||
@@ -173,8 +173,8 @@ $(function () {
|
||||
var navbarHtml =
|
||||
'<nav class="navbar">'
|
||||
+ '<ul class="nav">'
|
||||
+ '<li><a class="nav-link" id="a-1" href="#div-1">div 1</a></li>'
|
||||
+ '<li><a class="nav-link" id="a-2" href="#div-2">div 2</a></li>'
|
||||
+ '<li class="nav-item"><a class="nav-link" id="a-1" href="#div-1">div 1</a></li>'
|
||||
+ '<li class="nav-item"><a class="nav-link" id="a-2" href="#div-2">div 2</a></li>'
|
||||
+ '</ul>'
|
||||
+ '</nav>'
|
||||
var contentHtml =
|
||||
@@ -205,15 +205,89 @@ $(function () {
|
||||
.then(function () { done() })
|
||||
})
|
||||
|
||||
QUnit.test('should add the active class to the correct element (nav markup)', function (assert) {
|
||||
assert.expect(2)
|
||||
var navbarHtml =
|
||||
'<nav class="navbar">'
|
||||
+ '<nav class="nav">'
|
||||
+ '<a class="nav-link" id="a-1" href="#div-1">div 1</a>'
|
||||
+ '<a class="nav-link" id="a-2" href="#div-2">div 2</a>'
|
||||
+ '</nav>'
|
||||
+ '</nav>'
|
||||
var contentHtml =
|
||||
'<div class="content" style="overflow: auto; height: 50px">'
|
||||
+ '<div id="div-1" style="height: 100px; padding: 0; margin: 0">div 1</div>'
|
||||
+ '<div id="div-2" style="height: 200px; padding: 0; margin: 0">div 2</div>'
|
||||
+ '</div>'
|
||||
|
||||
$(navbarHtml).appendTo('#qunit-fixture')
|
||||
var $content = $(contentHtml)
|
||||
.appendTo('#qunit-fixture')
|
||||
.bootstrapScrollspy({ offset: 0, target: '.navbar' })
|
||||
|
||||
var done = assert.async()
|
||||
var testElementIsActiveAfterScroll = function (element, target) {
|
||||
var deferred = $.Deferred()
|
||||
var scrollHeight = Math.ceil($content.scrollTop() + $(target).position().top)
|
||||
$content.one('scroll', function () {
|
||||
assert.ok($(element).hasClass('active'), 'target:' + target + ', element' + element)
|
||||
deferred.resolve()
|
||||
})
|
||||
$content.scrollTop(scrollHeight)
|
||||
return deferred.promise()
|
||||
}
|
||||
|
||||
$.when(testElementIsActiveAfterScroll('#a-1', '#div-1'))
|
||||
.then(function () { return testElementIsActiveAfterScroll('#a-2', '#div-2') })
|
||||
.then(function () { done() })
|
||||
})
|
||||
|
||||
QUnit.test('should add the active class to the correct element (list-group markup)', function (assert) {
|
||||
assert.expect(2)
|
||||
var navbarHtml =
|
||||
'<nav class="navbar">'
|
||||
+ '<div class="list-group">'
|
||||
+ '<a class="list-group-item" id="a-1" href="#div-1">div 1</a>'
|
||||
+ '<a class="list-group-item" id="a-2" href="#div-2">div 2</a>'
|
||||
+ '</div>'
|
||||
+ '</nav>'
|
||||
var contentHtml =
|
||||
'<div class="content" style="overflow: auto; height: 50px">'
|
||||
+ '<div id="div-1" style="height: 100px; padding: 0; margin: 0">div 1</div>'
|
||||
+ '<div id="div-2" style="height: 200px; padding: 0; margin: 0">div 2</div>'
|
||||
+ '</div>'
|
||||
|
||||
$(navbarHtml).appendTo('#qunit-fixture')
|
||||
var $content = $(contentHtml)
|
||||
.appendTo('#qunit-fixture')
|
||||
.bootstrapScrollspy({ offset: 0, target: '.navbar' })
|
||||
|
||||
var done = assert.async()
|
||||
var testElementIsActiveAfterScroll = function (element, target) {
|
||||
var deferred = $.Deferred()
|
||||
var scrollHeight = Math.ceil($content.scrollTop() + $(target).position().top)
|
||||
$content.one('scroll', function () {
|
||||
assert.ok($(element).hasClass('active'), 'target:' + target + ', element' + element)
|
||||
deferred.resolve()
|
||||
})
|
||||
$content.scrollTop(scrollHeight)
|
||||
return deferred.promise()
|
||||
}
|
||||
|
||||
$.when(testElementIsActiveAfterScroll('#a-1', '#div-1'))
|
||||
.then(function () { return testElementIsActiveAfterScroll('#a-2', '#div-2') })
|
||||
.then(function () { done() })
|
||||
})
|
||||
|
||||
QUnit.test('should add the active class correctly when there are nested elements at 0 scroll offset', function (assert) {
|
||||
assert.expect(6)
|
||||
var times = 0
|
||||
var done = assert.async()
|
||||
var navbarHtml = '<nav id="navigation" class="navbar">'
|
||||
+ '<ul class="nav">'
|
||||
+ '<li><a id="a-1" class="nav-link" href="#div-1">div 1</a>'
|
||||
+ '<ul>'
|
||||
+ '<li><a id="a-2" class="nav-link" href="#div-2">div 2</a></li>'
|
||||
+ '<li class="nav-item"><a id="a-1" class="nav-link" href="#div-1">div 1</a>'
|
||||
+ '<ul class="nav">'
|
||||
+ '<li class="nav-item"><a id="a-2" class="nav-link" href="#div-2">div 2</a></li>'
|
||||
+ '</ul>'
|
||||
+ '</li>'
|
||||
+ '</ul>'
|
||||
@@ -246,16 +320,96 @@ $(function () {
|
||||
testActiveElements()
|
||||
})
|
||||
|
||||
QUnit.test('should add the active class correctly when there are nested elements (nav markup)', function (assert) {
|
||||
assert.expect(6)
|
||||
var times = 0
|
||||
var done = assert.async()
|
||||
var navbarHtml = '<nav id="navigation" class="navbar">'
|
||||
+ '<nav class="nav">'
|
||||
+ '<a id="a-1" class="nav-link" href="#div-1">div 1</a>'
|
||||
+ '<nav class="nav">'
|
||||
+ '<a id="a-2" class="nav-link" href="#div-2">div 2</a>'
|
||||
+ '</nav>'
|
||||
+ '</nav>'
|
||||
+ '</nav>'
|
||||
|
||||
var contentHtml = '<div class="content" style="position: absolute; top: 0px; overflow: auto; height: 50px">'
|
||||
+ '<div id="div-1" style="padding: 0; margin: 0">'
|
||||
+ '<div id="div-2" style="height: 200px; padding: 0; margin: 0">div 2</div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
|
||||
$(navbarHtml).appendTo('#qunit-fixture')
|
||||
|
||||
var $content = $(contentHtml)
|
||||
.appendTo('#qunit-fixture')
|
||||
.bootstrapScrollspy({ offset: 0, target: '#navigation' })
|
||||
|
||||
function testActiveElements() {
|
||||
if (++times > 3) { return done() }
|
||||
|
||||
$content.one('scroll', function () {
|
||||
assert.ok($('#a-1').hasClass('active'), 'nav item for outer element has "active" class')
|
||||
assert.ok($('#a-2').hasClass('active'), 'nav item for inner element has "active" class')
|
||||
testActiveElements()
|
||||
})
|
||||
|
||||
$content.scrollTop($content.scrollTop() + 10)
|
||||
}
|
||||
|
||||
testActiveElements()
|
||||
})
|
||||
|
||||
QUnit.test('should add the active class correctly when there are nested elements (list-group markup)', function (assert) {
|
||||
assert.expect(6)
|
||||
var times = 0
|
||||
var done = assert.async()
|
||||
var navbarHtml = '<nav id="navigation" class="navbar">'
|
||||
+ '<div class="list-group">'
|
||||
+ '<a id="a-1" class="list-group-item" href="#div-1">div 1</a>'
|
||||
+ '<div class="list-group">'
|
||||
+ '<a id="a-2" class="list-group-item" href="#div-2">div 2</a>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</nav>'
|
||||
|
||||
var contentHtml = '<div class="content" style="position: absolute; top: 0px; overflow: auto; height: 50px">'
|
||||
+ '<div id="div-1" style="padding: 0; margin: 0">'
|
||||
+ '<div id="div-2" style="height: 200px; padding: 0; margin: 0">div 2</div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
|
||||
$(navbarHtml).appendTo('#qunit-fixture')
|
||||
|
||||
var $content = $(contentHtml)
|
||||
.appendTo('#qunit-fixture')
|
||||
.bootstrapScrollspy({ offset: 0, target: '#navigation' })
|
||||
|
||||
function testActiveElements() {
|
||||
if (++times > 3) { return done() }
|
||||
|
||||
$content.one('scroll', function () {
|
||||
assert.ok($('#a-1').hasClass('active'), 'nav item for outer element has "active" class')
|
||||
assert.ok($('#a-2').hasClass('active'), 'nav item for inner element has "active" class')
|
||||
testActiveElements()
|
||||
})
|
||||
|
||||
$content.scrollTop($content.scrollTop() + 10)
|
||||
}
|
||||
|
||||
testActiveElements()
|
||||
})
|
||||
|
||||
QUnit.test('should clear selection if above the first section', function (assert) {
|
||||
assert.expect(3)
|
||||
var done = assert.async()
|
||||
|
||||
var sectionHTML = '<div id="header" style="height: 500px;"></div>'
|
||||
+ '<nav id="navigation" class="navbar">'
|
||||
+ '<ul class="nav navbar-nav">'
|
||||
+ '<li><a id="one-link" class="nav-link active" href="#one">One</a></li>'
|
||||
+ '<li><a id="two-link" class="nav-link" href="#two">Two</a></li>'
|
||||
+ '<li><a id="three-link" class="nav-link" href="#three">Three</a></li>'
|
||||
+ '<ul class="navbar-nav">'
|
||||
+ '<li class="nav-item"><a id="one-link" class="nav-link active" href="#one">One</a></li>'
|
||||
+ '<li class="nav-item"><a id="two-link" class="nav-link" href="#two">Two</a></li>'
|
||||
+ '<li class="nav-item"><a id="three-link" class="nav-link" href="#three">Three</a></li>'
|
||||
+ '</ul>'
|
||||
+ '</nav>'
|
||||
$(sectionHTML).appendTo('#qunit-fixture')
|
||||
@@ -293,10 +447,10 @@ $(function () {
|
||||
|
||||
var sectionHTML = '<div id="header" style="height: 500px;"></div>'
|
||||
+ '<nav id="navigation" class="navbar">'
|
||||
+ '<ul class="nav navbar-nav">'
|
||||
+ '<li><a id="one-link" class="nav-link active" href="#one">One</a></li>'
|
||||
+ '<li><a id="two-link" class="nav-link" href="#two">Two</a></li>'
|
||||
+ '<li><a id="three-link" class="nav-link" href="#three">Three</a></li>'
|
||||
+ '<ul class="navbar-nav">'
|
||||
+ '<li class="nav-item"><a id="one-link" class="nav-link active" href="#one">One</a></li>'
|
||||
+ '<li class="nav-item"><a id="two-link" class="nav-link" href="#two">Two</a></li>'
|
||||
+ '<li class="nav-item"><a id="three-link" class="nav-link" href="#three">Three</a></li>'
|
||||
+ '</ul>'
|
||||
+ '</nav>'
|
||||
$(sectionHTML).appendTo('#qunit-fixture')
|
||||
@@ -336,11 +490,11 @@ $(function () {
|
||||
var navbarHtml =
|
||||
'<nav class="navbar">'
|
||||
+ '<ul class="nav">'
|
||||
+ '<li><a id="li-100-1" class="nav-link" href="#div-100-1">div 1</a></li>'
|
||||
+ '<li><a id="li-100-2" class="nav-link" href="#div-100-2">div 2</a></li>'
|
||||
+ '<li><a id="li-100-3" class="nav-link" href="#div-100-3">div 3</a></li>'
|
||||
+ '<li><a id="li-100-4" class="nav-link" href="#div-100-4">div 4</a></li>'
|
||||
+ '<li><a id="li-100-5" class="nav-link" href="#div-100-5">div 5</a></li>'
|
||||
+ '<li class="nav-item"><a id="li-100-1" class="nav-link" href="#div-100-1">div 1</a></li>'
|
||||
+ '<li class="nav-item"><a id="li-100-2" class="nav-link" href="#div-100-2">div 2</a></li>'
|
||||
+ '<li class="nav-item"><a id="li-100-3" class="nav-link" href="#div-100-3">div 3</a></li>'
|
||||
+ '<li class="nav-item"><a id="li-100-4" class="nav-link" href="#div-100-4">div 4</a></li>'
|
||||
+ '<li class="nav-item"><a id="li-100-5" class="nav-link" href="#div-100-5">div 5</a></li>'
|
||||
+ '</ul>'
|
||||
+ '</nav>'
|
||||
var contentHtml =
|
||||
@@ -384,9 +538,9 @@ $(function () {
|
||||
var $navbar = $(
|
||||
'<nav class="navbar"' + (type === 'data' ? ' id="navbar-offset-method-menu"' : '') + '>'
|
||||
+ '<ul class="nav">'
|
||||
+ '<li><a id="li-' + type + 'm-1" class="nav-link" href="#div-' + type + 'm-1">div 1</a></li>'
|
||||
+ '<li><a id="li-' + type + 'm-2" class="nav-link" href="#div-' + type + 'm-2">div 2</a></li>'
|
||||
+ '<li><a id="li-' + type + 'm-3" class="nav-link" href="#div-' + type + 'm-3">div 3</a></li>'
|
||||
+ '<li class="nav-item"><a id="li-' + type + 'm-1" class="nav-link" href="#div-' + type + 'm-1">div 1</a></li>'
|
||||
+ '<li class="nav-item"><a id="li-' + type + 'm-2" class="nav-link" href="#div-' + type + 'm-2">div 2</a></li>'
|
||||
+ '<li class="nav-item"><a id="li-' + type + 'm-3" class="nav-link" href="#div-' + type + 'm-3">div 3</a></li>'
|
||||
+ '</ul>'
|
||||
+ '</nav>'
|
||||
)
|
||||
@@ -428,9 +582,9 @@ $(function () {
|
||||
var $navbar = $(
|
||||
'<nav class="navbar"' + (type === 'data' ? ' id="navbar-offset-method-menu"' : '') + '>'
|
||||
+ '<ul class="nav">'
|
||||
+ '<li><a class="nav-link" id="li-' + type + 'm-1" href="#div-' + type + 'm-1">div 1</a></li>'
|
||||
+ '<li><a class="nav-link" id="li-' + type + 'm-2" href="#div-' + type + 'm-2">div 2</a></li>'
|
||||
+ '<li><a class="nav-link" id="li-' + type + 'm-3" href="#div-' + type + 'm-3">div 3</a></li>'
|
||||
+ '<li class="nav-item"><a class="nav-link" id="li-' + type + 'm-1" href="#div-' + type + 'm-1">div 1</a></li>'
|
||||
+ '<li class="nav-item"><a class="nav-link" id="li-' + type + 'm-2" href="#div-' + type + 'm-2">div 2</a></li>'
|
||||
+ '<li class="nav-item"><a class="nav-link" id="li-' + type + 'm-3" href="#div-' + type + 'm-3">div 3</a></li>'
|
||||
+ '</ul>'
|
||||
+ '</nav>'
|
||||
)
|
||||
|
||||
+24
-8
@@ -46,7 +46,7 @@ $(function () {
|
||||
|
||||
QUnit.test('should activate element by tab id', function (assert) {
|
||||
assert.expect(2)
|
||||
var tabsHTML = '<ul class="tabs">'
|
||||
var tabsHTML = '<ul class="nav">'
|
||||
+ '<li><a href="#home">Home</a></li>'
|
||||
+ '<li><a href="#profile">Profile</a></li>'
|
||||
+ '</ul>'
|
||||
@@ -62,7 +62,7 @@ $(function () {
|
||||
|
||||
QUnit.test('should activate element by tab id', function (assert) {
|
||||
assert.expect(2)
|
||||
var pillsHTML = '<ul class="pills">'
|
||||
var pillsHTML = '<ul class="nav nav-pills">'
|
||||
+ '<li><a href="#home">Home</a></li>'
|
||||
+ '<li><a href="#profile">Profile</a></li>'
|
||||
+ '</ul>'
|
||||
@@ -78,7 +78,7 @@ $(function () {
|
||||
|
||||
QUnit.test('should activate element by tab id in ordered list', function (assert) {
|
||||
assert.expect(2)
|
||||
var pillsHTML = '<ol class="pills">'
|
||||
var pillsHTML = '<ol class="nav nav-pills">'
|
||||
+ '<li><a href="#home">Home</a></li>'
|
||||
+ '<li><a href="#profile">Profile</a></li>'
|
||||
+ '</ol>'
|
||||
@@ -108,11 +108,27 @@ $(function () {
|
||||
assert.strictEqual($('#qunit-fixture').find('.active').attr('id'), 'home')
|
||||
})
|
||||
|
||||
QUnit.test('should activate element by tab id in list group', function (assert) {
|
||||
assert.expect(2)
|
||||
var tabsHTML = '<div class="list-group">' +
|
||||
'<a href="#home">Home</a>' +
|
||||
'<a href="#profile">Profile</a>' +
|
||||
'</div>'
|
||||
|
||||
$('<nav><div id="home"></div><div id="profile"></div></nav>').appendTo('#qunit-fixture')
|
||||
|
||||
$(tabsHTML).find('a:last').bootstrapTab('show')
|
||||
assert.strictEqual($('#qunit-fixture').find('.active').attr('id'), 'profile')
|
||||
|
||||
$(tabsHTML).find('a:first').bootstrapTab('show')
|
||||
assert.strictEqual($('#qunit-fixture').find('.active').attr('id'), 'home')
|
||||
})
|
||||
|
||||
QUnit.test('should not fire shown when show is prevented', function (assert) {
|
||||
assert.expect(1)
|
||||
var done = assert.async()
|
||||
|
||||
$('<div class="tab"/>')
|
||||
$('<div class="nav"/>')
|
||||
.on('show.bs.tab', function (e) {
|
||||
e.preventDefault()
|
||||
assert.ok(true, 'show event fired')
|
||||
@@ -166,7 +182,7 @@ $(function () {
|
||||
assert.expect(2)
|
||||
var done = assert.async()
|
||||
|
||||
var dropHTML = '<ul class="drop">'
|
||||
var dropHTML = '<ul class="drop nav">'
|
||||
+ '<li class="dropdown"><a data-toggle="dropdown" href="#">1</a>'
|
||||
+ '<ul class="dropdown-menu">'
|
||||
+ '<li><a href="#1-1" data-toggle="tab">1-1</a></li>'
|
||||
@@ -194,7 +210,7 @@ $(function () {
|
||||
assert.expect(2)
|
||||
var done = assert.async()
|
||||
|
||||
var tabsHTML = '<ul class="tabs">'
|
||||
var tabsHTML = '<ul class="nav">'
|
||||
+ '<li><a href="#home">Home</a></li>'
|
||||
+ '<li><a href="#profile">Profile</a></li>'
|
||||
+ '</ul>'
|
||||
@@ -225,7 +241,7 @@ $(function () {
|
||||
assert.expect(1)
|
||||
var done = assert.async()
|
||||
|
||||
var tabsHTML = '<ul class="tabs">'
|
||||
var tabsHTML = '<ul class="nav">'
|
||||
+ '<li><a href="#home">Home</a></li>'
|
||||
+ '<li><a href="#profile">Profile</a></li>'
|
||||
+ '</ul>'
|
||||
@@ -250,7 +266,7 @@ $(function () {
|
||||
assert.expect(2)
|
||||
var done = assert.async()
|
||||
|
||||
var tabsHTML = '<ul class="tabs">'
|
||||
var tabsHTML = '<ul class="nav">'
|
||||
+ '<li><a href="#home">Home</a></li>'
|
||||
+ '<li><a href="#profile">Profile</a></li>'
|
||||
+ '</ul>'
|
||||
|
||||
+60
-103
@@ -111,7 +111,7 @@ $(function () {
|
||||
|
||||
assert
|
||||
.ok($('.tooltip')
|
||||
.is('.fade.bs-tether-element-attached-top.bs-tether-element-attached-center.show'), 'has correct classes applied')
|
||||
.is('.fade.bs-tooltip-bottom.show'), 'has correct classes applied')
|
||||
|
||||
$tooltip.bootstrapTooltip('hide')
|
||||
|
||||
@@ -364,32 +364,29 @@ $(function () {
|
||||
})
|
||||
|
||||
QUnit.test('should add position class before positioning so that position-specific styles are taken into account', function (assert) {
|
||||
assert.expect(1)
|
||||
assert.expect(2)
|
||||
var done = assert.async()
|
||||
var styles = '<style>'
|
||||
+ '.tooltip.right { white-space: nowrap; }'
|
||||
+ '.tooltip.right .tooltip-inner { max-width: none; }'
|
||||
+ '.bs-tooltip-right { white-space: nowrap; }'
|
||||
+ '.bs-tooltip-right .tooltip-inner { max-width: none; }'
|
||||
+ '</style>'
|
||||
var $styles = $(styles).appendTo('head')
|
||||
|
||||
var $container = $('<div/>').appendTo('#qunit-fixture')
|
||||
var $target = $('<a href="#" rel="tooltip" title="very very very very very very very very long tooltip in one line"/>')
|
||||
$('<a href="#" rel="tooltip" title="very very very very very very very very long tooltip in one line"/>')
|
||||
.appendTo($container)
|
||||
.bootstrapTooltip({
|
||||
placement: 'right'
|
||||
placement: 'right',
|
||||
trigger: 'manual'
|
||||
})
|
||||
.on('inserted.bs.tooltip', function () {
|
||||
var $tooltip = $($(this).data('bs.tooltip').tip)
|
||||
assert.ok($tooltip.hasClass('bs-tooltip-right'))
|
||||
assert.ok($tooltip.attr('style') === undefined)
|
||||
$styles.remove()
|
||||
done()
|
||||
})
|
||||
.bootstrapTooltip('show')
|
||||
|
||||
var $tooltip = $($target.data('bs.tooltip').tip)
|
||||
|
||||
// this is some dumb hack stuff because sub pixels in firefox
|
||||
var top = Math.round($target.offset().top + $target[0].offsetHeight / 2 - $tooltip[0].offsetHeight / 2)
|
||||
var top2 = Math.round($tooltip.offset().top)
|
||||
var topDiff = top - top2
|
||||
assert.ok(topDiff <= 1 && topDiff >= -1)
|
||||
$target.bootstrapTooltip('hide')
|
||||
|
||||
$container.remove()
|
||||
$styles.remove()
|
||||
})
|
||||
|
||||
QUnit.test('should use title attribute for tooltip text', function (assert) {
|
||||
@@ -459,7 +456,7 @@ $(function () {
|
||||
assert.expect(1)
|
||||
var done = assert.async()
|
||||
|
||||
var containerHTML = '<div>'
|
||||
var containerHTML = '<div id="test">'
|
||||
+ '<p style="margin-top: 200px">'
|
||||
+ '<a href="#" title="very very very very very very very long tooltip">Hover me</a>'
|
||||
+ '</p>'
|
||||
@@ -476,21 +473,24 @@ $(function () {
|
||||
})
|
||||
.appendTo('#qunit-fixture')
|
||||
|
||||
var $trigger = $container
|
||||
$container
|
||||
.find('a')
|
||||
.css('margin-top', 200)
|
||||
.bootstrapTooltip({
|
||||
placement: 'top',
|
||||
animate: false
|
||||
})
|
||||
.on('shown.bs.tooltip', function () {
|
||||
var $tooltip = $($(this).data('bs.tooltip').tip)
|
||||
if (/iPhone|iPad|iPod/.test(navigator.userAgent)) {
|
||||
assert.ok(Math.round($tooltip.offset().top + $tooltip.outerHeight()) <= Math.round($(this).offset().top))
|
||||
}
|
||||
else {
|
||||
assert.ok(Math.round($tooltip.offset().top + $tooltip.outerHeight()) >= Math.round($(this).offset().top))
|
||||
}
|
||||
done()
|
||||
})
|
||||
.bootstrapTooltip('show')
|
||||
|
||||
var $tooltip = $($trigger.data('bs.tooltip').tip)
|
||||
|
||||
setTimeout(function () {
|
||||
assert.ok(Math.round($tooltip.offset().top + $tooltip.outerHeight()) <= Math.round($trigger.offset().top))
|
||||
done()
|
||||
}, 0)
|
||||
})
|
||||
|
||||
QUnit.test('should show tooltip if leave event hasn\'t occurred before delay expires', function (assert) {
|
||||
@@ -629,45 +629,6 @@ $(function () {
|
||||
$tooltip.trigger('mouseenter')
|
||||
})
|
||||
|
||||
QUnit.test('should correctly position tooltips on SVG elements', function (assert) {
|
||||
if (!window.SVGElement) {
|
||||
// Skip IE8 since it doesn't support SVG
|
||||
assert.expect(0)
|
||||
return
|
||||
}
|
||||
assert.expect(2)
|
||||
|
||||
var done = assert.async()
|
||||
|
||||
var styles = '<style>'
|
||||
+ '.tooltip, .tooltip *, .tooltip *:before, .tooltip *:after { box-sizing: border-box; }'
|
||||
+ '.tooltip { position: absolute; }'
|
||||
+ '.tooltip .tooltip-inner { width: 24px; height: 24px; font-family: Helvetica; }'
|
||||
+ '</style>'
|
||||
var $styles = $(styles).appendTo('head')
|
||||
|
||||
$('#qunit-fixture').append(
|
||||
'<div style="position: fixed; top: 0; left: 0;">'
|
||||
+ ' <svg width="200" height="200">'
|
||||
+ ' <circle cx="100" cy="100" r="10" title="m" id="theCircle" />'
|
||||
+ ' </svg>'
|
||||
+ '</div>')
|
||||
var $circle = $('#theCircle')
|
||||
|
||||
$circle
|
||||
.on('shown.bs.tooltip', function () {
|
||||
var offset = $('.tooltip').offset()
|
||||
$styles.remove()
|
||||
assert.ok(Math.abs(offset.left - 88) <= 1, 'tooltip has correct horizontal location')
|
||||
$circle.bootstrapTooltip('hide')
|
||||
assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom')
|
||||
done()
|
||||
})
|
||||
.bootstrapTooltip({ placement: 'top', trigger: 'manual' })
|
||||
|
||||
$circle.bootstrapTooltip('show')
|
||||
})
|
||||
|
||||
QUnit.test('should not reload the tooltip on subsequent mouseenter events', function (assert) {
|
||||
assert.expect(1)
|
||||
var titleHtml = function () {
|
||||
@@ -731,43 +692,6 @@ $(function () {
|
||||
assert.strictEqual(currentUid, $('#tt-content').text())
|
||||
})
|
||||
|
||||
QUnit.test('should correctly position tooltips on transformed elements', function (assert) {
|
||||
var styleProps = document.documentElement.style
|
||||
if (!('transform' in styleProps) && !('webkitTransform' in styleProps) && !('msTransform' in styleProps)) {
|
||||
assert.expect(0)
|
||||
return
|
||||
}
|
||||
assert.expect(2)
|
||||
|
||||
var done = assert.async()
|
||||
|
||||
var styles = '<style>'
|
||||
+ '#qunit-fixture { top: 0; left: 0; }'
|
||||
+ '.tooltip, .tooltip *, .tooltip *:before, .tooltip *:after { box-sizing: border-box; }'
|
||||
+ '.tooltip { position: absolute; }'
|
||||
+ '.tooltip .tooltip-inner { width: 24px; height: 24px; font-family: Helvetica; }'
|
||||
+ '#target { position: absolute; top: 100px; left: 50px; width: 100px; height: 200px; -webkit-transform: rotate(270deg); -ms-transform: rotate(270deg); transform: rotate(270deg); }'
|
||||
+ '</style>'
|
||||
var $styles = $(styles).appendTo('head')
|
||||
|
||||
var $element = $('<div id="target" title="1"/>').appendTo('#qunit-fixture')
|
||||
|
||||
$element
|
||||
.on('shown.bs.tooltip', function () {
|
||||
var offset = $('.tooltip').offset()
|
||||
$styles.remove()
|
||||
assert.ok(Math.abs(offset.left - 88) <= 1, 'tooltip has correct horizontal location')
|
||||
assert.ok(Math.abs(offset.top - 126) <= 1, 'tooltip has correct vertical location')
|
||||
$element.bootstrapTooltip('hide')
|
||||
done()
|
||||
})
|
||||
.bootstrapTooltip({
|
||||
trigger: 'manual'
|
||||
})
|
||||
|
||||
$element.bootstrapTooltip('show')
|
||||
})
|
||||
|
||||
QUnit.test('should do nothing when an attempt is made to hide an uninitialized tooltip', function (assert) {
|
||||
assert.expect(1)
|
||||
|
||||
@@ -869,4 +793,37 @@ $(function () {
|
||||
})
|
||||
.modal('show')
|
||||
})
|
||||
|
||||
QUnit.test('should reset tip classes when hidden event triggered', function (assert) {
|
||||
assert.expect(2)
|
||||
var done = assert.async()
|
||||
var $el = $('<a href="#" rel="tooltip" title="Test tooltip"/>')
|
||||
.appendTo('#qunit-fixture')
|
||||
.bootstrapTooltip('show')
|
||||
.on('hidden.bs.tooltip', function () {
|
||||
var tooltip = $el.data('bs.tooltip')
|
||||
var $tooltip = $(tooltip.getTipElement())
|
||||
assert.ok($tooltip.hasClass('tooltip'))
|
||||
assert.ok($tooltip.hasClass('fade'))
|
||||
done()
|
||||
})
|
||||
|
||||
$el.bootstrapTooltip('hide')
|
||||
})
|
||||
|
||||
QUnit.test('should convert number in title to string', function (assert) {
|
||||
assert.expect(1)
|
||||
var done = assert.async()
|
||||
var $el = $('<a href="#" rel="tooltip" title="7"/>')
|
||||
.appendTo('#qunit-fixture')
|
||||
.bootstrapTooltip('show')
|
||||
.on('shown.bs.tooltip', function () {
|
||||
var tooltip = $el.data('bs.tooltip')
|
||||
var $tooltip = $(tooltip.getTipElement())
|
||||
assert.strictEqual($tooltip.children().text(), '7')
|
||||
done()
|
||||
})
|
||||
|
||||
$el.bootstrapTooltip('show')
|
||||
})
|
||||
})
|
||||
|
||||
+5039
-4428
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user