From a58febf71a5eac2161ce2db08c7d723755ed1163 Mon Sep 17 00:00:00 2001 From: fat Date: Tue, 12 May 2015 14:28:11 -0700 Subject: [PATCH] popover passing as well --- Gruntfile.js | 3 +- dist/css/bootstrap.css | 134 ++++----- dist/css/bootstrap.css.map | Bin 112623 -> 113126 bytes js/dist/popover.js | 189 +++++++++++++ js/dist/popover.js.map | Bin 0 -> 7682 bytes js/dist/scrollspy.js | 2 +- js/dist/scrollspy.js.map | Bin 13345 -> 13344 bytes js/dist/tooltip.js | 221 +++++++-------- js/dist/tooltip.js.map | Bin 28800 -> 27873 bytes js/popover.js | 108 -------- js/src/popover.js | 178 ++++++++++++ js/src/scrollspy.js | 2 +- js/src/tooltip.js | 191 ++++++------- js/tests/index.html | 10 +- js/tests/unit/popover.js | 25 +- js/tests/unit/tooltip.js | 16 +- js/tests/visual/popover.html | 10 +- js/tooltip.js | 514 ----------------------------------- scss/_popover.scss | 150 +++++----- 19 files changed, 724 insertions(+), 1029 deletions(-) create mode 100644 js/dist/popover.js create mode 100644 js/dist/popover.js.map delete mode 100644 js/popover.js create mode 100644 js/src/popover.js delete mode 100644 js/tooltip.js 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 dae2dfaf92a3cfc8ec4f3aab348b0af590ca7927..e21e231a9776f41a995b3a52058587a5081092c6 100644 GIT binary patch delta 1515 zcmai!&rcIU6vs1(av%XUvGGTU(HKmmV`?b^&7NkbWi3#kmhP`xsX|M)Ek70%544pK zF($;wVb0vWm|!?@^8euA!7B&<0pHv0F4KmDUbee$=DqLx%=gX3Mc?0leXSEB_K$x2 z=|4T*CvV8jG<&Hoh_hWXGW=S}Fka`hz*vE%9lm3~SLqC68LCxz+@6B4wkBwkWSbZq z^@0sm$yWIXdm}|NxHQdJnriS*$uh1}gE0ehZP}aBau=7csEnwuD#8@ zw;BX78~0PrE<(!e63sCt;!P4cy0zQihgHfcG20|VO$I-jWh@IjQmZK?$M~H8eklsR z*`cVY1tqXSC0FH1%i(k$H26hfi-s9&N#~|j@|wiu8@L=bhbqOxucZG*ni;krEiyV3 zw7za_sXiOP=vuRgQ8Zd)Y1!coYh1!ow*X5(zlPgDoDbN+P!-BmJz_Ob5(0B909Jum zr3cu82TZKD$b;K7q=U$ul=#-_MHb^SGKY_uo%6?j6DIWAbHac}zY^J{(5h*L$W}2$ zm(GFC$-Y%QZ1Ziv7W7}i>Rv&>=9qIHwzD>w1M^kPNr_F_yvBS{LpER1kjxkO3!$v} zCd31E_@q(v38VSz=0~u3V7}jN66xVtPl@w(FVAF$CrpDT%>__f3@x~2NEURBYb+S5 zg&bXK$8`f)4SJ*M7zxz}`u!7$J%*ft6~}dHqLcbGGOY`;M;?jkCK(WPkKAp#9AVfv z#IkJowupY5K{{jlm~;RMUGnXyF8el)p}-EIe8}ahp%ondQhyi1PVkr>_h{QV>N(%I zMaGJF5pY^!tkiAh)s%R$M~3pD!*Tx0o%#0_`#!@#XWZ=E2@bCXIMCpZeg%ASd`KeC zU{jaeokB5mX0iaV70|RSetjl0(IkfnMcXRrDv$D*D%~HILPN!Q$zrTr5YYoNGN?_c z)ax!?;Zg0hbU=p5z5I@s1eSyQCh`f6CA6udpD!Zfd@K+gEJv~1p Hcb@+T1W>cK delta 1463 zcmai!O-~b16ozvb;8&tC2BRzE!f5Oz<*QcG#CYy?tj$;}w)4TPL_jDrP>@2Ui76X4 zE&$WT#JFurv66C8MGz6~zl<90ah_4^8hgU^jaMj4F%ZxZK9k6@sn!lrppd2U8`|+nk z_O#=-bY*(C?XN2e_G`_oh!FZX7SONE30}rl)VJYh1UYU9YP{yRpXqTGWBiillP*v2 zh5nc!Um-co@I((0`sivEpDSuYe^RQaRh*EnjPUXzyu=xyj2_gDlDqED(HotdD3n0H z>N(R=Y>)4Pe)}p=^6iNysX?I<_ckwL#TOh@*a)^yKcWpJl?;ftj+Vl;VYF z2w)mv6U7vjT8~sDH@vzWKwS5bN)pe8H(>x8#r2Z@h0gr0vx%`_{V2}a zu$vu(fw|Q%BH407WAJVFKk3' + '
' + '

' + '
' + }); + + 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 0000000000000000000000000000000000000000..c6865e239fdf7fb142c2f11e84eb0f77dea964db GIT binary patch literal 7682 zcmcIpe{<7F68$Q3E^2MFLgp5>s7*F|HI@bVLShm-WJ8ilDYhId*piXP0T%e~_qu0B zBijncA7BbIn(2An{rbm@%;&~koEJ%!Hg=wPjUrp+{`&+YG!Lg(>&XnS|uU)zU-8WqV`nU7+g{PxH)4y|+*QKH2Nq0-f zK7m?W-3#I9skB$#k%5rRy+p#v%1$^79D4^g_ zF`IIMrRFind*8Af?TDfIi|u4+wuqhNk)7-7CP%KB{$PvT*DTv1#OP=fiX5x5viPaK{Gy)?4Nkl7q~>PF6n|BoO&_-~pRwGHFtsqFL;CWPI@85mP5vdG+G zreNb#hTkbRCUzMNCBR_TU%!@;7A6kgUI!D0Fbr&m40V!H}&Qot+j?yz~IPd80LeT$$(-1D=ybf5CS61A3$#Rt9aWHTi&)JKth!5Wz?R&Ydl2@a<9~ZQ+w9u9 zWtUGcT!Fr0vuO+nl1)?O7kv4)&GtG+jIc7?pkRh8=yg}nHee0Q>ZqW(I$60J$Z*Qb z^cC6`u5FMFuQ5&LG2S<}Urow4mmo`3oGN;ONfyg2S7MZ9bCoQ`G|v{I>35WVZeFDH zr}OaPMJgVOM?dVtaNR6Zh03F)Xx%;aAN!BnJHow5vB;}r9H&J*5vz0(=i;D060Mn1 z%VMX~xk=P)b?uL{MMr(OE;`p1u5&%lt~-mUP;uUQ)epkMVc7l&4s?i{ah4WJyw)#( zVo$VM587hyFY#GZCxj+X{6PBP3c(?Yg^E&DnCBlA91X|L38CFPlm{Vnu6_1I(*z4y zVg=uX$HV^Ma8r<@TM_HYk-XXu&#H33yDt1~$p0RlgvV!Bhl8tNaQGbI90}0;z@Mh) zWY#6|Y}NPTX|$RvUXMQ_$0x1NUp<@MzFGDtIHYEQJQ=^UD-v+Tn?LK?~n)j{>qy^cp=PeUc>hPjF-HE;oHW52YYleR|c`5-tMQdHQoX*OOJ zNu64j8=Ron$T*hER;mW@U~n=F5tQ(l1Q*$=h(RlU4BIA;MPG&T4W|i<&g1BAjc3X* zP7@mZyxvLKE6@*;G*S3nkE{O29dH`Xwouk(PYB(X3fq(1IRS4w;wDz04jr8l1p2#5 z#xyHTXKl4@wF!~OYL%yUMei^bCaPOa+pF1XR_@$PkD4Yo=S_P~G%wrdk1y#?f{zPXMZb&k9Kk2F@?$h?n540U z(BkmS%2&nN;i{x*o?6yO*6>h)H5|ZC_?9f&K1yiPvc25r7EaFD6c!?x3P?h=*;>h9 z0ngmRxwVYUVL~-;{!A_A;y-kXq;dXobnvQ4t%jdQsHe(7dP)5A!N=5A$mR0-5DT;? zfgj~@H4syrJq(>)-{K@Hgv!JsN>YWt;ZL z8qYAG>qood)V51ihg<5?GR~%Szi%jKvmtpY?;00 zpe7o%)lQF}#|u;ppWdzV4EO2iHt9&a?vd&rR*?ea$G)oXS{&Z%{%xH%-TdnIXcgz5`gBN6aRH^Mp*vK{VvP>U zCF_EywjN!SL<~IPaztZ8`eCAF`)q|NY7AFe6%|RDY)~yY*K`$7t{JHvk*?-*Yd!Hr zrTj0}_{%S%gPyDM?9&&zDs_B?C+kYZ7uu%%aU_-qNyh zPV;T&JwX^1xh=glESQR`G3H#;a%t0?j0Yn9gMo{`X*#s>)9x=ig;@Ddy0y3$EbXBA z-m}5*H`ADmahv>r-cIwCx!{}I&xTBzL28P(E4)taiJByLcv# a'; this._offsets = []; this._targets = []; diff --git a/js/dist/scrollspy.js.map b/js/dist/scrollspy.js.map index cf1c3ce1a1b64b7a21d033a9adc5ee566394f29a..46c0410a0af4ca548c8f80ea105704bedc0e6940 100644 GIT binary patch delta 28 kcmZ3Ou^?lEH8YF9qoe<1du9p7yv-5Jzoj;Z$ek4h0FBcLssI20 delta 30 mcmZ3Gu`pwUH8V?~qhsJ?du9p7g3S@kzoi(9HwVj|6$JpGI0_>G 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 b1ef80207a61a6c2f0baf9e4766679d836f9269b..089bef4ad9937d82d89c572b8167716a983800d4 100644 GIT binary patch delta 4015 zcmb_dYfM|`8P+*Kh+VGX76(!exCwSSF`;Rrg42@E$H!cZaT72!2?h@K0oxecH3te! zBYKg#A5+wJuO{_Jt0c>hRodF7JJY6Uf7)%8HceBeN!2o~Q*obfG) z=mqtIHYJ#Q3E^e21#XvBLD#+y;r6~dsHxn4U`igQsCh(mHFyHV%ID$Rm3=}t+^PJ; ziQdybn&of_M$ty0_^04qXQQ~Lz|Z%G;MtyPJICIq$T67fJ_xGqayi8Wn|6o!7n@tO z;VDQn3&NR>hSouht|S!7X@mk%*cJC&XLD?>qazxg8ZZ_phbm3`JS~Z`#fH|BA1yzu zN-C8R?-Z?4f!9S}(Hk==u`q6xfH@{!n5#MkH`?vxEY&AG?f22j?@O?ie>Lf_zOm7~1ZCr`nd zx&|y(Z6~b^zqcshMddPz7O)7X*Zmv?5J-)U@S_87^6p?{M;n}C-fzCp@MGbw3RGa6oFC?!{<%dt(%dN; zesiN)EHj4=-xA?BQX3?@tAzwSU(*cD9nIx9xW&Y2!475-X_n1fq1foy@E4SN4p+lm zOBGCa*f)15VwYt6-Y`)DUiN4tsL4;GJB3an+cB&~kq(`*L3anI)T(ZQW{Zjf0QA_W zphu0U=j09aH;4xUpLYDj$)<+#QYy`sH~ zf@*R4;O(B7$9eV9<)Ed4$HcV%v zZBI9J^c~$p-U9i)EB0Jki|NaH#*m=3KU7T&LyINoIi%&_w6uZHrz$xtK8ERd1tNcj`G2e(-qbrk>`J`=tdf zy`mQ)=oxK3t;f-nNom+i(;4~~%Vt&#X#zbh>Urrg=^}?T6rNPivQUZaS_x?&tVG6{ zcp)2GU9l2SMu(Lk6WKc}67gHuL+Fk#g2*-F1X~Y@V3@xZ{Ae}5p#&Lc%W@PgoDGK*_!keF{r=yJpR%PqCmEdpe8&jiR$KjxLd>%vYkc!&ORq}1Uw$BmqxT_~oykX-bzdw6pA zSOtIk`tYfdq784n5?fkvJ}km!vDl@laTP7y+!U@o**qpm9!j5UNB$PWGDCzWJQDr& zXt|u8iBDu*aco~Yk)HW%d;@jh)`dgxad`hO`Cc87gjslRCr z^pCr+WqvkRwww4*;V(t={izp3`0M%3Lxm~W(%BNHa~2-F@GA`Y#RV_>ZG-i(Du_-y zCih}!$8eN*#O-sTNTtWfMv#oWqOIsIceK#Susr=U2uJtZR*XWw!XwcaYYOYZ!{-^^ zi@Iwq5nmJoK%&j9MI$yGo=`Y4uBu}bxJdfx{T8PUGbirZ!>CFo)$Jb4+>BcU<@{Ub zYjalx_dO0B*13M6uQ+N?&EG7(H!P-{$xN3tVC_N=-*x@PGs_grSO`w5HLx#!6kgG5 zpf~P>oAFxsWHDv_G#>eCpgeWhqIXvi<~J7`#4^kozLWgr@lu0dyi{2CwAXjeg}$Jz zrVW|4dOI5(_ZD^BQ8>7kFSwpcRIDVjPfJk0)Y_0p#&z7{TnAT4THAp7)Dd_&T@PzZ MZ|yP-&UCc=Kid4mp8x;= delta 4966 zcma)8X>1$U5ysLwEcu{i9hPhzD_Pc3_L{V;`cUL+xuhsYqG?H#WYvefBA4XKE0SKW zXpEnH*@6irjObx|M%>eTH9C|aNmT);pOBWVj1sng^~Y!v+ypiO@SMd2dt zytlhtQb%k75|^{{X1@8pnR$BjA@kxR=I-kZvjjh2S{NOE#mv{l1!0m83PKomyM}h8 z{DP43^C3Y94GMy|XAxvI_Rkp z!>cRND@cUm5OKxC-~A;8P%5yhB%G;iHU8@QGqar(nHG5xOERl8`5g?w-HKg1B|(@l z&9qLFk#ZxLn*8iR%OjeR~ zBHV8LPX%EMepl7((nRB(Cf7RO48Mp;MBbW60+_VZfS<=w!n|y?|Cr?fo$Vb5@x2}} z-xDgcX8+P+9m)<_5h%GN41DC>UWk~5P|@g{gBai-oePU@Yyr|j^asHN_&w;c=r@rZ z9wzt*R-f55q}RxR=h0+I>WD!}ClwV@6@r>sYS=EAf^d%5_2W2Q#8+6F<3JU)cyg@t z3I7O#5+V;+%}?CI=58u=J%>!&DUjmQ6l6)5JsBq(t@IQgvJ>%&DA81(k)@vGbXg7IzfRH zR7$87S4_kIwzb2ryEYo{w*0|Wana8ogqp5arVo0$Zo&6jTj6V+oAxG`jkzf@U52DE zQ)Hqk4ygv8wGK3q1+Y*$9jKiaz{SxBTbkX_*wz3)YOb#n)xco1*cK9w_@`~}*E>T- zpAh|N__+PFyNpSnA0i!W3+_&wDCYz%j5Iv_yrY>>;hm1o_BDOzIgq*=T)1U!wznE{ z?2j4aepi8kM;@WjCWUcOd( zWl#kvQo6j$+IgPbg7B~1^=^By3uHm``HjEyeDI8DCd-i=5{>-s2d*Y-Xv{5F)C^A4 zYzN=YO4zrl627%}<2IC$Y;aRr>_hYZ7=XKb&mX&pYSMp0N_|Kr1Y-`@!J6-J<~11g z{tW`Y9#@|qRNs^vl({T4`dECb?=olEqnQF*RdnMgtByuTgwri9Qt9cr0Y^Vy&z|F z_{rf&VK}QP*RmO1QX>jR(b%Kx3uc*)O^}yDG9U>AA1V)1-#DbDYsIqPMM`N*Q zgxK|LZtchcIVmlw`f3%F$8$=U%j$ZTSpasRxv(;@!_A7&vFItH#0nOi5-1B6XHEeY zXDiql&Klnsc+u6xvax7%G!{NJD~yjvr%3{@p3SPdk~3B2p!!HpFDI)qk&r`&q@?C$ zD-kDWq&Zbi6z#^lM{YB4^Vsz|vvKsalK1Meo|ZLm9se!NpZG8Ai|>Np2p#JKLQI$) z3C_SL!u{eG<7fU}*Om#)7uU0z*Fp!M1zO;SQU~7*4j3Njft;ivKPR&Z*{fvo*n56Cnbl+u5@|YmEegFE`HDWF%&AHy1%1(-@Q*MH z?&tSa5T=Y{&+lj8(#S*OtD}EsjIopJ7(Rna{h%V80w6FHs9Y73I8T$2+H5ed@d)_4(5CCPd^m!i@(&gvM!n3O~;!PJ98D?E08Vv@s!`o7Xu=0&$C4A<5 zOV&QaY-v94xwd6(5q7bUb$ z{t^B;If%cl5SrQr52oIR?@!;@z%59bMM>rG2;4i}2!YdeySa20dEwaOb~XZxWrIsN zZQe+9aw2Ho^6=K_{%3F>4GL4_<~D|AdR<1_*;@?koa?KxcXKb?y3hni&fhNHE3hLz z57F7GIxd-wFXqXGWq|^1Hd4VU84e!Idg#Ne7rN=E(RbnAGsL~LGN$p>1v6fEFxDD S@-hc9`q(1(jhEBsD*g|1Qtq$- 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 @@ - - - + + + + +