diff --git a/Gruntfile.js b/Gruntfile.js
index 4754571ed..facc3672d 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -72,7 +72,8 @@ module.exports = function (grunt) {
'js/dist/modal.js' : 'js/src/modal.js',
'js/dist/scrollspy.js' : 'js/src/scrollspy.js',
'js/dist/tab.js' : 'js/src/tab.js',
- 'js/dist/tooltip.js' : 'js/src/tooltip.js'
+ 'js/dist/tooltip.js' : 'js/src/tooltip.js',
+ 'js/dist/popover.js' : 'js/src/popover.js'
}
}
},
diff --git a/dist/css/bootstrap.css b/dist/css/bootstrap.css
index c7aefbb6f..f7cabd0e0 100644
--- a/dist/css/bootstrap.css
+++ b/dist/css/bootstrap.css
@@ -3995,7 +3995,7 @@ button.close {
top: 0;
left: 0;
z-index: 1060;
- display: none;
+ display: block;
max-width: 276px;
padding: 1px;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
@@ -4008,18 +4008,74 @@ button.close {
background-clip: padding-box;
border: 1px solid rgba(0, 0, 0, 0.2);
border-radius: 0.3rem; }
-
-.popover-top {
- margin-top: -10px; }
-
-.popover-right {
- margin-left: 10px; }
-
-.popover-bottom {
- margin-top: 10px; }
-
-.popover-left {
- margin-left: -10px; }
+ .popover.popover-top,
+ .popover.bs-tether-element-attached-bottom {
+ margin-top: -10px; }
+ .popover.popover-top .popover-arrow,
+ .popover.bs-tether-element-attached-bottom .popover-arrow {
+ bottom: -11px;
+ left: 50%;
+ margin-left: -11px;
+ border-top-color: rgba(0, 0, 0, 0.25);
+ border-bottom-width: 0; }
+ .popover.popover-top .popover-arrow:after,
+ .popover.bs-tether-element-attached-bottom .popover-arrow:after {
+ bottom: 1px;
+ margin-left: -10px;
+ content: "";
+ border-top-color: #fff;
+ border-bottom-width: 0; }
+ .popover.popover-right,
+ .popover.bs-tether-element-attached-left {
+ margin-left: 10px; }
+ .popover.popover-right .popover-arrow,
+ .popover.bs-tether-element-attached-left .popover-arrow {
+ top: 50%;
+ left: -11px;
+ margin-top: -11px;
+ border-right-color: rgba(0, 0, 0, 0.25);
+ border-left-width: 0; }
+ .popover.popover-right .popover-arrow:after,
+ .popover.bs-tether-element-attached-left .popover-arrow:after {
+ bottom: -10px;
+ left: 1px;
+ content: "";
+ border-right-color: #fff;
+ border-left-width: 0; }
+ .popover.popover-bottom,
+ .popover.bs-tether-element-attached-top {
+ margin-top: 10px; }
+ .popover.popover-bottom .popover-arrow,
+ .popover.bs-tether-element-attached-top .popover-arrow {
+ top: -11px;
+ left: 50%;
+ margin-left: -11px;
+ border-top-width: 0;
+ border-bottom-color: rgba(0, 0, 0, 0.25); }
+ .popover.popover-bottom .popover-arrow:after,
+ .popover.bs-tether-element-attached-top .popover-arrow:after {
+ top: 1px;
+ margin-left: -10px;
+ content: "";
+ border-top-width: 0;
+ border-bottom-color: #fff; }
+ .popover.popover-left,
+ .popover.bs-tether-element-attached-right {
+ margin-left: -10px; }
+ .popover.popover-left .popover-arrow,
+ .popover.bs-tether-element-attached-right .popover-arrow {
+ top: 50%;
+ right: -11px;
+ margin-top: -11px;
+ border-right-width: 0;
+ border-left-color: rgba(0, 0, 0, 0.25); }
+ .popover.popover-left .popover-arrow:after,
+ .popover.bs-tether-element-attached-right .popover-arrow:after {
+ right: 1px;
+ bottom: -10px;
+ content: "";
+ border-right-width: 0;
+ border-left-color: #fff; }
.popover-title {
padding: 8px 14px;
@@ -4048,58 +4104,6 @@ button.close {
content: "";
border-width: 10px; }
-.popover-top > .popover-arrow {
- bottom: -11px;
- left: 50%;
- margin-left: -11px;
- border-top-color: rgba(0, 0, 0, 0.25);
- border-bottom-width: 0; }
- .popover-top > .popover-arrow:after {
- bottom: 1px;
- margin-left: -10px;
- content: "";
- border-top-color: #fff;
- border-bottom-width: 0; }
-
-.popover-right > .popover-arrow {
- top: 50%;
- left: -11px;
- margin-top: -11px;
- border-right-color: rgba(0, 0, 0, 0.25);
- border-left-width: 0; }
- .popover-right > .popover-arrow:after {
- bottom: -10px;
- left: 1px;
- content: "";
- border-right-color: #fff;
- border-left-width: 0; }
-
-.popover-bottom > .popover-arrow {
- top: -11px;
- left: 50%;
- margin-left: -11px;
- border-top-width: 0;
- border-bottom-color: rgba(0, 0, 0, 0.25); }
- .popover-bottom > .popover-arrow:after {
- top: 1px;
- margin-left: -10px;
- content: "";
- border-top-width: 0;
- border-bottom-color: #fff; }
-
-.popover-left > .popover-arrow {
- top: 50%;
- right: -11px;
- margin-top: -11px;
- border-right-width: 0;
- border-left-color: rgba(0, 0, 0, 0.25); }
- .popover-left > .popover-arrow:after {
- right: 1px;
- bottom: -10px;
- content: "";
- border-right-width: 0;
- border-left-color: #fff; }
-
.carousel {
position: relative; }
diff --git a/dist/css/bootstrap.css.map b/dist/css/bootstrap.css.map
index dae2dfaf9..e21e231a9 100644
Binary files a/dist/css/bootstrap.css.map and b/dist/css/bootstrap.css.map differ
diff --git a/js/dist/popover.js b/js/dist/popover.js
new file mode 100644
index 000000000..d6c3a3594
--- /dev/null
+++ b/js/dist/popover.js
@@ -0,0 +1,189 @@
+'use strict';
+
+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'); } }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0): popover.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Popover = (function ($) {
+
+ /**
+ * ------------------------------------------------------------------------
+ * Constants
+ * ------------------------------------------------------------------------
+ */
+
+ var NAME = 'popover';
+ var VERSION = '4.0.0';
+ var DATA_KEY = 'bs.popover';
+ var JQUERY_NO_CONFLICT = $.fn[NAME];
+
+ var Default = $.extend({}, Tooltip.Default, {
+ placement: 'right',
+ trigger: 'click',
+ content: '',
+ template: '
'
+ });
+
+ var ClassName = {
+ FADE: 'fade',
+ IN: 'in'
+ };
+
+ var Selector = {
+ TITLE: '.popover-title',
+ CONTENT: '.popover-content',
+ ARROW: '.popover-arrow'
+ };
+
+ var Event = {
+ HIDE: 'hide.bs.popover',
+ HIDDEN: 'hidden.bs.popover',
+ SHOW: 'show.bs.popover',
+ SHOWN: 'shown.bs.popover',
+ INSERTED: 'inserted.bs.popover',
+ CLICK: 'click.bs.popover',
+ FOCUSIN: 'focusin.bs.popover',
+ FOCUSOUT: 'focusout.bs.popover',
+ MOUSEENTER: 'mouseenter.bs.popover',
+ MOUSELEAVE: 'mouseleave.bs.popover'
+ };
+
+ /**
+ * ------------------------------------------------------------------------
+ * Class Definition
+ * ------------------------------------------------------------------------
+ */
+
+ var Popover = (function (_Tooltip) {
+ function Popover() {
+ _classCallCheck(this, Popover);
+
+ if (_Tooltip != null) {
+ _Tooltip.apply(this, arguments);
+ }
+ }
+
+ _inherits(Popover, _Tooltip);
+
+ _createClass(Popover, [{
+ key: 'isWithContent',
+
+ // overrides
+
+ value: function isWithContent() {
+ return this.getTitle() || this._getContent();
+ }
+ }, {
+ key: 'getTipElement',
+ value: function getTipElement() {
+ return this.tip = this.tip || $(this.config['template'])[0];
+ }
+ }, {
+ key: 'setContent',
+ value: function setContent() {
+ var tip = this.getTipElement();
+ var title = this.getTitle();
+ var content = this._getContent();
+ var titleElement = $(tip).find(Selector.TITLE)[0];
+
+ if (titleElement) {
+ titleElement[this.config.html ? 'innerHTML' : 'innerText'] = title;
+ }
+
+ // we use append for html objects to maintain js events
+ $(tip).find(Selector.CONTENT).children().detach().end()[this.config.html ? typeof content === 'string' ? 'html' : 'append' : 'text'](content);
+
+ $(tip).removeClass(ClassName.FADE).removeClass(ClassName.IN);
+
+ this.cleanupTether();
+ }
+ }, {
+ key: '_getContent',
+
+ // private
+
+ value: function _getContent() {
+ return this.element.getAttribute('data-content') || (typeof this.config.content == 'function' ? this.config.content.call(this.element) : this.config.content);
+ }
+ }], [{
+ key: 'VERSION',
+
+ // getters
+
+ get: function () {
+ return VERSION;
+ }
+ }, {
+ key: 'Default',
+ get: function () {
+ return Default;
+ }
+ }, {
+ key: 'NAME',
+ get: function () {
+ return NAME;
+ }
+ }, {
+ key: 'DATA_KEY',
+ get: function () {
+ return DATA_KEY;
+ }
+ }, {
+ key: 'Event',
+ get: function () {
+ return Event;
+ }
+ }, {
+ key: '_jQueryInterface',
+
+ // static
+
+ value: function _jQueryInterface(config) {
+ return this.each(function () {
+ var data = $(this).data(DATA_KEY);
+ var _config = typeof config === 'object' ? config : null;
+
+ if (!data && /destroy|hide/.test(config)) {
+ return;
+ }
+
+ if (!data) {
+ data = new Popover(this, _config);
+ $(this).data(DATA_KEY, data);
+ }
+
+ if (typeof config === 'string') {
+ data[config]();
+ }
+ });
+ }
+ }]);
+
+ return Popover;
+ })(Tooltip);
+
+ /**
+ * ------------------------------------------------------------------------
+ * jQuery
+ * ------------------------------------------------------------------------
+ */
+
+ $.fn[NAME] = Popover._jQueryInterface;
+ $.fn[NAME].Constructor = Popover;
+ $.fn[NAME].noConflict = function () {
+ $.fn[NAME] = JQUERY_NO_CONFLICT;
+ return Popover._jQueryInterface;
+ };
+
+ return Popover;
+})(jQuery);
+//# sourceMappingURL=popover.js.map
\ No newline at end of file
diff --git a/js/dist/popover.js.map b/js/dist/popover.js.map
new file mode 100644
index 000000000..c6865e239
Binary files /dev/null and b/js/dist/popover.js.map differ
diff --git a/js/dist/scrollspy.js b/js/dist/scrollspy.js
index 6bcfe883c..2c530b21b 100644
--- a/js/dist/scrollspy.js
+++ b/js/dist/scrollspy.js
@@ -57,7 +57,7 @@ var ScrollSpy = (function ($) {
_classCallCheck(this, ScrollSpy);
this._scrollElement = element.tagName === 'BODY' ? window : element;
- this._config = $.extend({}, Defaults, config);
+ this._config = $.extend({}, Default, config);
this._selector = '' + (this._config.target || '') + ' .nav li > a';
this._offsets = [];
this._targets = [];
diff --git a/js/dist/scrollspy.js.map b/js/dist/scrollspy.js.map
index cf1c3ce1a..46c0410a0 100644
Binary files a/js/dist/scrollspy.js.map and b/js/dist/scrollspy.js.map differ
diff --git a/js/dist/tooltip.js b/js/dist/tooltip.js
index 0ff622018..5e9fffcd6 100644
--- a/js/dist/tooltip.js
+++ b/js/dist/tooltip.js
@@ -6,12 +6,12 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
/**
* --------------------------------------------------------------------------
- * Bootstrap (v4.0.0): alert.js
+ * Bootstrap (v4.0.0): tooltip.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* --------------------------------------------------------------------------
*/
-var ToolTip = (function ($) {
+var Tooltip = (function ($) {
/**
* ------------------------------------------------------------------------
@@ -34,33 +34,16 @@ var ToolTip = (function ($) {
delay: 0,
html: false,
selector: false,
- attachment: 'top',
+ placement: 'top',
offset: '0 0',
constraints: null
};
- var HorizontalMirror = {
- LEFT: 'right',
- CENTER: 'center',
- RIGHT: 'left'
- };
-
- var VerticalMirror = {
- TOP: 'bottom',
- MIDDLE: 'middle',
- BOTTOM: 'top'
- };
-
- var VerticalDefault = {
- LEFT: 'middle',
- CENTER: 'bottom',
- RIGHT: 'middle'
- };
-
- var HorizontalDefault = {
- TOP: 'center',
- MIDDLE: 'left',
- BOTTOM: 'center'
+ var AttachmentMap = {
+ TOP: 'bottom center',
+ RIGHT: 'middle left',
+ BOTTOM: 'top center',
+ LEFT: 'middle right'
};
var HoverState = {
@@ -88,13 +71,18 @@ var ToolTip = (function ($) {
var Selector = {
TOOLTIP: '.tooltip',
- TOOLTIP_INNER: '.tooltip-inner',
- TOOLTIP_ARROW: '.tooltip-arrow'
- };
+ TOOLTIP_INNER: '.tooltip-inner' };
var TetherClass = {
- 'element': false,
- 'enabled': false
+ element: false,
+ enabled: false
+ };
+
+ var Trigger = {
+ HOVER: 'hover',
+ FOCUS: 'focus',
+ CLICK: 'click',
+ MANUAL: 'manual'
};
/**
@@ -112,12 +100,12 @@ var ToolTip = (function ($) {
this._timeout = 0;
this._hoverState = '';
this._activeTrigger = {};
+ this._tether = null;
// protected
this.element = element;
this.config = this._getConfig(config);
this.tip = null;
- this.tether = null;
this._setListeners();
}
@@ -144,13 +132,14 @@ var ToolTip = (function ($) {
key: 'toggle',
value: function toggle(event) {
var context = this;
+ var dataKey = this.constructor.DATA_KEY;
if (event) {
- context = $(event.currentTarget).data(DATA_KEY);
+ context = $(event.currentTarget).data(dataKey);
if (!context) {
context = new this.constructor(event.currentTarget, this._getDelegateConfig());
- $(event.currentTarget).data(DATA_KEY, context);
+ $(event.currentTarget).data(dataKey, context);
}
context._activeTrigger.click = !context._activeTrigger.click;
@@ -171,7 +160,13 @@ var ToolTip = (function ($) {
clearTimeout(this._timeout);
this.hide(function () {
- $(_this.element).off(Selector.TOOLTIP).removeData(DATA_KEY);
+ $(_this.element).off('.' + _this.constructor.NAME).removeData(_this.constructor.DATA_KEY);
+
+ if (_this.tip) {
+ $(_this.tip).detach();
+ }
+
+ _this.tip = null;
});
}
}, {
@@ -179,7 +174,7 @@ var ToolTip = (function ($) {
value: function show() {
var _this2 = this;
- var showEvent = $.Event(Event.SHOW);
+ var showEvent = $.Event(this.constructor.Event.SHOW);
if (this.isWithContent() && this._isEnabled) {
$(this.element).trigger(showEvent);
@@ -191,7 +186,7 @@ var ToolTip = (function ($) {
}
var tip = this.getTipElement();
- var tipId = Util.getUID(NAME);
+ var tipId = Util.getUID(this.constructor.NAME);
tip.setAttribute('id', tipId);
this.element.setAttribute('aria-describedby', tipId);
@@ -202,17 +197,16 @@ var ToolTip = (function ($) {
$(tip).addClass(ClassName.FADE);
}
- var attachment = typeof this.config.attachment === 'function' ? this.config.attachment.call(this, tip, this.element) : this.config.attachment;
+ var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement;
- attachment = this.getAttachment(attachment);
+ var attachment = this._getAttachment(placement);
- $(tip).data(DATA_KEY, this);
+ $(tip).data(this.constructor.DATA_KEY, this).appendTo(document.body);
- this.element.parentNode.insertBefore(tip, this.element.nextSibling);
- $(this.element).trigger(Event.INSERTED);
+ $(this.element).trigger(this.constructor.Event.INSERTED);
- this.tether = new Tether({
- element: this.tip,
+ this._tether = new Tether({
+ element: tip,
target: this.element,
attachment: attachment,
classes: TetherClass,
@@ -222,7 +216,7 @@ var ToolTip = (function ($) {
});
Util.reflow(tip);
- this.tether.position();
+ this._tether.position();
$(tip).addClass(ClassName.IN);
@@ -230,7 +224,7 @@ var ToolTip = (function ($) {
var prevHoverState = _this2._hoverState;
_this2._hoverState = null;
- $(_this2.element).trigger(Event.SHOWN);
+ $(_this2.element).trigger(_this2.constructor.Event.SHOWN);
if (prevHoverState === HoverState.OUT) {
_this2._leave(null, _this2);
@@ -246,14 +240,14 @@ var ToolTip = (function ($) {
var _this3 = this;
var tip = this.getTipElement();
- var hideEvent = $.Event(Event.HIDE);
+ var hideEvent = $.Event(this.constructor.Event.HIDE);
var complete = function complete() {
if (_this3._hoverState !== HoverState.IN && tip.parentNode) {
tip.parentNode.removeChild(tip);
}
_this3.element.removeAttribute('aria-describedby');
- $(_this3.element).trigger(Event.HIDDEN);
+ $(_this3.element).trigger(_this3.constructor.Event.HIDDEN);
_this3.cleanupTether();
if (callback) {
@@ -291,63 +285,6 @@ var ToolTip = (function ($) {
value: function getTipElement() {
return this.tip = this.tip || $(this.config.template)[0];
}
- }, {
- key: 'getAttachment',
- value: function getAttachment(attachmentString) {
- var attachmentArray = attachmentString.split(' ');
- var normalizedAttachment = {};
-
- if (!attachmentArray.length) {
- throw new Error('Tooltip requires attachment');
- }
-
- var _iteratorNormalCompletion = true;
- var _didIteratorError = false;
- var _iteratorError = undefined;
-
- try {
- for (var _iterator = attachmentArray[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
- var attachment = _step.value;
-
- attachment = attachment.toUpperCase();
-
- if (HorizontalMirror[attachment]) {
- normalizedAttachment.horizontal = HorizontalMirror[attachment];
- }
-
- if (VerticalMirror[attachment]) {
- normalizedAttachment.vertical = VerticalMirror[attachment];
- }
- }
- } catch (err) {
- _didIteratorError = true;
- _iteratorError = err;
- } finally {
- try {
- if (!_iteratorNormalCompletion && _iterator['return']) {
- _iterator['return']();
- }
- } finally {
- if (_didIteratorError) {
- throw _iteratorError;
- }
- }
- }
-
- if (!normalizedAttachment.horizontal && !normalizedAttachment.vertical) {
- throw new Error('Tooltip requires valid attachment');
- }
-
- if (!normalizedAttachment.horizontal) {
- normalizedAttachment.horizontal = HorizontalDefault[normalizedAttachment.vertical.toUpperCase()];
- }
-
- if (!normalizedAttachment.vertical) {
- normalizedAttachment.vertical = VerticalDefault[normalizedAttachment.horizontal.toUpperCase()];
- }
-
- return [normalizedAttachment.vertical, normalizedAttachment.horizontal].join(' ');
- }
}, {
key: 'setContent',
value: function setContent() {
@@ -372,29 +309,29 @@ var ToolTip = (function ($) {
return title;
}
- }, {
- key: 'removeTetherClasses',
- value: function removeTetherClasses(i, css) {
- return ((css.baseVal || css).match(new RegExp('(^|\\s)' + CLASS_PREFIX + '-\\S+', 'g')) || []).join(' ');
- }
}, {
key: 'cleanupTether',
value: function cleanupTether() {
- if (this.tether) {
- this.tether.destroy();
+ if (this._tether) {
+ this._tether.destroy();
// clean up after tether's junk classes
// remove after they fix issue
// (https://github.com/HubSpot/tether/issues/36)
- $(this.element).removeClass(this.removeTetherClasses);
- $(this.tip).removeClass(this.removeTetherClasses);
+ $(this.element).removeClass(this._removeTetherClasses);
+ $(this.tip).removeClass(this._removeTetherClasses);
}
}
}, {
- key: '_setListeners',
+ key: '_getAttachment',
// private
+ value: function _getAttachment(placement) {
+ return AttachmentMap[placement.toUpperCase()];
+ }
+ }, {
+ key: '_setListeners',
value: function _setListeners() {
var _this4 = this;
@@ -402,10 +339,10 @@ var ToolTip = (function ($) {
triggers.forEach(function (trigger) {
if (trigger === 'click') {
- $(_this4.element).on(Event.CLICK, _this4.config.selector, _this4.toggle.bind(_this4));
- } else if (trigger !== 'manual') {
- var eventIn = trigger == 'hover' ? Event.MOUSEENTER : Event.FOCUSIN;
- var eventOut = trigger == 'hover' ? Event.MOUSELEAVE : Event.FOCUSOUT;
+ $(_this4.element).on(_this4.constructor.Event.CLICK, _this4.config.selector, _this4.toggle.bind(_this4));
+ } else if (trigger !== Trigger.MANUAL) {
+ var eventIn = trigger == Trigger.HOVER ? _this4.constructor.Event.MOUSEENTER : _this4.constructor.Event.FOCUSIN;
+ var eventOut = trigger == Trigger.HOVER ? _this4.constructor.Event.MOUSELEAVE : _this4.constructor.Event.FOCUSOUT;
$(_this4.element).on(eventIn, _this4.config.selector, _this4._enter.bind(_this4)).on(eventOut, _this4.config.selector, _this4._leave.bind(_this4));
}
@@ -420,6 +357,11 @@ var ToolTip = (function ($) {
this._fixTitle();
}
}
+ }, {
+ key: '_removeTetherClasses',
+ value: function _removeTetherClasses(i, css) {
+ return ((css.baseVal || css).match(new RegExp('(^|\\s)' + CLASS_PREFIX + '-\\S+', 'g')) || []).join(' ');
+ }
}, {
key: '_fixTitle',
value: function _fixTitle() {
@@ -432,19 +374,21 @@ var ToolTip = (function ($) {
}, {
key: '_enter',
value: function _enter(event, context) {
- context = context || $(event.currentTarget).data(DATA_KEY);
+ var dataKey = this.constructor.DATA_KEY;
+
+ context = context || $(event.currentTarget).data(dataKey);
if (!context) {
context = new this.constructor(event.currentTarget, this._getDelegateConfig());
- $(event.currentTarget).data(DATA_KEY, context);
+ $(event.currentTarget).data(dataKey, context);
}
if (event) {
- context._activeTrigger[event.type == 'focusin' ? 'focus' : 'hover'] = true;
+ context._activeTrigger[event.type == 'focusin' ? Trigger.FOCUS : Trigger.HOVER] = true;
}
- if ($(context.getTipElement()).hasClass('in') || context._hoverState === 'in') {
- context._hoverState = 'in';
+ if ($(context.getTipElement()).hasClass(ClassName.IN) || context._hoverState === HoverState.IN) {
+ context._hoverState = HoverState.IN;
return;
}
@@ -466,15 +410,17 @@ var ToolTip = (function ($) {
}, {
key: '_leave',
value: function _leave(event, context) {
- context = context || $(event.currentTarget).data(DATA_KEY);
+ var dataKey = this.constructor.DATA_KEY;
+
+ context = context || $(event.currentTarget).data(dataKey);
if (!context) {
context = new this.constructor(event.currentTarget, this._getDelegateConfig());
- $(event.currentTarget).data(DATA_KEY, context);
+ $(event.currentTarget).data(dataKey, context);
}
if (event) {
- context._activeTrigger[event.type == 'focusout' ? 'focus' : 'hover'] = false;
+ context._activeTrigger[event.type == 'focusout' ? Trigger.FOCUS : Trigger.HOVER] = false;
}
if (context._isWithActiveTrigger()) {
@@ -510,12 +456,12 @@ var ToolTip = (function ($) {
}, {
key: '_getConfig',
value: function _getConfig(config) {
- config = $.extend({}, Default, $(this.element).data(), config);
+ config = $.extend({}, this.constructor.Default, $(this.element).data(), config);
if (config.delay && typeof config.delay === 'number') {
config.delay = {
- 'show': config.delay,
- 'hide': config.delay
+ show: config.delay,
+ hide: config.delay
};
}
@@ -529,7 +475,7 @@ var ToolTip = (function ($) {
if (this.config) {
for (var key in this.config) {
var value = this.config[key];
- if (Default[key] !== value) {
+ if (this.constructor.Default[key] !== value) {
config[key] = value;
}
}
@@ -550,6 +496,21 @@ var ToolTip = (function ($) {
get: function () {
return Default;
}
+ }, {
+ key: 'NAME',
+ get: function () {
+ return NAME;
+ }
+ }, {
+ key: 'DATA_KEY',
+ get: function () {
+ return DATA_KEY;
+ }
+ }, {
+ key: 'Event',
+ get: function () {
+ return Event;
+ }
}, {
key: '_jQueryInterface',
diff --git a/js/dist/tooltip.js.map b/js/dist/tooltip.js.map
index b1ef80207..089bef4ad 100644
Binary files a/js/dist/tooltip.js.map and b/js/dist/tooltip.js.map differ
diff --git a/js/popover.js b/js/popover.js
deleted file mode 100644
index 0b0755ee2..000000000
--- a/js/popover.js
+++ /dev/null
@@ -1,108 +0,0 @@
-/* ========================================================================
- * Bootstrap: popover.js v3.3.4
- * http://getbootstrap.com/javascript/#popovers
- * ========================================================================
- * Copyright 2011-2015 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
-
-
-+function ($) {
- 'use strict';
-
- // POPOVER PUBLIC CLASS DEFINITION
- // ===============================
-
- var Popover = function (element, options) {
- this.init('popover', element, options)
- }
-
- if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
-
- Popover.VERSION = '3.3.4'
-
- Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
- placement: 'right',
- trigger: 'click',
- content: '',
- template: ''
- })
-
-
- // NOTE: POPOVER EXTENDS tooltip.js
- // ================================
-
- Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
-
- Popover.prototype.constructor = Popover
-
- Popover.prototype.getDefaults = function () {
- return Popover.DEFAULTS
- }
-
- Popover.prototype.setContent = function () {
- var $tip = this.tip()
- var title = this.getTitle()
- var content = this.getContent()
-
- $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
- $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
- this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
- ](content)
-
- $tip.removeClass('fade top bottom left right in')
-
- // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
- // this manually by checking the contents.
- if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
- }
-
- Popover.prototype.hasContent = function () {
- return this.getTitle() || this.getContent()
- }
-
- Popover.prototype.getContent = function () {
- var $e = this.$element
- var o = this.options
-
- return $e.attr('data-content')
- || (typeof o.content == 'function' ?
- o.content.call($e[0]) :
- o.content)
- }
-
- Popover.prototype.arrow = function () {
- return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
- }
-
-
- // POPOVER PLUGIN DEFINITION
- // =========================
-
- function Plugin(option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.popover')
- var options = typeof option == 'object' && option
-
- if (!data && /destroy|hide/.test(option)) return
- if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
- if (typeof option == 'string') data[option]()
- })
- }
-
- var old = $.fn.popover
-
- $.fn.popover = Plugin
- $.fn.popover.Constructor = Popover
-
-
- // POPOVER NO CONFLICT
- // ===================
-
- $.fn.popover.noConflict = function () {
- $.fn.popover = old
- return this
- }
-
-}(jQuery);
diff --git a/js/src/popover.js b/js/src/popover.js
new file mode 100644
index 000000000..6b14a2983
--- /dev/null
+++ b/js/src/popover.js
@@ -0,0 +1,178 @@
+import Tooltip from './tooltip'
+
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0): popover.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+const Popover = (($) => {
+
+
+ /**
+ * ------------------------------------------------------------------------
+ * Constants
+ * ------------------------------------------------------------------------
+ */
+
+ const NAME = 'popover'
+ const VERSION = '4.0.0'
+ const DATA_KEY = 'bs.popover'
+ const JQUERY_NO_CONFLICT = $.fn[NAME]
+
+ const Default = $.extend({}, Tooltip.Default, {
+ placement : 'right',
+ trigger : 'click',
+ content : '',
+ template : ''
+ })
+
+ const ClassName = {
+ FADE : 'fade',
+ IN : 'in'
+ }
+
+ const Selector = {
+ TITLE : '.popover-title',
+ CONTENT : '.popover-content',
+ ARROW : '.popover-arrow'
+ }
+
+ const Event = {
+ HIDE : 'hide.bs.popover',
+ HIDDEN : 'hidden.bs.popover',
+ SHOW : 'show.bs.popover',
+ SHOWN : 'shown.bs.popover',
+ INSERTED : 'inserted.bs.popover',
+ CLICK : 'click.bs.popover',
+ FOCUSIN : 'focusin.bs.popover',
+ FOCUSOUT : 'focusout.bs.popover',
+ MOUSEENTER : 'mouseenter.bs.popover',
+ MOUSELEAVE : 'mouseleave.bs.popover'
+ }
+
+
+ /**
+ * ------------------------------------------------------------------------
+ * Class Definition
+ * ------------------------------------------------------------------------
+ */
+
+ class Popover extends Tooltip {
+
+
+ // getters
+
+ static get VERSION() {
+ return VERSION
+ }
+
+ static get Default() {
+ return Default
+ }
+
+ static get NAME() {
+ return NAME
+ }
+
+ static get DATA_KEY() {
+ return DATA_KEY
+ }
+
+ static get Event() {
+ return Event
+ }
+
+
+ // overrides
+
+ isWithContent() {
+ return this.getTitle() || this._getContent()
+ }
+
+ getTipElement() {
+ return (this.tip = this.tip || $(this.config.template)[0])
+ }
+
+ setContent() {
+ let tip = this.getTipElement()
+ let title = this.getTitle()
+ let content = this._getContent()
+ let titleElement = $(tip).find(Selector.TITLE)[0]
+
+ if (titleElement) {
+ titleElement[
+ this.config.html ? 'innerHTML' : 'innerText'
+ ] = title
+ }
+
+ // we use append for html objects to maintain js events
+ $(tip).find(Selector.CONTENT).children().detach().end()[
+ this.config.html ?
+ (typeof content === 'string' ? 'html' : 'append') : 'text'
+ ](content)
+
+ $(tip)
+ .removeClass(ClassName.FADE)
+ .removeClass(ClassName.IN)
+
+ this.cleanupTether()
+ }
+
+ // private
+
+ _getContent() {
+ return this.element.getAttribute('data-content')
+ || (typeof this.config.content == 'function' ?
+ this.config.content.call(this.element) :
+ this.config.content)
+ }
+
+
+ // static
+
+ static _jQueryInterface(config) {
+ return this.each(function () {
+ let data = $(this).data(DATA_KEY)
+ let _config = typeof config === 'object' ? config : null
+
+ if (!data && /destroy|hide/.test(config)) {
+ return
+ }
+
+ if (!data) {
+ data = new Popover(this, _config)
+ $(this).data(DATA_KEY, data)
+ }
+
+ if (typeof config === 'string') {
+ data[config]()
+ }
+ })
+ }
+ }
+
+
+ /**
+ * ------------------------------------------------------------------------
+ * jQuery
+ * ------------------------------------------------------------------------
+ */
+
+ $.fn[NAME] = Popover._jQueryInterface
+ $.fn[NAME].Constructor = Popover
+ $.fn[NAME].noConflict = function () {
+ $.fn[NAME] = JQUERY_NO_CONFLICT
+ return Popover._jQueryInterface
+ }
+
+ return Popover
+
+})(jQuery)
+
+export default Popover
diff --git a/js/src/scrollspy.js b/js/src/scrollspy.js
index 0ab8804c6..e41a3ae12 100644
--- a/js/src/scrollspy.js
+++ b/js/src/scrollspy.js
@@ -55,7 +55,7 @@ const ScrollSpy = (($) => {
constructor(element, config) {
this._scrollElement = element.tagName === 'BODY' ? window : element
- this._config = $.extend({}, Defaults, config)
+ this._config = $.extend({}, Default, config)
this._selector = `${this._config.target || ''} .nav li > a`
this._offsets = []
this._targets = []
diff --git a/js/src/tooltip.js b/js/src/tooltip.js
index 4c09a5baf..a04085130 100644
--- a/js/src/tooltip.js
+++ b/js/src/tooltip.js
@@ -8,7 +8,7 @@ import Util from './util'
* --------------------------------------------------------------------------
*/
-const ToolTip = (($) => {
+const Tooltip = (($) => {
/**
@@ -34,33 +34,16 @@ const ToolTip = (($) => {
delay : 0,
html : false,
selector : false,
- attachment : 'top',
+ placement : 'top',
offset : '0 0',
constraints : null
}
- const HorizontalMirror = {
- LEFT : 'right',
- CENTER : 'center',
- RIGHT : 'left'
- }
-
- const VerticalMirror = {
- TOP : 'bottom',
- MIDDLE : 'middle',
- BOTTOM : 'top'
- }
-
- const VerticalDefault = {
- LEFT : 'middle',
- CENTER : 'bottom',
- RIGHT : 'middle'
- }
-
- const HorizontalDefault = {
- TOP : 'center',
- MIDDLE : 'left',
- BOTTOM : 'center'
+ const AttachmentMap = {
+ TOP : 'bottom center',
+ RIGHT : 'middle left',
+ BOTTOM : 'top center',
+ LEFT : 'middle right'
}
const HoverState = {
@@ -88,8 +71,7 @@ const ToolTip = (($) => {
const Selector = {
TOOLTIP : '.tooltip',
- TOOLTIP_INNER : '.tooltip-inner',
- TOOLTIP_ARROW : '.tooltip-arrow'
+ TOOLTIP_INNER : '.tooltip-inner'
}
const TetherClass = {
@@ -120,12 +102,12 @@ const ToolTip = (($) => {
this._timeout = 0
this._hoverState = ''
this._activeTrigger = {}
+ this._tether = null
// protected
this.element = element
this.config = this._getConfig(config)
this.tip = null
- this.tether = null
this._setListeners()
@@ -142,6 +124,19 @@ const ToolTip = (($) => {
return Default
}
+ static get NAME() {
+ return NAME
+ }
+
+ static get DATA_KEY() {
+ return DATA_KEY
+ }
+
+ static get Event() {
+ return Event
+ }
+
+
// public
@@ -159,16 +154,17 @@ const ToolTip = (($) => {
toggle(event) {
let context = this
+ let dataKey = this.constructor.DATA_KEY
if (event) {
- context = $(event.currentTarget).data(DATA_KEY)
+ context = $(event.currentTarget).data(dataKey)
if (!context) {
context = new this.constructor(
event.currentTarget,
this._getDelegateConfig()
)
- $(event.currentTarget).data(DATA_KEY, context)
+ $(event.currentTarget).data(dataKey, context)
}
context._activeTrigger.click = !context._activeTrigger.click
@@ -190,13 +186,19 @@ const ToolTip = (($) => {
clearTimeout(this._timeout)
this.hide(() => {
$(this.element)
- .off(Selector.TOOLTIP)
- .removeData(DATA_KEY)
+ .off(`.${this.constructor.NAME}`)
+ .removeData(this.constructor.DATA_KEY)
+
+ if (this.tip) {
+ $(this.tip).detach()
+ }
+
+ this.tip = null
})
}
show() {
- let showEvent = $.Event(Event.SHOW)
+ let showEvent = $.Event(this.constructor.Event.SHOW)
if (this.isWithContent() && this._isEnabled) {
$(this.element).trigger(showEvent)
@@ -211,7 +213,7 @@ const ToolTip = (($) => {
}
let tip = this.getTipElement()
- let tipId = Util.getUID(NAME)
+ let tipId = Util.getUID(this.constructor.NAME)
tip.setAttribute('id', tipId)
this.element.setAttribute('aria-describedby', tipId)
@@ -222,19 +224,20 @@ const ToolTip = (($) => {
$(tip).addClass(ClassName.FADE)
}
- let attachment = typeof this.config.attachment === 'function' ?
- this.config.attachment.call(this, tip, this.element) :
- this.config.attachment
+ let placement = typeof this.config.placement === 'function' ?
+ this.config.placement.call(this, tip, this.element) :
+ this.config.placement
- attachment = this.getAttachment(attachment)
+ let attachment = this._getAttachment(placement)
- $(tip).data(DATA_KEY, this)
+ $(tip)
+ .data(this.constructor.DATA_KEY, this)
+ .appendTo(document.body)
- this.element.parentNode.insertBefore(tip, this.element.nextSibling)
- $(this.element).trigger(Event.INSERTED)
+ $(this.element).trigger(this.constructor.Event.INSERTED)
- this.tether = new Tether({
- element : this.tip,
+ this._tether = new Tether({
+ element : tip,
target : this.element,
attachment : attachment,
classes : TetherClass,
@@ -244,7 +247,7 @@ const ToolTip = (($) => {
})
Util.reflow(tip)
- this.tether.position()
+ this._tether.position()
$(tip).addClass(ClassName.IN)
@@ -252,7 +255,7 @@ const ToolTip = (($) => {
let prevHoverState = this._hoverState
this._hoverState = null
- $(this.element).trigger(Event.SHOWN)
+ $(this.element).trigger(this.constructor.Event.SHOWN)
if (prevHoverState === HoverState.OUT) {
this._leave(null, this)
@@ -269,14 +272,14 @@ const ToolTip = (($) => {
hide(callback) {
let tip = this.getTipElement()
- let hideEvent = $.Event(Event.HIDE)
+ let hideEvent = $.Event(this.constructor.Event.HIDE)
let complete = () => {
if (this._hoverState !== HoverState.IN && tip.parentNode) {
tip.parentNode.removeChild(tip)
}
this.element.removeAttribute('aria-describedby')
- $(this.element).trigger(Event.HIDDEN)
+ $(this.element).trigger(this.constructor.Event.HIDDEN)
this.cleanupTether()
if (callback) {
@@ -317,47 +320,6 @@ const ToolTip = (($) => {
return (this.tip = this.tip || $(this.config.template)[0])
}
- getAttachment(attachmentString) {
- let attachmentArray = attachmentString.split(' ')
- let normalizedAttachment = {}
-
- if (!attachmentArray.length) {
- throw new Error('Tooltip requires attachment')
- }
-
- for (let attachment of attachmentArray) {
- attachment = attachment.toUpperCase()
-
- if (HorizontalMirror[attachment]) {
- normalizedAttachment.horizontal = HorizontalMirror[attachment]
- }
-
- if (VerticalMirror[attachment]) {
- normalizedAttachment.vertical = VerticalMirror[attachment]
- }
- }
-
- if (!normalizedAttachment.horizontal &&
- (!normalizedAttachment.vertical)) {
- throw new Error('Tooltip requires valid attachment')
- }
-
- if (!normalizedAttachment.horizontal) {
- normalizedAttachment.horizontal =
- HorizontalDefault[normalizedAttachment.vertical.toUpperCase()]
- }
-
- if (!normalizedAttachment.vertical) {
- normalizedAttachment.vertical =
- VerticalDefault[normalizedAttachment.horizontal.toUpperCase()]
- }
-
- return [
- normalizedAttachment.vertical,
- normalizedAttachment.horizontal
- ].join(' ')
- }
-
setContent() {
let tip = this.getTipElement()
let title = this.getTitle()
@@ -384,43 +346,43 @@ const ToolTip = (($) => {
return title
}
- removeTetherClasses(i, css) {
- return ((css.baseVal || css).match(
- new RegExp(`(^|\\s)${CLASS_PREFIX}-\\S+`, 'g')) || []
- ).join(' ')
- }
-
cleanupTether() {
- if (this.tether) {
- this.tether.destroy()
+ if (this._tether) {
+ this._tether.destroy()
// clean up after tether's junk classes
// remove after they fix issue
// (https://github.com/HubSpot/tether/issues/36)
- $(this.element).removeClass(this.removeTetherClasses)
- $(this.tip).removeClass(this.removeTetherClasses)
+ $(this.element).removeClass(this._removeTetherClasses)
+ $(this.tip).removeClass(this._removeTetherClasses)
}
}
// private
+ _getAttachment(placement) {
+ return AttachmentMap[placement.toUpperCase()]
+ }
+
_setListeners() {
let triggers = this.config.trigger.split(' ')
triggers.forEach((trigger) => {
if (trigger === 'click') {
$(this.element).on(
- Event.CLICK,
+ this.constructor.Event.CLICK,
this.config.selector,
this.toggle.bind(this)
)
} else if (trigger !== Trigger.MANUAL) {
let eventIn = trigger == Trigger.HOVER ?
- Event.MOUSEENTER : Event.FOCUSIN
+ this.constructor.Event.MOUSEENTER :
+ this.constructor.Event.FOCUSIN
let eventOut = trigger == Trigger.HOVER ?
- Event.MOUSELEAVE : Event.FOCUSOUT
+ this.constructor.Event.MOUSELEAVE :
+ this.constructor.Event.FOCUSOUT
$(this.element)
.on(
@@ -446,6 +408,12 @@ const ToolTip = (($) => {
}
}
+ _removeTetherClasses(i, css) {
+ return ((css.baseVal || css).match(
+ new RegExp(`(^|\\s)${CLASS_PREFIX}-\\S+`, 'g')) || []
+ ).join(' ')
+ }
+
_fixTitle() {
let titleType = typeof this.element.getAttribute('data-original-title')
if (this.element.getAttribute('title') ||
@@ -459,14 +427,16 @@ const ToolTip = (($) => {
}
_enter(event, context) {
- context = context || $(event.currentTarget).data(DATA_KEY)
+ let dataKey = this.constructor.DATA_KEY
+
+ context = context || $(event.currentTarget).data(dataKey)
if (!context) {
context = new this.constructor(
event.currentTarget,
this._getDelegateConfig()
)
- $(event.currentTarget).data(DATA_KEY, context)
+ $(event.currentTarget).data(dataKey, context)
}
if (event) {
@@ -498,19 +468,21 @@ const ToolTip = (($) => {
}
_leave(event, context) {
- context = context || $(event.currentTarget).data(DATA_KEY)
+ let dataKey = this.constructor.DATA_KEY
+
+ context = context || $(event.currentTarget).data(dataKey)
if (!context) {
context = new this.constructor(
event.currentTarget,
this._getDelegateConfig()
)
- $(event.currentTarget).data(DATA_KEY, context)
+ $(event.currentTarget).data(dataKey, context)
}
if (event) {
context._activeTrigger[
- event.type == 'focusout' ? Triger.FOCUS : Trigger.HOVER
+ event.type == 'focusout' ? Trigger.FOCUS : Trigger.HOVER
] = false
}
@@ -545,7 +517,12 @@ const ToolTip = (($) => {
}
_getConfig(config) {
- config = $.extend({}, Default, $(this.element).data(), config)
+ config = $.extend(
+ {},
+ this.constructor.Default,
+ $(this.element).data(),
+ config
+ )
if (config.delay && typeof config.delay === 'number') {
config.delay = {
@@ -563,7 +540,7 @@ const ToolTip = (($) => {
if (this.config) {
for (let key in this.config) {
let value = this.config[key]
- if (Default[key] !== value) {
+ if (this.constructor.Default[key] !== value) {
config[key] = value
}
}
diff --git a/js/tests/index.html b/js/tests/index.html
index 2491d8d86..0e2bdd012 100644
--- a/js/tests/index.html
+++ b/js/tests/index.html
@@ -141,11 +141,9 @@
+
-
-
-
-
@@ -153,9 +151,9 @@
- -->
+
-
+
diff --git a/js/tests/unit/popover.js b/js/tests/unit/popover.js
index a25df3a58..01c6a97cb 100644
--- a/js/tests/unit/popover.js
+++ b/js/tests/unit/popover.js
@@ -16,6 +16,7 @@ $(function () {
afterEach: function () {
$.fn.popover = $.fn.bootstrapPopover
delete $.fn.bootstrapPopover
+ $('.popover').remove()
}
})
@@ -81,6 +82,7 @@ $(function () {
assert.strictEqual($('.popover .popover-content').text(), 'loves writing tests (╯°□°)╯︵ ┻━┻', 'content correctly inserted')
$popover.bootstrapPopover('hide')
+
assert.strictEqual($('.popover').length, 0, 'popover was removed')
})
@@ -91,6 +93,7 @@ $(function () {
var $popover = $('@fat')
.appendTo('#qunit-fixture')
.bootstrapPopover({
+ html: true,
content: function () {
return $div
}
@@ -98,14 +101,14 @@ $(function () {
$popover.bootstrapPopover('show')
assert.notEqual($('.popover').length, 0, 'popover was inserted')
- assert.equal($('.popover .popover-content').html(), $div, 'content correctly inserted')
+ assert.equal($('.popover .popover-content').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, 'content correctly inserted')
+ assert.equal($('.popover .popover-content').html(), $div[0].outerHTML, 'content correctly inserted')
$popover.bootstrapPopover('hide')
assert.strictEqual($('.popover').length, 0, 'popover was removed')
@@ -126,7 +129,6 @@ $(function () {
assert.strictEqual($('.popover').length, 0, 'popover was removed')
})
-
QUnit.test('should get title and content from attributes ignoring options passed via js', function (assert) {
assert.expect(4)
var $popover = $('@mdo')
@@ -240,13 +242,6 @@ $(function () {
.bootstrapPopover('show')
})
- QUnit.test('should throw an error when initializing popover on the document object without specifying a delegation selector', function (assert) {
- assert.expect(1)
- assert.throws(function () {
- $(document).bootstrapPopover({ title: 'What am I on?', content: 'My selector is missing' })
- }, new Error('`selector` option must be specified when initializing popover on the window.document object!'))
- })
-
QUnit.test('should do nothing when an attempt is made to hide an uninitialized popover', function (assert) {
assert.expect(1)
@@ -259,16 +254,6 @@ $(function () {
assert.strictEqual($popover.data('bs.popover'), undefined, 'should not initialize the popover')
})
- QUnit.test('should throw an error when template contains multiple top-level elements', function (assert) {
- assert.expect(1)
- assert.throws(function () {
- $('some text')
- .appendTo('#qunit-fixture')
- .bootstrapPopover({ template: 'Foo
Bar
' })
- .bootstrapPopover('show')
- }, new Error('popover `template` option must consist of exactly 1 top-level element!'))
- })
-
QUnit.test('should fire inserted event', function (assert) {
assert.expect(2)
var done = assert.async()
diff --git a/js/tests/unit/tooltip.js b/js/tests/unit/tooltip.js
index 8f2cbc3e8..f3df4d828 100644
--- a/js/tests/unit/tooltip.js
+++ b/js/tests/unit/tooltip.js
@@ -89,11 +89,11 @@ $(function () {
assert.strictEqual(id.indexOf('tooltip'), 0, 'tooltip id has prefix')
})
- QUnit.test('should place tooltips relative to attachment option', function (assert) {
+ QUnit.test('should place tooltips relative to placement option', function (assert) {
assert.expect(2)
var $tooltip = $('')
.appendTo('#qunit-fixture')
- .bootstrapTooltip({ attachment: 'bottom' })
+ .bootstrapTooltip({ placement: 'bottom' })
$tooltip.bootstrapTooltip('show')
@@ -321,7 +321,7 @@ $(function () {
var $target = $('')
.appendTo($container)
.bootstrapTooltip({
- attachment: 'right',
+ placement: 'right',
})
.bootstrapTooltip('show')
@@ -389,7 +389,7 @@ $(function () {
.one('show.bs.tooltip', function () {
$(this).remove()
})
- .bootstrapTooltip({ attachment: 'top' })
+ .bootstrapTooltip({ placement: 'top' })
try {
$tooltip.bootstrapTooltip('show')
@@ -426,7 +426,7 @@ $(function () {
.find('a')
.css('margin-top', 200)
.bootstrapTooltip({
- attachment: 'top',
+ placement: 'top',
animate: false
})
.bootstrapTooltip('show')
@@ -609,7 +609,7 @@ $(function () {
assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom')
done()
})
- .bootstrapTooltip({ attachment: 'top', trigger: 'manual' })
+ .bootstrapTooltip({ placement: 'top', trigger: 'manual' })
$circle.bootstrapTooltip('show')
})
@@ -621,7 +621,7 @@ $(function () {
return '' + uid + '
' + uid + '
' + uid + '
'
}
- var $tooltip = $('some text')
+ var $tooltip = $('some text')
.appendTo('#qunit-fixture')
$tooltip.bootstrapTooltip({
@@ -649,7 +649,7 @@ $(function () {
return '' + uid + '
' + uid + '
' + uid + '
'
}
- var $tooltip = $('some text')
+ var $tooltip = $('some text')
.appendTo('#qunit-fixture')
$tooltip.bootstrapTooltip({
diff --git a/js/tests/visual/popover.html b/js/tests/visual/popover.html
index 0e84f5cee..ac6557256 100644
--- a/js/tests/visual/popover.html
+++ b/js/tests/visual/popover.html
@@ -5,7 +5,7 @@
Popover
-
+
@@ -39,9 +39,11 @@
-
-
-
+
+
+
+
+