From de0f48d02dc10e3ab21899ee5405a5a2bdf462ec Mon Sep 17 00:00:00 2001 From: Johann-S Date: Thu, 6 Apr 2017 23:16:07 +0200 Subject: [PATCH 01/26] Use Popper for tooltip and popover --- docs/assets/js/vendor/popper.min.js | 3 ++ docs/assets/js/vendor/tether.min.js | 1 - js/src/popover.js | 2 - js/src/tooltip.js | 73 +++++++++-------------------- js/tests/visual/popover.html | 2 +- js/tests/visual/tooltip.html | 2 +- 6 files changed, 27 insertions(+), 56 deletions(-) create mode 100644 docs/assets/js/vendor/popper.min.js delete mode 100644 docs/assets/js/vendor/tether.min.js diff --git a/docs/assets/js/vendor/popper.min.js b/docs/assets/js/vendor/popper.min.js new file mode 100644 index 000000000000..22ac698abe70 --- /dev/null +++ b/docs/assets/js/vendor/popper.min.js @@ -0,0 +1,3 @@ +(function(e,t){'object'==typeof exports&&'undefined'!=typeof module?module.exports=t():'function'==typeof define&&define.amd?define(t):e.Popper=t()})(this,function(){'use strict';function e(he){const ce=he.offsetParent,ue=ce&&ce.nodeName;return ue&&'BODY'!==ue&&'HTML'!==ue?ce:window.document.documentElement}function t(he,ce){if(1!==he.nodeType)return[];const ue=window.getComputedStyle(he,null);return ce?ue[ce]:ue}function o(he){return'HTML'===he.nodeName?he:he.parentNode||he.host}function r(he){if(!he||-1!==['HTML','BODY','#document'].indexOf(he.nodeName))return window.document.body;const{overflow:ce,overflowX:ue,overflowY:ge}=t(he);return /(auto|scroll)/.test(ce+ge+ue)?he:r(o(he))}function s(he){const ce=he.nodeName;return'BODY'===ce||'HTML'===ce?!1:'fixed'===t(he,'position')||s(o(he))}function p(he){const ce=e(he),ue=s(ce);return ue?'fixed':'absolute'}function f(he,ce){const ue='x'===ce?'Left':'Top',ge='Left'==ue?'Right':'Bottom';return+he[`border${ue}Width`].split('px')[0]+ +he[`border${ge}Width`].split('px')[0]}function d(he){const ce=-1!==navigator.appVersion.indexOf('MSIE 10');let ue;if(ce)try{ue=he.getBoundingClientRect()}catch(xe){ue={}}else ue=he.getBoundingClientRect();const ge={left:ue.left,top:ue.top,right:ue.right,bottom:ue.bottom,width:ue.right-ue.left,height:ue.bottom-ue.top};if('HTML'===he.nodeName&&ce){const{scrollTop:xe,scrollLeft:ye}=window.document.documentElement;ge.top-=xe,ge.bottom-=xe,ge.left-=ye,ge.right-=ye}let be=ue.width-(he.clientWidth||ue.right-ue.left),we=ue.height-(he.clientHeight||ue.bottom-ue.top);if(be||we){const xe=t(he);be-=f(xe,'x'),we-=f(xe,'y')}return ge.right-=be,ge.width-=be,ge.bottom-=we,ge.height-=we,ge}function l(he,ce='top'){const ue='top'===ce?'scrollTop':'scrollLeft',ge=he.nodeName;if('BODY'===ge||'HTML'===ge){const be=window.document.documentElement,we=window.document.scrollingElement||be;return we[ue]}return he[ue]}function m(he,ce,ue=!1){const ge=l(ce,'top'),be=l(ce,'left'),we=ue?-1:1;return he.top+=ge*we,he.bottom+=ge*we,he.left+=be*we,he.right+=be*we,he}function h(he,ce,ue=!1,ge=!1){const be=r(ce),we=d(he),xe=d(ce);let ye={top:we.top-xe.top,left:we.left-xe.left,bottom:we.top-xe.top+we.height,right:we.left-xe.left+we.width,width:we.width,height:we.height};ue&&!ge?ye=m(ye,be,!0):e(he).contains(be)&&'BODY'!==be.nodeName&&(ye=m(ye,ce));const ve=t(ce),Oe=+ve.borderTopWidth.split('px')[0],Ee=+ve.borderLeftWidth.split('px')[0];return ye.top-=Oe,ye.bottom-=Oe,ye.left-=Ee,ye.right-=Ee,ye}function c(){const he=window.document.body,ce=window.document.documentElement;return{height:Math.max(he.scrollHeight,he.offsetHeight,ce.clientHeight,ce.scrollHeight,ce.offsetHeight),width:Math.max(he.scrollWidth,he.offsetWidth,ce.clientWidth,ce.scrollWidth,ce.offsetWidth)}}function u(he){let ce;if('HTML'===he.nodeName){const{width:ue,height:ge}=c();ce={width:ue,height:ge,left:0,top:0}}else ce={width:he.offsetWidth,height:he.offsetHeight,left:he.offsetLeft,top:he.offsetTop};return ce.right=ce.left+ce.width,ce.bottom=ce.top+ce.height,ce}function g(he){const ce=u(he);if('HTML'!==he.nodeName){const ue=e(he),ge=g(ue),be={width:ce.offsetWidth,height:ce.offsetHeight,left:ce.left+ge.left,top:ce.top+ge.top,right:ce.right-ge.right,bottom:ce.bottom-ge.bottom};return be}return ce}function w(he,ce='top'){const ue=r(he),ge=l(ue,ce);return-1===['BODY','HTML'].indexOf(ue.nodeName)?ge+w(o(ue),ce):ge}function v(he,ce,ue){let ge={top:0,left:0};const be=e(he);if('viewport'===ue){const{left:we,top:xe}=g(be),{clientWidth:ye,clientHeight:ve}=window.document.documentElement;if('fixed'===p(he))ge.right=ye,ge.bottom=ve;else{const Oe=w(he,'left'),Ee=w(he,'top');ge={top:0-xe,right:ye-we+Oe,bottom:ve-xe+Ee,left:0-we}}}else{let we;if(we='scrollParent'===ue?r(o(he)):'window'===ue?window.document.body:ue,'BODY'===we.nodeName){const{height:xe,width:ye}=c();ge.right=ye,ge.bottom=xe}else ge=h(we,be,s(he))}return ge.left+=ce,ge.top+=ce,ge.right-=ce,ge.bottom-=ce,ge}function O(he,ce,ue){if(-1===he.indexOf('auto'))return he;const ge=v(ue,0,'scrollParent'),be={top:ce.top-ge.top,right:ge.right-ce.right,bottom:ge.bottom-ce.bottom,left:ce.left-ge.left},we=Object.keys(be).sort((ye,ve)=>be[ve]-be[ye])[0],xe=he.split('-')[1];return we+(xe?`-${xe}`:'')}function N(he,ce){return Array.prototype.find?he.find(ce):he.filter(ce)[0]}function L(he,ce,ue){if(Array.prototype.findIndex)return he.findIndex((be)=>be[ce]===ue);const ge=N(he,(be)=>be[ce]===ue);return he.indexOf(ge)}function T(he){return fe({},he,{right:he.left+he.width,bottom:he.top+he.height})}function P(he){const ce=window.getComputedStyle(he),ue=parseFloat(ce.marginTop)+parseFloat(ce.marginBottom),ge=parseFloat(ce.marginLeft)+parseFloat(ce.marginRight),be={width:he.offsetWidth+ge,height:he.offsetHeight+ue};return be}function B(he){const ce={left:'right',right:'left',bottom:'top',top:'bottom'};return he.replace(/left|right|bottom|top/g,(ue)=>ce[ue])}function H(he,ce,ue,ge){ge=ge.split('-')[0];const be=P(ce),we={position:he,width:be.width,height:be.height},xe=-1!==['right','left'].indexOf(ge),ye=xe?'top':'left',ve=xe?'left':'top',Oe=xe?'height':'width',Ee=xe?'width':'height';return we[ye]=ue[ye]+ue[Oe]/2-be[Oe]/2,we[ve]=ge===ve?ue[ve]-be[Ee]:ue[B(ve)],we}function W(he,ce,ue){const ge='fixed'===he.position,be=he.isParentTransformed,we=e(ge&&be?ue:ce);return h(ue,we,ge,be)}function D(he){const ce=[!1,'ms','webkit','moz','o'],ue=he.charAt(0).toUpperCase()+he.slice(1);for(let ge=0;gege&&ue===ce)}function R(he,ce,ue){const ge=N(he,({name:be})=>be===ce);return!!ge&&he.some((be)=>{return be.name===ue&&be.enabled&&be.order{ue.removeEventListener('scroll',ce.updateBound)}),ce.updateBound=null,ce.scrollParents=[],ce.scrollElement=null,ce.eventsEnabled=!1,ce}function I(he,ce,ue){const ge=void 0===ue?he:he.slice(0,L(he,'name',ue));return ge.forEach((be)=>{be.enabled&&C(be.function)&&(ce=be.function(ce,be))}),ce}function U(he,ce){Object.keys(ce).forEach(function(ue){const ge=ce[ue];!1===ge?he.removeAttribute(ue):he.setAttribute(ue,ce[ue])})}function q(he,ce){Object.keys(ce).forEach((ue)=>{let ge='';-1!==['width','height','top','right','bottom','left'].indexOf(ue)&&A(ce[ue])&&(ge='px'),he.style[ue]=ce[ue]+ge})}function z(he,ce,ue,ge){const be='BODY'===he.nodeName,we=be?window:he;we.addEventListener(ce,ue,{passive:!0}),be||z(r(we.parentNode),ce,ue,ge),ge.push(we)}function F(he,ce,ue,ge){ue.updateBound=ge,window.addEventListener('resize',ue.updateBound,{passive:!0});const be=r(he);return z(be,'scroll',ue.updateBound,ue.scrollParents),ue.scrollElement=be,ue.eventsEnabled=!0,ue}function X(he){return'end'===he?'start':'start'===he?'end':he}const te=['native code','[object MutationObserverConstructor]'];var oe=(he)=>te.some((ce)=>-1<(he||'').toString().indexOf(ce));const ie='undefined'!=typeof window,re=['Edge','Trident','Firefox'];let ne=0;for(let he=0;he{he(),ce=!1});return be.observe(ge,{attributes:!0}),()=>{ce||(ce=!0,ge.setAttribute('x-index',ue),++ue)}}:function(he){let ce=!1;return()=>{ce||(ce=!0,setTimeout(()=>{ce=!1,he()},ne))}},fe=Object.assign||function(he){for(var ue,ce=1;cerequestAnimationFrame(this.update),this.update=pe(this.update.bind(this)),this.options=fe({},me.Defaults,ue),this.state={isDestroyed:!1,isCreated:!1,scrollParents:[]},this.reference=he.jquery?he[0]:he,this.popper=ce.jquery?ce[0]:ce,this.modifiers=Object.keys(me.Defaults.modifiers).map((be)=>fe({name:be},me.Defaults.modifiers[be])),this.modifiers=this.modifiers.map((be)=>{const we=ue.modifiers&&ue.modifiers[be.name]||{};return fe({},be,we)}),ue.modifiers&&(this.options.modifiers=fe({},me.Defaults.modifiers,ue.modifiers),Object.keys(ue.modifiers).forEach((be)=>{if(void 0===me.Defaults.modifiers[be]){const we=ue.modifiers[be];we.name=be,this.modifiers.push(we)}})),this.state.position=p(this.reference),this.modifiers=this.modifiers.sort((be,we)=>be.order-we.order),this.modifiers.forEach((be)=>{be.enabled&&C(be.onLoad)&&be.onLoad(this.reference,this.popper,this.options,be,this.state)}),this.state.isParentTransformed=k(this.popper.parentNode),this.update();const ge=this.options.eventsEnabled;ge&&this.enableEventListeners(),this.state.eventsEnabled=ge}update(){if(!this.state.isDestroyed){let he={instance:this,styles:{},attributes:{},flipped:!1,offsets:{}};this.state.position=p(this.reference),q(this.popper,{position:this.state.position}),he.offsets.reference=W(this.state,this.popper,this.reference),he.placement=O(this.options.placement,he.offsets.reference,this.popper),he.originalPlacement=this.options.placement,he.offsets.popper=H(this.state,this.popper,he.offsets.reference,he.placement),he=I(this.modifiers,he),this.state.isCreated?this.options.onUpdate(he):(this.state.isCreated=!0,this.options.onCreate(he))}}destroy(){return this.state.isDestroyed=!0,M(this.modifiers,'applyStyle')&&(this.popper.removeAttribute('x-placement'),this.popper.style.left='',this.popper.style.position='',this.popper.style.top='',this.popper.style[D('transform')]=''),this.disableEventListeners(),this.options.removeOnDestroy&&this.popper.parentNode.removeChild(this.popper),this}enableEventListeners(){this.state.eventsEnabled||(this.state=F(this.reference,this.options,this.state,this.scheduleUpdate))}disableEventListeners(){this.state.eventsEnabled&&(window.cancelAnimationFrame(this.scheduleUpdate),this.state=Y(this.reference,this.state))}}return me.Utils={computeAutoPlacement:O,debounce:pe,findIndex:L,getBordersSize:f,getBoundaries:v,getBoundingClientRect:d,getClientRect:T,getOffsetParent:e,getOffsetRect:u,getOffsetRectRelativeToCustomParent:h,getOuterSizes:P,getParentNode:o,getPopperOffsets:H,getPosition:p,getReferenceOffsets:W,getScroll:l,getScrollParent:r,getStyleComputedProperty:t,getSupportedPropertyName:D,getTotalScroll:w,getWindowSizes:c,includeScroll:m,isFixed:s,isFunction:C,isModifierEnabled:M,isModifierRequired:R,isNative:oe,isNumeric:A,isTransformed:k,removeEventListeners:Y,runModifiers:I,setAttributes:U,setStyles:q,setupEventListeners:F},me.placements=['auto','auto-start','auto-end','top','top-start','top-end','right','right-start','right-end','bottom','bottom-start','bottom-end','left','left-start','left-end'],me.Defaults={placement:'bottom',eventsEnabled:!0,onCreate:()=>{},onUpdate:()=>{},modifiers:{shift:{order:100,enabled:!0,function:function(he){const ce=he.placement,ue=ce.split('-')[0],ge=ce.split('-')[1];if(ge){const be=he.offsets.reference,we=T(he.offsets.popper),xe=-1!==['bottom','top'].indexOf(ue),ye=xe?'left':'top',ve=xe?'width':'height',Oe={start:{[ye]:be[ye]},end:{[ye]:be[ye]+be[ve]-we[ve]}};he.offsets.popper=fe({},we,Oe[ge])}return he}},offset:{order:200,enabled:!0,function:function(he,ce){const ue=he.placement,ge=he.offsets.popper;let be;return A(ce.offset)?be=[ce.offset,0]:(be=ce.offset.split(' '),be=be.map((we,xe)=>{const ye=we.match(/(\d*\.?\d*)(.*)/),ve=+ye[1],Oe=ye[2];let Ee=-1!==ue.indexOf('right')||-1!==ue.indexOf('left');1===xe&&(Ee=!Ee);const Se=Ee?'height':'width';if(0===Oe.indexOf('%')){let Ne;switch(Oe){case'%p':Ne=he.offsets.popper;break;case'%':case'$r':default:Ne=he.offsets.reference;}const Le=T(Ne),Te=Le[Se];return Te/100*ve}if('vh'===Oe||'vw'===Oe){let Ne;return Ne='vh'===Oe?Math.max(document.documentElement.clientHeight,window.innerHeight||0):Math.max(document.documentElement.clientWidth,window.innerWidth||0),Ne/100*ve}return'px'===Oe?+ve:+we})),-1===he.placement.indexOf('left')?-1===he.placement.indexOf('right')?-1===he.placement.indexOf('top')?-1!==he.placement.indexOf('bottom')&&(ge.left+=be[0],ge.top+=be[1]||0):(ge.left+=be[0],ge.top-=be[1]||0):(ge.top+=be[0],ge.left+=be[1]||0):(ge.top+=be[0],ge.left-=be[1]||0),he},offset:0},preventOverflow:{order:300,enabled:!0,function:function(he,ce){const ue=ce.boundariesElement||e(he.instance.popper),ge=v(he.instance.popper,ce.padding,ue);ce.boundaries=ge;const be=ce.priority;let we=T(he.offsets.popper);const xe={primary(ye){let ve=we[ye];return we[ye]ge[ye]&&!ce.escapeWithReference&&(Oe=Math.min(we[ve],ge[ye]-('right'===ye?we.width:we.height))),{[ve]:Oe}}};return be.forEach((ye)=>{const ve=-1===['left','top'].indexOf(ye)?'secondary':'primary';we=fe({},we,xe[ve](ye))}),he.offsets.popper=we,he},priority:['left','right','top','bottom'],padding:5,boundariesElement:'scrollParent'},keepTogether:{order:400,enabled:!0,function:function(he){const ce=T(he.offsets.popper),ue=he.offsets.reference,ge=he.placement.split('-')[0],be=Math.floor,we=-1!==['top','bottom'].indexOf(ge),xe=we?'right':'bottom',ye=we?'left':'top',ve=we?'width':'height';return ce[xe]be(ue[xe])&&(he.offsets.popper[ye]=be(ue[xe])),he}},arrow:{order:500,enabled:!0,function:function(he,ce){if(!R(he.instance.modifiers,'arrow','keepTogether'))return console.warn('WARNING: `keepTogether` modifier is required by arrow modifier in order to work, be sure to include it before `arrow`!'),he;let ue=ce.element;if('string'==typeof ue){if(ue=he.instance.popper.querySelector(ue),!ue)return he;}else if(!he.instance.popper.contains(ue))return console.warn('WARNING: `arrow.element` must be child of its popper element!'),he;const ge=he.placement.split('-')[0],be=T(he.offsets.popper),we=he.offsets.reference,xe=-1!==['left','right'].indexOf(ge),ye=xe?'height':'width',ve=xe?'top':'left',Oe=xe?'left':'top',Ee=xe?'bottom':'right',Se=P(ue)[ye];we[Ee]-Sebe[Ee]&&(he.offsets.popper[ve]+=we[ve]+Se-be[Ee]);const Ne=we[ve]+we[ye]/2-Se/2;let Le=Ne-T(he.offsets.popper)[ve];return Le=Math.max(Math.min(be[ye]-Se,Le),0),he.arrowElement=ue,he.offsets.arrow={},he.offsets.arrow[ve]=Le,he.offsets.arrow[Oe]='',he},element:'[x-arrow]'},flip:{order:600,enabled:!0,function:function(he,ce){if(M(he.instance.modifiers,'inner'))return he;if(he.flipped&&he.placement===he.originalPlacement)return he;const ue=v(he.instance.popper,ce.padding,ce.boundariesElement);let ge=he.placement.split('-')[0],be=B(ge),we=he.placement.split('-')[1]||'',xe=[];return xe='flip'===ce.behavior?[ge,be]:ce.behavior,xe.forEach((ye,ve)=>{if(ge!==ye||xe.length===ve+1)return he;ge=he.placement.split('-')[0],be=B(ge);const Oe=T(he.offsets.popper),Ee=he.offsets.reference,Se=Math.floor,Ne='left'===ge&&Se(Oe.right)>Se(Ee.left)||'right'===ge&&Se(Oe.left)Se(Ee.top)||'bottom'===ge&&Se(Oe.top)Se(ue.right),Pe=Se(Oe.top)Se(ue.bottom),He='left'===ge&&Le||'right'===ge&&Te||'top'===ge&&Pe||'bottom'===ge&&Be,We=-1!==['top','bottom'].indexOf(ge),De=!!ce.flipVariations&&(We&&'start'===we&&Le||We&&'end'===we&&Te||!We&&'start'===we&&Pe||!We&&'end'===we&&Be);(Ne||He||De)&&(he.flipped=!0,(Ne||He)&&(ge=xe[ve+1]),De&&(we=X(we)),he.placement=ge+(we?'-'+we:''),he.offsets.popper=H(he.instance.state.position,he.instance.popper,he.offsets.reference,he.placement),he=I(he.instance.modifiers,he,'flip'))}),he},behavior:'flip',padding:5,boundariesElement:'viewport'},inner:{order:700,enabled:!1,function:function(he){const ce=he.placement,ue=ce.split('-')[0],ge=T(he.offsets.popper),be=T(he.offsets.reference),we=-1!==['left','right'].indexOf(ue),xe=-1===['top','left'].indexOf(ue);return ge[we?'left':'top']=be[ce]-(xe?ge[we?'width':'height']:0),he.placement=B(ce),he.offsets.popper=T(ge),he}},hide:{order:800,enabled:!0,function:function(he){if(!R(he.instance.modifiers,'hide','preventOverflow'))return console.warn('WARNING: preventOverflow modifier is required by hide modifier in order to work, be sure to include it before hide!'),he;const ce=he.offsets.reference,ue=N(he.instance.modifiers,(ge)=>'preventOverflow'===ge.name).boundaries;if(ce.bottomue.right||ce.top>ue.bottom||ce.right=0)&&i.push(n)}return i.push(t.ownerDocument.body),t.ownerDocument!==document&&i.push(t.ownerDocument.defaultView),i}function s(){A&&document.body.removeChild(A),A=null}function a(t){var e=void 0;t===document?(e=document,t=document.documentElement):e=t.ownerDocument;var o=e.documentElement,i=n(t),r=P();return i.top-=r.top,i.left-=r.left,"undefined"==typeof i.width&&(i.width=document.body.scrollWidth-i.left-i.right),"undefined"==typeof i.height&&(i.height=document.body.scrollHeight-i.top-i.bottom),i.top=i.top-o.clientTop,i.left=i.left-o.clientLeft,i.right=e.body.clientWidth-i.width-i.left,i.bottom=e.body.clientHeight-i.height-i.top,i}function f(t){return t.offsetParent||document.documentElement}function l(){if(M)return M;var t=document.createElement("div");t.style.width="100%",t.style.height="200px";var e=document.createElement("div");h(e.style,{position:"absolute",top:0,left:0,pointerEvents:"none",visibility:"hidden",width:"200px",height:"150px",overflow:"hidden"}),e.appendChild(t),document.body.appendChild(e);var o=t.offsetWidth;e.style.overflow="scroll";var i=t.offsetWidth;o===i&&(i=e.clientWidth),document.body.removeChild(e);var n=o-i;return M={width:n,height:n}}function h(){var t=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],e=[];return Array.prototype.push.apply(e,arguments),e.slice(1).forEach(function(e){if(e)for(var o in e)({}).hasOwnProperty.call(e,o)&&(t[o]=e[o])}),t}function d(t,e){if("undefined"!=typeof t.classList)e.split(" ").forEach(function(e){e.trim()&&t.classList.remove(e)});else{var o=new RegExp("(^| )"+e.split(" ").join("|")+"( |$)","gi"),i=c(t).replace(o," ");g(t,i)}}function p(t,e){if("undefined"!=typeof t.classList)e.split(" ").forEach(function(e){e.trim()&&t.classList.add(e)});else{d(t,e);var o=c(t)+(" "+e);g(t,o)}}function u(t,e){if("undefined"!=typeof t.classList)return t.classList.contains(e);var o=c(t);return new RegExp("(^| )"+e+"( |$)","gi").test(o)}function c(t){return t.className instanceof t.ownerDocument.defaultView.SVGAnimatedString?t.className.baseVal:t.className}function g(t,e){t.setAttribute("class",e)}function m(t,e,o){o.forEach(function(o){e.indexOf(o)===-1&&u(t,o)&&d(t,o)}),e.forEach(function(e){u(t,e)||p(t,e)})}function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function v(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function y(t,e){var o=arguments.length<=2||void 0===arguments[2]?1:arguments[2];return t+o>=e&&e>=t-o}function b(){return"undefined"!=typeof performance&&"undefined"!=typeof performance.now?performance.now():+new Date}function w(){for(var t={top:0,left:0},e=arguments.length,o=Array(e),i=0;i1?o-1:0),n=1;n16?(e=Math.min(e-16,250),void(o=setTimeout(n,250))):void("undefined"!=typeof t&&b()-t<10||(null!=o&&(clearTimeout(o),o=null),t=b(),X(),e=b()-t))};"undefined"!=typeof window&&"undefined"!=typeof window.addEventListener&&["resize","scroll","touchmove"].forEach(function(t){window.addEventListener(t,i)})}();var F={center:"center",left:"right",right:"left"},H={middle:"middle",top:"bottom",bottom:"top"},N={top:0,left:0,middle:"50%",center:"50%",bottom:"100%",right:"100%"},U=function(t,e){var o=t.left,i=t.top;return"auto"===o&&(o=F[e.left]),"auto"===i&&(i=H[e.top]),{left:o,top:i}},V=function(t){var e=t.left,o=t.top;return"undefined"!=typeof N[t.left]&&(e=N[t.left]),"undefined"!=typeof N[t.top]&&(o=N[t.top]),{left:e,top:o}},R=function(t){var e=t.split(" "),o=z(e,2),i=o[0],n=o[1];return{top:i,left:n}},q=R,I=function(t){function e(t){var o=this;i(this,e),j(Object.getPrototypeOf(e.prototype),"constructor",this).call(this),this.position=this.position.bind(this),D.push(this),this.history=[],this.setOptions(t,!1),x.modules.forEach(function(t){"undefined"!=typeof t.initialize&&t.initialize.call(o)}),this.position()}return v(e,t),E(e,[{key:"getClass",value:function(){var t=arguments.length<=0||void 0===arguments[0]?"":arguments[0],e=this.options.classes;return"undefined"!=typeof e&&e[t]?this.options.classes[t]:this.options.classPrefix?this.options.classPrefix+"-"+t:t}},{key:"setOptions",value:function(t){var e=this,o=arguments.length<=1||void 0===arguments[1]||arguments[1],i={offset:"0 0",targetOffset:"0 0",targetAttachment:"auto auto",classPrefix:"tether"};this.options=h(i,t);var n=this.options,s=n.element,a=n.target,f=n.targetModifier;if(this.element=s,this.target=a,this.targetModifier=f,"viewport"===this.target?(this.target=document.body,this.targetModifier="visible"):"scroll-handle"===this.target&&(this.target=document.body,this.targetModifier="scroll-handle"),["element","target"].forEach(function(t){if("undefined"==typeof e[t])throw new Error("Tether Error: Both element and target must be defined");"undefined"!=typeof e[t].jquery?e[t]=e[t][0]:"string"==typeof e[t]&&(e[t]=document.querySelector(e[t]))}),p(this.element,this.getClass("element")),this.options.addTargetClasses!==!1&&p(this.target,this.getClass("target")),!this.options.attachment)throw new Error("Tether Error: You must provide an attachment");this.targetAttachment=q(this.options.targetAttachment),this.attachment=q(this.options.attachment),this.offset=R(this.options.offset),this.targetOffset=R(this.options.targetOffset),"undefined"!=typeof this.scrollParents&&this.disable(),"scroll-handle"===this.targetModifier?this.scrollParents=[this.target]:this.scrollParents=r(this.target),this.options.enabled!==!1&&this.enable(o)}},{key:"getTargetBounds",value:function(){if("undefined"==typeof this.targetModifier)return a(this.target);if("visible"===this.targetModifier){if(this.target===document.body)return{top:pageYOffset,left:pageXOffset,height:innerHeight,width:innerWidth};var t=a(this.target),e={height:t.height,width:t.width,top:t.top,left:t.left};return e.height=Math.min(e.height,t.height-(pageYOffset-t.top)),e.height=Math.min(e.height,t.height-(t.top+t.height-(pageYOffset+innerHeight))),e.height=Math.min(innerHeight,e.height),e.height-=2,e.width=Math.min(e.width,t.width-(pageXOffset-t.left)),e.width=Math.min(e.width,t.width-(t.left+t.width-(pageXOffset+innerWidth))),e.width=Math.min(innerWidth,e.width),e.width-=2,e.topo.clientWidth||[i.overflow,i.overflowX].indexOf("scroll")>=0||this.target!==document.body,r=0;n&&(r=15);var s=t.height-parseFloat(i.borderTopWidth)-parseFloat(i.borderBottomWidth)-r,e={width:15,height:.975*s*(s/o.scrollHeight),left:t.left+t.width-parseFloat(i.borderLeftWidth)-15},f=0;s<408&&this.target===document.body&&(f=-11e-5*Math.pow(s,2)-.00727*s+22.58),this.target!==document.body&&(e.height=Math.max(e.height,24));var l=this.target.scrollTop/(o.scrollHeight-s);return e.top=l*(s-e.height-f)+t.top+parseFloat(i.borderTopWidth),this.target===document.body&&(e.height=Math.max(e.height,24)),e}}},{key:"clearCache",value:function(){this._cache={}}},{key:"cache",value:function(t,e){return"undefined"==typeof this._cache&&(this._cache={}),"undefined"==typeof this._cache[t]&&(this._cache[t]=e.call(this)),this._cache[t]}},{key:"enable",value:function(){var t=this,e=arguments.length<=0||void 0===arguments[0]||arguments[0];this.options.addTargetClasses!==!1&&p(this.target,this.getClass("enabled")),p(this.element,this.getClass("enabled")),this.enabled=!0,this.scrollParents.forEach(function(e){e!==t.target.ownerDocument&&e.addEventListener("scroll",t.position)}),e&&this.position()}},{key:"disable",value:function(){var t=this;d(this.target,this.getClass("enabled")),d(this.element,this.getClass("enabled")),this.enabled=!1,"undefined"!=typeof this.scrollParents&&this.scrollParents.forEach(function(e){e.removeEventListener("scroll",t.position)})}},{key:"destroy",value:function(){var t=this;this.disable(),D.forEach(function(e,o){e===t&&D.splice(o,1)}),0===D.length&&s()}},{key:"updateAttachClasses",value:function(t,e){var o=this;t=t||this.attachment,e=e||this.targetAttachment;var i=["left","top","bottom","right","middle","center"];"undefined"!=typeof this._addAttachClasses&&this._addAttachClasses.length&&this._addAttachClasses.splice(0,this._addAttachClasses.length),"undefined"==typeof this._addAttachClasses&&(this._addAttachClasses=[]);var n=this._addAttachClasses;t.top&&n.push(this.getClass("element-attached")+"-"+t.top),t.left&&n.push(this.getClass("element-attached")+"-"+t.left),e.top&&n.push(this.getClass("target-attached")+"-"+e.top),e.left&&n.push(this.getClass("target-attached")+"-"+e.left);var r=[];i.forEach(function(t){r.push(o.getClass("element-attached")+"-"+t),r.push(o.getClass("target-attached")+"-"+t)}),k(function(){"undefined"!=typeof o._addAttachClasses&&(m(o.element,o._addAttachClasses,r),o.options.addTargetClasses!==!1&&m(o.target,o._addAttachClasses,r),delete o._addAttachClasses)})}},{key:"position",value:function(){var t=this,e=arguments.length<=0||void 0===arguments[0]||arguments[0];if(this.enabled){this.clearCache();var o=U(this.targetAttachment,this.attachment);this.updateAttachClasses(this.attachment,o);var i=this.cache("element-bounds",function(){return a(t.element)}),n=i.width,r=i.height;if(0===n&&0===r&&"undefined"!=typeof this.lastSize){var s=this.lastSize;n=s.width,r=s.height}else this.lastSize={width:n,height:r};var h=this.cache("target-bounds",function(){return t.getTargetBounds()}),d=h,p=C(V(this.attachment),{width:n,height:r}),u=C(V(o),d),c=C(this.offset,{width:n,height:r}),g=C(this.targetOffset,d);p=w(p,c),u=w(u,g);for(var m=h.left+u.left-p.left,v=h.top+u.top-p.top,y=0;yA.documentElement.clientHeight&&(S=this.cache("scrollbar-size",l),E.viewport.bottom-=S.height),T.innerWidth>A.documentElement.clientWidth&&(S=this.cache("scrollbar-size",l),E.viewport.right-=S.width),["","static"].indexOf(A.body.style.position)!==-1&&["","static"].indexOf(A.body.parentElement.style.position)!==-1||(E.page.bottom=A.body.scrollHeight-v-r,E.page.right=A.body.scrollWidth-m-n),"undefined"!=typeof this.options.optimizations&&this.options.optimizations.moveElement!==!1&&"undefined"==typeof this.targetModifier&&!function(){var e=t.cache("target-offsetparent",function(){return f(t.target)}),o=t.cache("target-offsetparent-bounds",function(){return a(e)}),i=getComputedStyle(e),n=o,r={};if(["Top","Left","Bottom","Right"].forEach(function(t){r[t.toLowerCase()]=parseFloat(i["border"+t+"Width"])}),o.right=A.body.scrollWidth-o.left-n.width+r.right,o.bottom=A.body.scrollHeight-o.top-n.height+r.bottom,E.page.top>=o.top+r.top&&E.page.bottom>=o.bottom&&E.page.left>=o.left+r.left&&E.page.right>=o.right){var s=e.scrollTop,l=e.scrollLeft;E.offset={top:E.page.top-o.top+s-r.top,left:E.page.left-o.left+l-r.left}}}(),this.move(E),this.history.unshift(E),this.history.length>3&&this.history.pop(),e&&_(),!0}}},{key:"move",value:function(t){var e=this;if("undefined"!=typeof this.element.parentNode){var o={};for(var i in t){o[i]={};for(var n in t[i]){for(var r=!1,s=0;s=0){var c=a.split(" "),m=z(c,2);d=m[0],h=m[1]}else h=d=a;var b=O(e,r);"target"!==d&&"both"!==d||(ob[3]&&"bottom"===v.top&&(o-=p,v.top="top")),"together"===d&&("top"===v.top&&("bottom"===y.top&&ob[3]&&o-(s-p)>=b[1]&&(o-=s-p,v.top="bottom",y.top="bottom")),"bottom"===v.top&&("top"===y.top&&o+s>b[3]?(o-=p,v.top="top",o-=s,y.top="bottom"):"bottom"===y.top&&ob[3]&&"top"===y.top?(o-=s,y.top="bottom"):ob[2]&&"right"===v.left&&(i-=u,v.left="left")),"together"===h&&(ib[2]&&"right"===v.left?"left"===y.left?(i-=u,v.left="left",i-=f,y.left="right"):"right"===y.left&&(i-=u,v.left="left",i+=f,y.left="left"):"center"===v.left&&(i+f>b[2]&&"left"===y.left?(i-=f,y.left="right"):ib[3]&&"top"===y.top&&(o-=s,y.top="bottom")),"element"!==h&&"both"!==h||(ib[2]&&("left"===y.left?(i-=f,y.left="right"):"center"===y.left&&(i-=f/2,y.left="right"))),"string"==typeof l?l=l.split(",").map(function(t){return t.trim()}):l===!0&&(l=["top","left","right","bottom"]),l=l||[];var w=[],C=[];o=0?(o=b[1],w.push("top")):C.push("top")),o+s>b[3]&&(l.indexOf("bottom")>=0?(o=b[3]-s,w.push("bottom")):C.push("bottom")),i=0?(i=b[0],w.push("left")):C.push("left")),i+f>b[2]&&(l.indexOf("right")>=0?(i=b[2]-f,w.push("right")):C.push("right")),w.length&&!function(){var t=void 0;t="undefined"!=typeof e.options.pinnedClass?e.options.pinnedClass:e.getClass("pinned"),g.push(t),w.forEach(function(e){g.push(t+"-"+e)})}(),C.length&&!function(){var t=void 0;t="undefined"!=typeof e.options.outOfBoundsClass?e.options.outOfBoundsClass:e.getClass("out-of-bounds"),g.push(t),C.forEach(function(e){g.push(t+"-"+e)})}(),(w.indexOf("left")>=0||w.indexOf("right")>=0)&&(y.left=v.left=!1),(w.indexOf("top")>=0||w.indexOf("bottom")>=0)&&(y.top=v.top=!1),v.top===n.top&&v.left===n.left&&y.top===e.attachment.top&&y.left===e.attachment.left||(e.updateAttachClasses(y,v),e.trigger("update",{attachment:y,targetAttachment:v}))}),k(function(){e.options.addTargetClasses!==!1&&m(e.target,g,c),m(e.element,g,c)}),{top:o,left:i}}});var Y=x.Utils,a=Y.getBounds,m=Y.updateClasses,k=Y.defer;x.modules.push({position:function(t){var e=this,o=t.top,i=t.left,n=this.cache("element-bounds",function(){return a(e.element)}),r=n.height,s=n.width,f=this.getTargetBounds(),l=o+r,h=i+s,d=[];o<=f.bottom&&l>=f.top&&["left","right"].forEach(function(t){var e=f[t];e!==i&&e!==h||d.push(t)}),i<=f.right&&h>=f.left&&["top","bottom"].forEach(function(t){var e=f[t];e!==o&&e!==l||d.push(t)});var p=[],u=[],c=["left","top","right","bottom"];return p.push(this.getClass("abutted")),c.forEach(function(t){p.push(e.getClass("abutted")+"-"+t)}),d.length&&u.push(this.getClass("abutted")),d.forEach(function(t){u.push(e.getClass("abutted")+"-"+t)}),k(function(){e.options.addTargetClasses!==!1&&m(e.target,u,p),m(e.element,u,p)}),!0}});var z=function(){function t(t,e){var o=[],i=!0,n=!1,r=void 0;try{for(var s,a=t[Symbol.iterator]();!(i=(s=a.next()).done)&&(o.push(s.value),!e||o.length!==e);i=!0);}catch(f){n=!0,r=f}finally{try{!i&&a["return"]&&a["return"]()}finally{if(n)throw r}}return o}return function(e,o){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,o);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();return x.modules.push({position:function(t){var e=t.top,o=t.left;if(this.options.shift){var i=this.options.shift;"function"==typeof this.options.shift&&(i=this.options.shift.call(this,{top:e,left:o}));var n=void 0,r=void 0;if("string"==typeof i){i=i.split(" "),i[1]=i[1]||i[0];var s=i,a=z(s,2);n=a[0],r=a[1],n=parseFloat(n,10),r=parseFloat(r,10)}else n=i.top,r=i.left;return e+=n,o+=r,{top:e,left:o}}}}),$}); \ No newline at end of file diff --git a/js/src/popover.js b/js/src/popover.js index b68b4799840c..e20b50f976cc 100644 --- a/js/src/popover.js +++ b/js/src/popover.js @@ -118,8 +118,6 @@ const Popover = (($) => { this.setElementContent($tip.find(Selector.CONTENT), this._getContent()) $tip.removeClass(`${ClassName.FADE} ${ClassName.SHOW}`) - - this.cleanupTether() } // private diff --git a/js/src/tooltip.js b/js/src/tooltip.js index 47c3d8d0588f..c4c4ee2f648c 100644 --- a/js/src/tooltip.js +++ b/js/src/tooltip.js @@ -1,4 +1,4 @@ -/* global Tether */ +/* global Popper */ import Util from './util' @@ -13,11 +13,11 @@ import Util from './util' const Tooltip = (($) => { /** - * Check for Tether dependency - * Tether - http://tether.io/ + * Check for Popper dependency + * Tether - https://popper.js.org */ - if (typeof Tether === 'undefined') { - throw new Error('Bootstrap tooltips require Tether (http://tether.io/)') + if (typeof Popper === 'undefined') { + throw new Error('Bootstrap tooltips require Popper (https://popper.js.org)') } @@ -33,8 +33,6 @@ const Tooltip = (($) => { const EVENT_KEY = `.${DATA_KEY}` const JQUERY_NO_CONFLICT = $.fn[NAME] const TRANSITION_DURATION = 150 - const CLASS_PREFIX = 'bs-tether' - const TETHER_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g') const Default = { animation : true, @@ -66,10 +64,10 @@ const Tooltip = (($) => { } const AttachmentMap = { - TOP : 'bottom center', - RIGHT : 'middle left', - BOTTOM : 'top center', - LEFT : 'middle right' + TOP : 'top', + RIGHT : 'right', + BOTTOM : 'bottom', + LEFT : 'left' } const HoverState = { @@ -100,11 +98,6 @@ const Tooltip = (($) => { TOOLTIP_INNER : '.tooltip-inner' } - const TetherClass = { - element : false, - enabled : false - } - const Trigger = { HOVER : 'hover', FOCUS : 'focus', @@ -128,7 +121,7 @@ const Tooltip = (($) => { this._timeout = 0 this._hoverState = '' this._activeTrigger = {} - this._tether = null + this._popper = null // protected this.element = element @@ -220,8 +213,6 @@ const Tooltip = (($) => { dispose() { clearTimeout(this._timeout) - this.cleanupTether() - $.removeData(this.element, this.constructor.DATA_KEY) $(this.element).off(this.constructor.EVENT_KEY) @@ -235,7 +226,7 @@ const Tooltip = (($) => { this._timeout = null this._hoverState = null this._activeTrigger = null - this._tether = null + this._popper = null this.element = null this.config = null @@ -288,19 +279,19 @@ const Tooltip = (($) => { $(this.element).trigger(this.constructor.Event.INSERTED) - this._tether = new Tether({ - attachment, - element : tip, - target : this.element, - classes : TetherClass, - classPrefix : CLASS_PREFIX, - offset : this.config.offset, - constraints : this.config.constraints, - addTargetClasses: false + this._popper = new Popper(this.element, tip, { + placement : attachment, + modifiers : { + arrow : { + element : Selector.TOOLTIP + }, + offset : { + offset : this.config.offset + } + } }) Util.reflow(tip) - this._tether.position() $(tip).addClass(ClassName.SHOW) @@ -342,11 +333,9 @@ const Tooltip = (($) => { tip.parentNode.removeChild(tip) } - this._cleanTipClass() this.element.removeAttribute('aria-describedby') $(this.element).trigger(this.constructor.Event.HIDDEN) - this.cleanupTether() - + this._popper.destroy() if (callback) { callback() } @@ -398,12 +387,8 @@ const Tooltip = (($) => { setContent() { const $tip = $(this.getTipElement()) - this.setElementContent($tip.find(Selector.TOOLTIP_INNER), this.getTitle()) - $tip.removeClass(`${ClassName.FADE} ${ClassName.SHOW}`) - - this.cleanupTether() } setElementContent($element, content) { @@ -434,12 +419,6 @@ const Tooltip = (($) => { return title } - cleanupTether() { - if (this._tether) { - this._tether.destroy() - } - } - // private @@ -447,14 +426,6 @@ const Tooltip = (($) => { return AttachmentMap[placement.toUpperCase()] } - _cleanTipClass() { - const $tip = $(this.getTipElement()) - const tabClass = $tip.attr('class').match(TETHER_PREFIX_REGEX) - if (tabClass !== null && tabClass.length > 0) { - $tip.removeClass(tabClass.join('')) - } - } - _setListeners() { const triggers = this.config.trigger.split(' ') diff --git a/js/tests/visual/popover.html b/js/tests/visual/popover.html index 51b5fe506529..4fd813c0603f 100644 --- a/js/tests/visual/popover.html +++ b/js/tests/visual/popover.html @@ -29,7 +29,7 @@

Popover Bootstrap Visual Test

- + diff --git a/js/tests/visual/tooltip.html b/js/tests/visual/tooltip.html index f447a533b657..c646c2c56c57 100644 --- a/js/tests/visual/tooltip.html +++ b/js/tests/visual/tooltip.html @@ -34,7 +34,7 @@

Tooltip Bootstrap Visual Test

- + From 7492478339325a4899726aa7da5f445c0ac6bc4a Mon Sep 17 00:00:00 2001 From: Johann-S Date: Fri, 7 Apr 2017 11:12:17 +0200 Subject: [PATCH 02/26] Begin to add arrow to Popover and Tooltip --- js/src/popover.js | 1 + js/src/tooltip.js | 10 ++++++---- js/tests/visual/modal.html | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/js/src/popover.js b/js/src/popover.js index e20b50f976cc..02efe2b2edea 100644 --- a/js/src/popover.js +++ b/js/src/popover.js @@ -28,6 +28,7 @@ const Popover = (($) => { trigger : 'click', content : '', template : '' }) diff --git a/js/src/tooltip.js b/js/src/tooltip.js index c4c4ee2f648c..505a8d492abe 100644 --- a/js/src/tooltip.js +++ b/js/src/tooltip.js @@ -37,6 +37,7 @@ const Tooltip = (($) => { const Default = { animation : true, template : '', trigger : 'hover focus', title : '', @@ -281,10 +282,8 @@ const Tooltip = (($) => { this._popper = new Popper(this.element, tip, { placement : attachment, + arrowElement : '.arrow', modifiers : { - arrow : { - element : Selector.TOOLTIP - }, offset : { offset : this.config.offset } @@ -335,7 +334,10 @@ const Tooltip = (($) => { this.element.removeAttribute('aria-describedby') $(this.element).trigger(this.constructor.Event.HIDDEN) - this._popper.destroy() + if (this._popper !== null) { + this._popper.destroy() + } + if (callback) { callback() } diff --git a/js/tests/visual/modal.html b/js/tests/visual/modal.html index e999514f7b96..90b814e67434 100644 --- a/js/tests/visual/modal.html +++ b/js/tests/visual/modal.html @@ -170,7 +170,7 @@ - + From e4f7a075cc03875163d458ab99f459433ce99ebf Mon Sep 17 00:00:00 2001 From: Johann-S Date: Fri, 7 Apr 2017 13:20:34 +0200 Subject: [PATCH 03/26] Add attachment classes --- js/src/popover.js | 14 ++++++++++++++ js/src/tooltip.js | 16 ++++++++++++++++ js/tests/index.html | 2 +- js/tests/unit/tooltip.js | 2 +- 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/js/src/popover.js b/js/src/popover.js index 02efe2b2edea..f89d3d5c8b41 100644 --- a/js/src/popover.js +++ b/js/src/popover.js @@ -22,6 +22,8 @@ const Popover = (($) => { const DATA_KEY = 'bs.popover' const EVENT_KEY = `.${DATA_KEY}` const JQUERY_NO_CONFLICT = $.fn[NAME] + const CLASS_PREFIX = 'bs-popover' + const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g') const Default = $.extend({}, Tooltip.Default, { placement : 'right', @@ -107,6 +109,10 @@ const Popover = (($) => { return this.getTitle() || this._getContent() } + addAttachmentClass(attachment) { + $(this.getTipElement()).addClass(`${CLASS_PREFIX}-${attachment}`) + } + getTipElement() { return this.tip = this.tip || $(this.config.template)[0] } @@ -130,6 +136,14 @@ const Popover = (($) => { this.config.content) } + _cleanTipClass() { + const $tip = $(this.getTipElement()) + const tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX) + if (tabClass !== null && tabClass.length > 0) { + $tip.removeClass(tabClass.join('')) + } + } + // static diff --git a/js/src/tooltip.js b/js/src/tooltip.js index 505a8d492abe..fb4ff131c4b8 100644 --- a/js/src/tooltip.js +++ b/js/src/tooltip.js @@ -33,6 +33,8 @@ const Tooltip = (($) => { const EVENT_KEY = `.${DATA_KEY}` const JQUERY_NO_CONFLICT = $.fn[NAME] const TRANSITION_DURATION = 150 + const CLASS_PREFIX = 'bs-tooltip' + const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g') const Default = { animation : true, @@ -269,6 +271,7 @@ const Tooltip = (($) => { this.config.placement const attachment = this._getAttachment(placement) + this.addAttachmentClass(attachment) const container = this.config.container === false ? document.body : $(this.config.container) @@ -332,6 +335,7 @@ const Tooltip = (($) => { tip.parentNode.removeChild(tip) } + this._cleanTipClass() this.element.removeAttribute('aria-describedby') $(this.element).trigger(this.constructor.Event.HIDDEN) if (this._popper !== null) { @@ -383,6 +387,10 @@ const Tooltip = (($) => { return Boolean(this.getTitle()) } + addAttachmentClass(attachment) { + $(this.getTipElement()).addClass(`${CLASS_PREFIX}-${attachment}`) + } + getTipElement() { return this.tip = this.tip || $(this.config.template)[0] } @@ -624,6 +632,14 @@ const Tooltip = (($) => { return config } + _cleanTipClass() { + const $tip = $(this.getTipElement()) + const tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX) + if (tabClass !== null && tabClass.length > 0) { + $tip.removeClass(tabClass.join('')) + } + } + // static diff --git a/js/tests/index.html b/js/tests/index.html index 81efd5876d4e..d17608e4a9c6 100644 --- a/js/tests/index.html +++ b/js/tests/index.html @@ -7,7 +7,7 @@ - + diff --git a/js/tests/unit/tooltip.js b/js/tests/unit/tooltip.js index 8cb1a6fdf19d..dc6364415a94 100644 --- a/js/tests/unit/tooltip.js +++ b/js/tests/unit/tooltip.js @@ -111,7 +111,7 @@ $(function () { assert .ok($('.tooltip') - .is('.fade.bs-tether-element-attached-top.bs-tether-element-attached-center.show'), 'has correct classes applied') + .is('.fade.bs-tooltip-bottom.show'), 'has correct classes applied') $tooltip.bootstrapTooltip('hide') From 2a10fbe362b7a8dcba9bb8b7c15570bf02f861a9 Mon Sep 17 00:00:00 2001 From: Johann-S Date: Sat, 8 Apr 2017 21:13:15 +0200 Subject: [PATCH 04/26] Fix arrow for tooltip and popover --- js/src/tooltip.js | 19 ++++----- js/tests/unit/tooltip.js | 83 ++++++++++++------------------------ js/tests/visual/tooltip.html | 3 ++ scss/_popover.scss | 56 +++++++++++------------- scss/_tooltip.scss | 22 ++++------ 5 files changed, 73 insertions(+), 110 deletions(-) diff --git a/js/src/tooltip.js b/js/src/tooltip.js index fb4ff131c4b8..c380f8675f92 100644 --- a/js/src/tooltip.js +++ b/js/src/tooltip.js @@ -285,11 +285,8 @@ const Tooltip = (($) => { this._popper = new Popper(this.element, tip, { placement : attachment, - arrowElement : '.arrow', - modifiers : { - offset : { - offset : this.config.offset - } + offsets : { + popper : this.config.offset } }) @@ -632,13 +629,13 @@ const Tooltip = (($) => { return config } - _cleanTipClass() { - const $tip = $(this.getTipElement()) - const tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX) - if (tabClass !== null && tabClass.length > 0) { - $tip.removeClass(tabClass.join('')) + _cleanTipClass() { + const $tip = $(this.getTipElement()) + const tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX) + if (tabClass !== null && tabClass.length > 0) { + $tip.removeClass(tabClass.join('')) + } } - } // static diff --git a/js/tests/unit/tooltip.js b/js/tests/unit/tooltip.js index dc6364415a94..0bb90156b9e1 100644 --- a/js/tests/unit/tooltip.js +++ b/js/tests/unit/tooltip.js @@ -364,32 +364,31 @@ $(function () { }) QUnit.test('should add position class before positioning so that position-specific styles are taken into account', function (assert) { - assert.expect(1) + assert.expect(2) + var done = assert.async() var styles = '' var $styles = $(styles).appendTo('head') var $container = $('
').appendTo('#qunit-fixture') - var $target = $('') + $('') .appendTo($container) .bootstrapTooltip({ - placement: 'right' + placement: 'right', + trigger: 'manual' + }) + .on('inserted.bs.tooltip', function () { + var $tooltip = $($(this).data('bs.tooltip').tip) + assert.ok($tooltip.hasClass('bs-tooltip-right')) + assert.ok($tooltip.attr('style') === undefined) + $(this).bootstrapTooltip('hide') + $container.remove() + $styles.remove() + done() }) .bootstrapTooltip('show') - - var $tooltip = $($target.data('bs.tooltip').tip) - - // this is some dumb hack stuff because sub pixels in firefox - var top = Math.round($target.offset().top + $target[0].offsetHeight / 2 - $tooltip[0].offsetHeight / 2) - var top2 = Math.round($tooltip.offset().top) - var topDiff = top - top2 - assert.ok(topDiff <= 1 && topDiff >= -1) - $target.bootstrapTooltip('hide') - - $container.remove() - $styles.remove() }) QUnit.test('should use title attribute for tooltip text', function (assert) { @@ -476,6 +475,12 @@ $(function () { }) .appendTo('#qunit-fixture') + $('#qunit-fixture').css({ + position : 'relative', + top : '0px', + left : '0px' + }) + var $trigger = $container .find('a') .css('margin-top', 200) @@ -489,6 +494,11 @@ $(function () { setTimeout(function () { assert.ok(Math.round($tooltip.offset().top + $tooltip.outerHeight()) <= Math.round($trigger.offset().top)) + $('#qunit-fixture').css({ + position : 'absolute', + top : '-10000px', + left : '-10000px' + }) done() }, 0) }) @@ -629,45 +639,6 @@ $(function () { $tooltip.trigger('mouseenter') }) - QUnit.test('should correctly position tooltips on SVG elements', function (assert) { - if (!window.SVGElement) { - // Skip IE8 since it doesn't support SVG - assert.expect(0) - return - } - assert.expect(2) - - var done = assert.async() - - var styles = '' - var $styles = $(styles).appendTo('head') - - $('#qunit-fixture').append( - '
' - + ' ' - + ' ' - + ' ' - + '
') - var $circle = $('#theCircle') - - $circle - .on('shown.bs.tooltip', function () { - var offset = $('.tooltip').offset() - $styles.remove() - assert.ok(Math.abs(offset.left - 88) <= 1, 'tooltip has correct horizontal location') - $circle.bootstrapTooltip('hide') - assert.strictEqual($('.tooltip').length, 0, 'tooltip removed from dom') - done() - }) - .bootstrapTooltip({ placement: 'top', trigger: 'manual' }) - - $circle.bootstrapTooltip('show') - }) - QUnit.test('should not reload the tooltip on subsequent mouseenter events', function (assert) { assert.expect(1) var titleHtml = function () { diff --git a/js/tests/visual/tooltip.html b/js/tests/visual/tooltip.html index c646c2c56c57..9fbd196b6faa 100644 --- a/js/tests/visual/tooltip.html +++ b/js/tests/visual/tooltip.html @@ -30,6 +30,9 @@

Tooltip Bootstrap Visual Test

+ + +

diff --git a/scss/_popover.scss b/scss/_popover.scss index c259916d76ff..d763039ff3ea 100644 --- a/scss/_popover.scss +++ b/scss/_popover.scss @@ -21,69 +21,66 @@ // Popover directions - &.popover-top, - &.bs-tether-element-attached-bottom { - margin-top: -$popover-arrow-width; + &.bs-popover-top { + margin-bottom: $popover-arrow-width; - &::before, - &::after { + ::before, + ::after { left: 50%; border-bottom-width: 0; } - &::before { + ::before { bottom: -$popover-arrow-outer-width; margin-left: -$popover-arrow-outer-width; border-top-color: $popover-arrow-outer-color; } - &::after { + ::after { bottom: -($popover-arrow-outer-width - 1); margin-left: -$popover-arrow-width; border-top-color: $popover-arrow-color; } } - &.popover-right, - &.bs-tether-element-attached-left { + &.bs-popover-right { margin-left: $popover-arrow-width; - &::before, - &::after { + ::before, + ::after { top: 50%; border-left-width: 0; } - &::before { + ::before { left: -$popover-arrow-outer-width; margin-top: -$popover-arrow-outer-width; border-right-color: $popover-arrow-outer-color; } - &::after { + ::after { left: -($popover-arrow-outer-width - 1); margin-top: -($popover-arrow-outer-width - 1); border-right-color: $popover-arrow-color; } } - &.popover-bottom, - &.bs-tether-element-attached-top { + &.bs-popover-bottom { margin-top: $popover-arrow-width; - &::before, - &::after { + ::before, + ::after { left: 50%; border-top-width: 0; } - &::before { + ::before { top: -$popover-arrow-outer-width; margin-left: -$popover-arrow-outer-width; border-bottom-color: $popover-arrow-outer-color; } - &::after { + ::after { top: -($popover-arrow-outer-width - 1); margin-left: -$popover-arrow-width; border-bottom-color: $popover-arrow-color; @@ -102,23 +99,22 @@ } } - &.popover-left, - &.bs-tether-element-attached-right { - margin-left: -$popover-arrow-width; + &.bs-popover-left { + margin-right: $popover-arrow-width; - &::before, - &::after { + ::before, + ::after { top: 50%; border-right-width: 0; } - &::before { + ::before { right: -$popover-arrow-outer-width; margin-top: -$popover-arrow-outer-width; border-left-color: $popover-arrow-outer-color; } - &::after { + ::after { right: -($popover-arrow-outer-width - 1); margin-top: -($popover-arrow-outer-width - 1); border-left-color: $popover-arrow-color; @@ -153,8 +149,8 @@ // // .popover-arrow is outer, .popover-arrow::after is inner -.popover::before, -.popover::after { +.arrow::before, +.arrow::after { position: absolute; display: block; width: 0; @@ -163,11 +159,11 @@ border-style: solid; } -.popover::before { +.arrow::before { content: ""; border-width: $popover-arrow-outer-width; } -.popover::after { +.arrow::after { content: ""; border-width: $popover-arrow-width; } diff --git a/scss/_tooltip.scss b/scss/_tooltip.scss index 24e198d464e2..4006b46d96af 100644 --- a/scss/_tooltip.scss +++ b/scss/_tooltip.scss @@ -13,12 +13,11 @@ &.show { opacity: $tooltip-opacity; } - &.tooltip-top, - &.bs-tether-element-attached-bottom { + &.bs-tooltip-top { padding: $tooltip-arrow-width 0; margin-top: -$tooltip-margin; - .tooltip-inner::before { + .arrow::before { bottom: 0; left: 50%; margin-left: -$tooltip-arrow-width; @@ -27,12 +26,11 @@ border-top-color: $tooltip-arrow-color; } } - &.tooltip-right, - &.bs-tether-element-attached-left { + &.bs-tooltip-right { padding: 0 $tooltip-arrow-width; margin-left: $tooltip-margin; - .tooltip-inner::before { + .arrow::before { top: 50%; left: 0; margin-top: -$tooltip-arrow-width; @@ -41,12 +39,11 @@ border-right-color: $tooltip-arrow-color; } } - &.tooltip-bottom, - &.bs-tether-element-attached-top { + &.bs-tooltip-bottom { padding: $tooltip-arrow-width 0; margin-top: $tooltip-margin; - .tooltip-inner::before { + .arrow::before { top: 0; left: 50%; margin-left: -$tooltip-arrow-width; @@ -55,12 +52,11 @@ border-bottom-color: $tooltip-arrow-color; } } - &.tooltip-left, - &.bs-tether-element-attached-right { + &.bs-tooltip-left { padding: 0 $tooltip-arrow-width; margin-left: -$tooltip-margin; - .tooltip-inner::before { + .arrow::before { top: 50%; right: 0; margin-top: -$tooltip-arrow-width; @@ -80,7 +76,7 @@ background-color: $tooltip-bg; @include border-radius($border-radius); - &::before { + .arrow::before { position: absolute; width: 0; height: 0; From 44924575c0e175eebce8fd4a9376f0fd9ff0559c Mon Sep 17 00:00:00 2001 From: Johann-S Date: Fri, 14 Apr 2017 11:25:53 +0200 Subject: [PATCH 05/26] Begin to use Popper for Dropdown --- js/src/dropdown.js | 98 ++++++++++++++++++++++++++++++++--- js/src/tooltip.js | 2 +- js/tests/visual/dropdown.html | 1 + scss/_dropdown.scss | 18 ++----- 4 files changed, 97 insertions(+), 22 deletions(-) diff --git a/js/src/dropdown.js b/js/src/dropdown.js index eb536dc7dc34..a2b5561c2720 100644 --- a/js/src/dropdown.js +++ b/js/src/dropdown.js @@ -10,6 +10,13 @@ import Util from './util' const Dropdown = (($) => { + /** + * Check for Popper dependency + * Popper - https://popper.js.org + */ + if (typeof Popper === 'undefined') { + throw new Error('Bootstrap dropdown require Popper (https://popper.js.org)') + } /** * ------------------------------------------------------------------------ @@ -55,6 +62,20 @@ const Dropdown = (($) => { VISIBLE_ITEMS : '.dropdown-menu .dropdown-item:not(.disabled)' } + const Default = { + animation : true, + trigger : 'click', + placement : 'bottom', + offset : '0 0' + } + + const DefaultType = { + animation : 'boolean', + trigger : 'string', + placement : 'string', + offset : 'string' + } + /** * ------------------------------------------------------------------------ @@ -64,8 +85,11 @@ const Dropdown = (($) => { class Dropdown { - constructor(element) { + constructor(element, config) { this._element = element + this._popper = null + this._config = this._getConfig(config) + this._menu = this._getMenuElement() this._addEventListeners() } @@ -77,16 +101,30 @@ const Dropdown = (($) => { return VERSION } + static get Default() { + return Default + } + + static get DefaultType() { + return DefaultType + } + // public toggle() { - if (this.disabled || $(this).hasClass(ClassName.DISABLED)) { + let context = $(this).data(DATA_KEY) + if (!context) { + context = new Dropdown(this) + $(this).data(DATA_KEY, context) + } + + if (context.disabled || $(this).hasClass(ClassName.DISABLED)) { return false } const parent = Dropdown._getParentFromElement(this) - const isActive = $(parent).hasClass(ClassName.SHOW) + const isActive = $(context._menu).hasClass(ClassName.SHOW) Dropdown._clearMenus() @@ -97,7 +135,7 @@ const Dropdown = (($) => { const relatedTarget = { relatedTarget : this } - const showEvent = $.Event(Event.SHOW, relatedTarget) + const showEvent = $.Event(Event.SHOW, relatedTarget) $(parent).trigger(showEvent) @@ -105,6 +143,13 @@ const Dropdown = (($) => { return false } + this._popper = new Popper(this, context._menu, { + placement : context._config.placement, + offsets : { + popper : context._config.offset + } + }) + // if this is a touch-enabled device we add extra // empty mouseover listeners to the body's immediate children; // only needed because of broken event delegation on iOS @@ -117,8 +162,10 @@ const Dropdown = (($) => { this.focus() this.setAttribute('aria-expanded', true) - $(parent).toggleClass(ClassName.SHOW) - $(parent).trigger($.Event(Event.SHOWN, relatedTarget)) + $(context._menu).toggleClass(ClassName.SHOW) + $(parent) + .toggleClass(ClassName.SHOW) + .trigger($.Event(Event.SHOWN, relatedTarget)) return false } @@ -127,6 +174,10 @@ const Dropdown = (($) => { $.removeData(this._element, DATA_KEY) $(this._element).off(EVENT_KEY) this._element = null + this._menu = null + if (this._popper !== null) { + this._popper.destroy() + } } @@ -136,15 +187,40 @@ const Dropdown = (($) => { $(this._element).on(Event.CLICK, this.toggle) } + _getConfig(config) { + config = $.extend( + {}, + this.constructor.Default, + $(this._element).data(), + config + ) + + Util.typeCheckConfig( + NAME, + config, + this.constructor.DefaultType + ) + + return config + } + + _getMenuElement() { + if (!this._menu) { + let parent = Dropdown._getParentFromElement(this._element) + this._menu = $(parent).find(Selector.MENU)[0] + } + return this._menu + } // static static _jQueryInterface(config) { return this.each(function () { let data = $(this).data(DATA_KEY) + let _config = typeof config === 'object' ? config : null if (!data) { - data = new Dropdown(this) + data = new Dropdown(this, _config) $(this).data(DATA_KEY, data) } @@ -164,13 +240,18 @@ const Dropdown = (($) => { } const toggles = $.makeArray($(Selector.DATA_TOGGLE)) - for (let i = 0; i < toggles.length; i++) { const parent = Dropdown._getParentFromElement(toggles[i]) + let context = $(toggles[i]).data(DATA_KEY) const relatedTarget = { relatedTarget : toggles[i] } + if (!context) { + continue + } + + let dropdownMenu = context._menu if (!$(parent).hasClass(ClassName.SHOW)) { continue } @@ -195,6 +276,7 @@ const Dropdown = (($) => { toggles[i].setAttribute('aria-expanded', 'false') + $(dropdownMenu).removeClass(ClassName.SHOW) $(parent) .removeClass(ClassName.SHOW) .trigger($.Event(Event.HIDDEN, relatedTarget)) diff --git a/js/src/tooltip.js b/js/src/tooltip.js index c380f8675f92..2c22a7ed4120 100644 --- a/js/src/tooltip.js +++ b/js/src/tooltip.js @@ -14,7 +14,7 @@ const Tooltip = (($) => { /** * Check for Popper dependency - * Tether - https://popper.js.org + * Popper - https://popper.js.org */ if (typeof Popper === 'undefined') { throw new Error('Bootstrap tooltips require Popper (https://popper.js.org)') diff --git a/js/tests/visual/dropdown.html b/js/tests/visual/dropdown.html index cc8a6e709c2a..d96b367e9919 100644 --- a/js/tests/visual/dropdown.html +++ b/js/tests/visual/dropdown.html @@ -61,6 +61,7 @@

Dropdown Bootstrap Visual Test

+ diff --git a/scss/_dropdown.scss b/scss/_dropdown.scss index 3c5a5c66ed70..2c57f0209c65 100644 --- a/scss/_dropdown.scss +++ b/scss/_dropdown.scss @@ -100,11 +100,6 @@ // Open state for the dropdown .show { - // Show the menu - > .dropdown-menu { - display: block; - } - // Remove the outline when :focus is triggered > a { outline: 0; @@ -125,6 +120,10 @@ left: 0; } +.dropdown-menu.show { + display: block; +} + // Dropdown section headers .dropdown-header { display: block; @@ -139,11 +138,4 @@ // // Just add .dropup after the standard .dropdown class and you're set. -.dropup { - // Different positioning for bottom up menu - .dropdown-menu { - top: auto; - bottom: 100%; - margin-bottom: $dropdown-margin-top; - } -} +.dropup {} From 6d39a0ee792bbae0bc19c02f6b46271df2ec623f Mon Sep 17 00:00:00 2001 From: Johann-S Date: Fri, 14 Apr 2017 12:05:54 +0200 Subject: [PATCH 06/26] Remove constraints option and check every options --- js/src/dropdown.js | 14 ++++++-------- js/src/tooltip.js | 12 ++++++------ 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/js/src/dropdown.js b/js/src/dropdown.js index a2b5561c2720..ad5ee8d9fcf0 100644 --- a/js/src/dropdown.js +++ b/js/src/dropdown.js @@ -63,17 +63,13 @@ const Dropdown = (($) => { } const Default = { - animation : true, - trigger : 'click', placement : 'bottom', - offset : '0 0' + offset : {} } const DefaultType = { - animation : 'boolean', - trigger : 'string', placement : 'string', - offset : 'string' + offset : 'number' } @@ -145,8 +141,10 @@ const Dropdown = (($) => { this._popper = new Popper(this, context._menu, { placement : context._config.placement, - offsets : { - popper : context._config.offset + modifiers : { + offset : { + offset : this.config.offset + } } }) diff --git a/js/src/tooltip.js b/js/src/tooltip.js index 2c22a7ed4120..5f5e3d7bcbe1 100644 --- a/js/src/tooltip.js +++ b/js/src/tooltip.js @@ -47,8 +47,7 @@ const Tooltip = (($) => { html : false, selector : false, placement : 'top', - offset : '0 0', - constraints : [], + offset : {}, container : false } @@ -61,8 +60,7 @@ const Tooltip = (($) => { html : 'boolean', selector : '(string|boolean)', placement : '(string|function)', - offset : 'string', - constraints : 'array', + offset : 'number', container : '(string|element|boolean)' } @@ -285,8 +283,10 @@ const Tooltip = (($) => { this._popper = new Popper(this.element, tip, { placement : attachment, - offsets : { - popper : this.config.offset + modifiers : { + offset : { + offset : this.config.offset + } } }) From 7dd6936c4e9fd415b4ec701f44b66609c8d7b443 Mon Sep 17 00:00:00 2001 From: Johann-S Date: Fri, 14 Apr 2017 13:30:55 +0200 Subject: [PATCH 07/26] Fix unit tests + Update Popper to 1.6.0 --- docs/assets/js/vendor/popper.min.js | 4 +- js/src/dropdown.js | 14 ++++--- js/src/tooltip.js | 2 +- js/tests/unit/dropdown.js | 48 +++++++++++----------- js/tests/unit/popover.js | 15 ++++--- js/tests/unit/tooltip.js | 64 +++-------------------------- js/tests/visual/tooltip.html | 18 ++++++++ scss/_dropdown.scss | 2 +- 8 files changed, 70 insertions(+), 97 deletions(-) diff --git a/docs/assets/js/vendor/popper.min.js b/docs/assets/js/vendor/popper.min.js index 22ac698abe70..fffdb1d1bf78 100644 --- a/docs/assets/js/vendor/popper.min.js +++ b/docs/assets/js/vendor/popper.min.js @@ -1,3 +1,3 @@ -(function(e,t){'object'==typeof exports&&'undefined'!=typeof module?module.exports=t():'function'==typeof define&&define.amd?define(t):e.Popper=t()})(this,function(){'use strict';function e(he){const ce=he.offsetParent,ue=ce&&ce.nodeName;return ue&&'BODY'!==ue&&'HTML'!==ue?ce:window.document.documentElement}function t(he,ce){if(1!==he.nodeType)return[];const ue=window.getComputedStyle(he,null);return ce?ue[ce]:ue}function o(he){return'HTML'===he.nodeName?he:he.parentNode||he.host}function r(he){if(!he||-1!==['HTML','BODY','#document'].indexOf(he.nodeName))return window.document.body;const{overflow:ce,overflowX:ue,overflowY:ge}=t(he);return /(auto|scroll)/.test(ce+ge+ue)?he:r(o(he))}function s(he){const ce=he.nodeName;return'BODY'===ce||'HTML'===ce?!1:'fixed'===t(he,'position')||s(o(he))}function p(he){const ce=e(he),ue=s(ce);return ue?'fixed':'absolute'}function f(he,ce){const ue='x'===ce?'Left':'Top',ge='Left'==ue?'Right':'Bottom';return+he[`border${ue}Width`].split('px')[0]+ +he[`border${ge}Width`].split('px')[0]}function d(he){const ce=-1!==navigator.appVersion.indexOf('MSIE 10');let ue;if(ce)try{ue=he.getBoundingClientRect()}catch(xe){ue={}}else ue=he.getBoundingClientRect();const ge={left:ue.left,top:ue.top,right:ue.right,bottom:ue.bottom,width:ue.right-ue.left,height:ue.bottom-ue.top};if('HTML'===he.nodeName&&ce){const{scrollTop:xe,scrollLeft:ye}=window.document.documentElement;ge.top-=xe,ge.bottom-=xe,ge.left-=ye,ge.right-=ye}let be=ue.width-(he.clientWidth||ue.right-ue.left),we=ue.height-(he.clientHeight||ue.bottom-ue.top);if(be||we){const xe=t(he);be-=f(xe,'x'),we-=f(xe,'y')}return ge.right-=be,ge.width-=be,ge.bottom-=we,ge.height-=we,ge}function l(he,ce='top'){const ue='top'===ce?'scrollTop':'scrollLeft',ge=he.nodeName;if('BODY'===ge||'HTML'===ge){const be=window.document.documentElement,we=window.document.scrollingElement||be;return we[ue]}return he[ue]}function m(he,ce,ue=!1){const ge=l(ce,'top'),be=l(ce,'left'),we=ue?-1:1;return he.top+=ge*we,he.bottom+=ge*we,he.left+=be*we,he.right+=be*we,he}function h(he,ce,ue=!1,ge=!1){const be=r(ce),we=d(he),xe=d(ce);let ye={top:we.top-xe.top,left:we.left-xe.left,bottom:we.top-xe.top+we.height,right:we.left-xe.left+we.width,width:we.width,height:we.height};ue&&!ge?ye=m(ye,be,!0):e(he).contains(be)&&'BODY'!==be.nodeName&&(ye=m(ye,ce));const ve=t(ce),Oe=+ve.borderTopWidth.split('px')[0],Ee=+ve.borderLeftWidth.split('px')[0];return ye.top-=Oe,ye.bottom-=Oe,ye.left-=Ee,ye.right-=Ee,ye}function c(){const he=window.document.body,ce=window.document.documentElement;return{height:Math.max(he.scrollHeight,he.offsetHeight,ce.clientHeight,ce.scrollHeight,ce.offsetHeight),width:Math.max(he.scrollWidth,he.offsetWidth,ce.clientWidth,ce.scrollWidth,ce.offsetWidth)}}function u(he){let ce;if('HTML'===he.nodeName){const{width:ue,height:ge}=c();ce={width:ue,height:ge,left:0,top:0}}else ce={width:he.offsetWidth,height:he.offsetHeight,left:he.offsetLeft,top:he.offsetTop};return ce.right=ce.left+ce.width,ce.bottom=ce.top+ce.height,ce}function g(he){const ce=u(he);if('HTML'!==he.nodeName){const ue=e(he),ge=g(ue),be={width:ce.offsetWidth,height:ce.offsetHeight,left:ce.left+ge.left,top:ce.top+ge.top,right:ce.right-ge.right,bottom:ce.bottom-ge.bottom};return be}return ce}function w(he,ce='top'){const ue=r(he),ge=l(ue,ce);return-1===['BODY','HTML'].indexOf(ue.nodeName)?ge+w(o(ue),ce):ge}function v(he,ce,ue){let ge={top:0,left:0};const be=e(he);if('viewport'===ue){const{left:we,top:xe}=g(be),{clientWidth:ye,clientHeight:ve}=window.document.documentElement;if('fixed'===p(he))ge.right=ye,ge.bottom=ve;else{const Oe=w(he,'left'),Ee=w(he,'top');ge={top:0-xe,right:ye-we+Oe,bottom:ve-xe+Ee,left:0-we}}}else{let we;if(we='scrollParent'===ue?r(o(he)):'window'===ue?window.document.body:ue,'BODY'===we.nodeName){const{height:xe,width:ye}=c();ge.right=ye,ge.bottom=xe}else ge=h(we,be,s(he))}return ge.left+=ce,ge.top+=ce,ge.right-=ce,ge.bottom-=ce,ge}function O(he,ce,ue){if(-1===he.indexOf('auto'))return he;const ge=v(ue,0,'scrollParent'),be={top:ce.top-ge.top,right:ge.right-ce.right,bottom:ge.bottom-ce.bottom,left:ce.left-ge.left},we=Object.keys(be).sort((ye,ve)=>be[ve]-be[ye])[0],xe=he.split('-')[1];return we+(xe?`-${xe}`:'')}function N(he,ce){return Array.prototype.find?he.find(ce):he.filter(ce)[0]}function L(he,ce,ue){if(Array.prototype.findIndex)return he.findIndex((be)=>be[ce]===ue);const ge=N(he,(be)=>be[ce]===ue);return he.indexOf(ge)}function T(he){return fe({},he,{right:he.left+he.width,bottom:he.top+he.height})}function P(he){const ce=window.getComputedStyle(he),ue=parseFloat(ce.marginTop)+parseFloat(ce.marginBottom),ge=parseFloat(ce.marginLeft)+parseFloat(ce.marginRight),be={width:he.offsetWidth+ge,height:he.offsetHeight+ue};return be}function B(he){const ce={left:'right',right:'left',bottom:'top',top:'bottom'};return he.replace(/left|right|bottom|top/g,(ue)=>ce[ue])}function H(he,ce,ue,ge){ge=ge.split('-')[0];const be=P(ce),we={position:he,width:be.width,height:be.height},xe=-1!==['right','left'].indexOf(ge),ye=xe?'top':'left',ve=xe?'left':'top',Oe=xe?'height':'width',Ee=xe?'width':'height';return we[ye]=ue[ye]+ue[Oe]/2-be[Oe]/2,we[ve]=ge===ve?ue[ve]-be[Ee]:ue[B(ve)],we}function W(he,ce,ue){const ge='fixed'===he.position,be=he.isParentTransformed,we=e(ge&&be?ue:ce);return h(ue,we,ge,be)}function D(he){const ce=[!1,'ms','webkit','moz','o'],ue=he.charAt(0).toUpperCase()+he.slice(1);for(let ge=0;gege&&ue===ce)}function R(he,ce,ue){const ge=N(he,({name:be})=>be===ce);return!!ge&&he.some((be)=>{return be.name===ue&&be.enabled&&be.order{ue.removeEventListener('scroll',ce.updateBound)}),ce.updateBound=null,ce.scrollParents=[],ce.scrollElement=null,ce.eventsEnabled=!1,ce}function I(he,ce,ue){const ge=void 0===ue?he:he.slice(0,L(he,'name',ue));return ge.forEach((be)=>{be.enabled&&C(be.function)&&(ce=be.function(ce,be))}),ce}function U(he,ce){Object.keys(ce).forEach(function(ue){const ge=ce[ue];!1===ge?he.removeAttribute(ue):he.setAttribute(ue,ce[ue])})}function q(he,ce){Object.keys(ce).forEach((ue)=>{let ge='';-1!==['width','height','top','right','bottom','left'].indexOf(ue)&&A(ce[ue])&&(ge='px'),he.style[ue]=ce[ue]+ge})}function z(he,ce,ue,ge){const be='BODY'===he.nodeName,we=be?window:he;we.addEventListener(ce,ue,{passive:!0}),be||z(r(we.parentNode),ce,ue,ge),ge.push(we)}function F(he,ce,ue,ge){ue.updateBound=ge,window.addEventListener('resize',ue.updateBound,{passive:!0});const be=r(he);return z(be,'scroll',ue.updateBound,ue.scrollParents),ue.scrollElement=be,ue.eventsEnabled=!0,ue}function X(he){return'end'===he?'start':'start'===he?'end':he}const te=['native code','[object MutationObserverConstructor]'];var oe=(he)=>te.some((ce)=>-1<(he||'').toString().indexOf(ce));const ie='undefined'!=typeof window,re=['Edge','Trident','Firefox'];let ne=0;for(let he=0;he{he(),ce=!1});return be.observe(ge,{attributes:!0}),()=>{ce||(ce=!0,ge.setAttribute('x-index',ue),++ue)}}:function(he){let ce=!1;return()=>{ce||(ce=!0,setTimeout(()=>{ce=!1,he()},ne))}},fe=Object.assign||function(he){for(var ue,ce=1;cerequestAnimationFrame(this.update),this.update=pe(this.update.bind(this)),this.options=fe({},me.Defaults,ue),this.state={isDestroyed:!1,isCreated:!1,scrollParents:[]},this.reference=he.jquery?he[0]:he,this.popper=ce.jquery?ce[0]:ce,this.modifiers=Object.keys(me.Defaults.modifiers).map((be)=>fe({name:be},me.Defaults.modifiers[be])),this.modifiers=this.modifiers.map((be)=>{const we=ue.modifiers&&ue.modifiers[be.name]||{};return fe({},be,we)}),ue.modifiers&&(this.options.modifiers=fe({},me.Defaults.modifiers,ue.modifiers),Object.keys(ue.modifiers).forEach((be)=>{if(void 0===me.Defaults.modifiers[be]){const we=ue.modifiers[be];we.name=be,this.modifiers.push(we)}})),this.state.position=p(this.reference),this.modifiers=this.modifiers.sort((be,we)=>be.order-we.order),this.modifiers.forEach((be)=>{be.enabled&&C(be.onLoad)&&be.onLoad(this.reference,this.popper,this.options,be,this.state)}),this.state.isParentTransformed=k(this.popper.parentNode),this.update();const ge=this.options.eventsEnabled;ge&&this.enableEventListeners(),this.state.eventsEnabled=ge}update(){if(!this.state.isDestroyed){let he={instance:this,styles:{},attributes:{},flipped:!1,offsets:{}};this.state.position=p(this.reference),q(this.popper,{position:this.state.position}),he.offsets.reference=W(this.state,this.popper,this.reference),he.placement=O(this.options.placement,he.offsets.reference,this.popper),he.originalPlacement=this.options.placement,he.offsets.popper=H(this.state,this.popper,he.offsets.reference,he.placement),he=I(this.modifiers,he),this.state.isCreated?this.options.onUpdate(he):(this.state.isCreated=!0,this.options.onCreate(he))}}destroy(){return this.state.isDestroyed=!0,M(this.modifiers,'applyStyle')&&(this.popper.removeAttribute('x-placement'),this.popper.style.left='',this.popper.style.position='',this.popper.style.top='',this.popper.style[D('transform')]=''),this.disableEventListeners(),this.options.removeOnDestroy&&this.popper.parentNode.removeChild(this.popper),this}enableEventListeners(){this.state.eventsEnabled||(this.state=F(this.reference,this.options,this.state,this.scheduleUpdate))}disableEventListeners(){this.state.eventsEnabled&&(window.cancelAnimationFrame(this.scheduleUpdate),this.state=Y(this.reference,this.state))}}return me.Utils={computeAutoPlacement:O,debounce:pe,findIndex:L,getBordersSize:f,getBoundaries:v,getBoundingClientRect:d,getClientRect:T,getOffsetParent:e,getOffsetRect:u,getOffsetRectRelativeToCustomParent:h,getOuterSizes:P,getParentNode:o,getPopperOffsets:H,getPosition:p,getReferenceOffsets:W,getScroll:l,getScrollParent:r,getStyleComputedProperty:t,getSupportedPropertyName:D,getTotalScroll:w,getWindowSizes:c,includeScroll:m,isFixed:s,isFunction:C,isModifierEnabled:M,isModifierRequired:R,isNative:oe,isNumeric:A,isTransformed:k,removeEventListeners:Y,runModifiers:I,setAttributes:U,setStyles:q,setupEventListeners:F},me.placements=['auto','auto-start','auto-end','top','top-start','top-end','right','right-start','right-end','bottom','bottom-start','bottom-end','left','left-start','left-end'],me.Defaults={placement:'bottom',eventsEnabled:!0,onCreate:()=>{},onUpdate:()=>{},modifiers:{shift:{order:100,enabled:!0,function:function(he){const ce=he.placement,ue=ce.split('-')[0],ge=ce.split('-')[1];if(ge){const be=he.offsets.reference,we=T(he.offsets.popper),xe=-1!==['bottom','top'].indexOf(ue),ye=xe?'left':'top',ve=xe?'width':'height',Oe={start:{[ye]:be[ye]},end:{[ye]:be[ye]+be[ve]-we[ve]}};he.offsets.popper=fe({},we,Oe[ge])}return he}},offset:{order:200,enabled:!0,function:function(he,ce){const ue=he.placement,ge=he.offsets.popper;let be;return A(ce.offset)?be=[ce.offset,0]:(be=ce.offset.split(' '),be=be.map((we,xe)=>{const ye=we.match(/(\d*\.?\d*)(.*)/),ve=+ye[1],Oe=ye[2];let Ee=-1!==ue.indexOf('right')||-1!==ue.indexOf('left');1===xe&&(Ee=!Ee);const Se=Ee?'height':'width';if(0===Oe.indexOf('%')){let Ne;switch(Oe){case'%p':Ne=he.offsets.popper;break;case'%':case'$r':default:Ne=he.offsets.reference;}const Le=T(Ne),Te=Le[Se];return Te/100*ve}if('vh'===Oe||'vw'===Oe){let Ne;return Ne='vh'===Oe?Math.max(document.documentElement.clientHeight,window.innerHeight||0):Math.max(document.documentElement.clientWidth,window.innerWidth||0),Ne/100*ve}return'px'===Oe?+ve:+we})),-1===he.placement.indexOf('left')?-1===he.placement.indexOf('right')?-1===he.placement.indexOf('top')?-1!==he.placement.indexOf('bottom')&&(ge.left+=be[0],ge.top+=be[1]||0):(ge.left+=be[0],ge.top-=be[1]||0):(ge.top+=be[0],ge.left+=be[1]||0):(ge.top+=be[0],ge.left-=be[1]||0),he},offset:0},preventOverflow:{order:300,enabled:!0,function:function(he,ce){const ue=ce.boundariesElement||e(he.instance.popper),ge=v(he.instance.popper,ce.padding,ue);ce.boundaries=ge;const be=ce.priority;let we=T(he.offsets.popper);const xe={primary(ye){let ve=we[ye];return we[ye]ge[ye]&&!ce.escapeWithReference&&(Oe=Math.min(we[ve],ge[ye]-('right'===ye?we.width:we.height))),{[ve]:Oe}}};return be.forEach((ye)=>{const ve=-1===['left','top'].indexOf(ye)?'secondary':'primary';we=fe({},we,xe[ve](ye))}),he.offsets.popper=we,he},priority:['left','right','top','bottom'],padding:5,boundariesElement:'scrollParent'},keepTogether:{order:400,enabled:!0,function:function(he){const ce=T(he.offsets.popper),ue=he.offsets.reference,ge=he.placement.split('-')[0],be=Math.floor,we=-1!==['top','bottom'].indexOf(ge),xe=we?'right':'bottom',ye=we?'left':'top',ve=we?'width':'height';return ce[xe]be(ue[xe])&&(he.offsets.popper[ye]=be(ue[xe])),he}},arrow:{order:500,enabled:!0,function:function(he,ce){if(!R(he.instance.modifiers,'arrow','keepTogether'))return console.warn('WARNING: `keepTogether` modifier is required by arrow modifier in order to work, be sure to include it before `arrow`!'),he;let ue=ce.element;if('string'==typeof ue){if(ue=he.instance.popper.querySelector(ue),!ue)return he;}else if(!he.instance.popper.contains(ue))return console.warn('WARNING: `arrow.element` must be child of its popper element!'),he;const ge=he.placement.split('-')[0],be=T(he.offsets.popper),we=he.offsets.reference,xe=-1!==['left','right'].indexOf(ge),ye=xe?'height':'width',ve=xe?'top':'left',Oe=xe?'left':'top',Ee=xe?'bottom':'right',Se=P(ue)[ye];we[Ee]-Sebe[Ee]&&(he.offsets.popper[ve]+=we[ve]+Se-be[Ee]);const Ne=we[ve]+we[ye]/2-Se/2;let Le=Ne-T(he.offsets.popper)[ve];return Le=Math.max(Math.min(be[ye]-Se,Le),0),he.arrowElement=ue,he.offsets.arrow={},he.offsets.arrow[ve]=Le,he.offsets.arrow[Oe]='',he},element:'[x-arrow]'},flip:{order:600,enabled:!0,function:function(he,ce){if(M(he.instance.modifiers,'inner'))return he;if(he.flipped&&he.placement===he.originalPlacement)return he;const ue=v(he.instance.popper,ce.padding,ce.boundariesElement);let ge=he.placement.split('-')[0],be=B(ge),we=he.placement.split('-')[1]||'',xe=[];return xe='flip'===ce.behavior?[ge,be]:ce.behavior,xe.forEach((ye,ve)=>{if(ge!==ye||xe.length===ve+1)return he;ge=he.placement.split('-')[0],be=B(ge);const Oe=T(he.offsets.popper),Ee=he.offsets.reference,Se=Math.floor,Ne='left'===ge&&Se(Oe.right)>Se(Ee.left)||'right'===ge&&Se(Oe.left)Se(Ee.top)||'bottom'===ge&&Se(Oe.top)Se(ue.right),Pe=Se(Oe.top)Se(ue.bottom),He='left'===ge&&Le||'right'===ge&&Te||'top'===ge&&Pe||'bottom'===ge&&Be,We=-1!==['top','bottom'].indexOf(ge),De=!!ce.flipVariations&&(We&&'start'===we&&Le||We&&'end'===we&&Te||!We&&'start'===we&&Pe||!We&&'end'===we&&Be);(Ne||He||De)&&(he.flipped=!0,(Ne||He)&&(ge=xe[ve+1]),De&&(we=X(we)),he.placement=ge+(we?'-'+we:''),he.offsets.popper=H(he.instance.state.position,he.instance.popper,he.offsets.reference,he.placement),he=I(he.instance.modifiers,he,'flip'))}),he},behavior:'flip',padding:5,boundariesElement:'viewport'},inner:{order:700,enabled:!1,function:function(he){const ce=he.placement,ue=ce.split('-')[0],ge=T(he.offsets.popper),be=T(he.offsets.reference),we=-1!==['left','right'].indexOf(ue),xe=-1===['top','left'].indexOf(ue);return ge[we?'left':'top']=be[ce]-(xe?ge[we?'width':'height']:0),he.placement=B(ce),he.offsets.popper=T(ge),he}},hide:{order:800,enabled:!0,function:function(he){if(!R(he.instance.modifiers,'hide','preventOverflow'))return console.warn('WARNING: preventOverflow modifier is required by hide modifier in order to work, be sure to include it before hide!'),he;const ce=he.offsets.reference,ue=N(he.instance.modifiers,(ge)=>'preventOverflow'===ge.name).boundaries;if(ce.bottomue.right||ce.top>ue.bottom||ce.rightve[Ne]&&!we.escapeWithReference&&(Pe=_Mathmin(Ee[Te],ve[Ne]-('right'===Ne?Ee.width:Ee.height))),ne({},Te,Pe)}};return Oe.forEach(function(Le){var Ne=-1===['left','top'].indexOf(Le)?'secondary':'primary';Ee=re({},Ee,Se[Ne](Le))}),ye.offsets.popper=Ee,ye},priority:['left','right','top','bottom'],padding:5,boundariesElement:'scrollParent'},keepTogether:{order:400,enabled:!0,function:function(ye){var we=h(ye.offsets.popper),xe=ye.offsets.reference,ve=ye.placement.split('-')[0],Oe=_Mathfloor,Ee=-1!==['top','bottom'].indexOf(ve),Se=Ee?'right':'bottom',Le=Ee?'left':'top',Ne=Ee?'width':'height';return we[Se]Oe(xe[Se])&&(ye.offsets.popper[Le]=Oe(xe[Se])),ye}},arrow:{order:500,enabled:!0,function:function(ye,we){if(!R(ye.instance.modifiers,'arrow','keepTogether'))return console.warn('WARNING: `keepTogether` modifier is required by arrow modifier in order to work, be sure to include it before `arrow`!'),ye;var xe=we.element;if('string'==typeof xe){if(xe=ye.instance.popper.querySelector(xe),!xe)return ye;}else if(!ye.instance.popper.contains(xe))return console.warn('WARNING: `arrow.element` must be child of its popper element!'),ye;var ve=ye.placement.split('-')[0],Oe=h(ye.offsets.popper),Ee=ye.offsets.reference,Se=-1!==['left','right'].indexOf(ve),Le=Se?'height':'width',Ne=Se?'top':'left',Te=Se?'left':'top',Pe=Se?'bottom':'right',We=W(xe)[Le];Ee[Pe]-WeOe[Pe]&&(ye.offsets.popper[Ne]+=Ee[Ne]+We-Oe[Pe]);var He=Ee[Ne]+Ee[Le]/2-We/2,Be=He-h(ye.offsets.popper)[Ne];return Be=_Mathmax(_Mathmin(Oe[Le]-We,Be),0),ye.arrowElement=xe,ye.offsets.arrow={},ye.offsets.arrow[Ne]=Be,ye.offsets.arrow[Te]='',ye},element:'[x-arrow]'},flip:{order:600,enabled:!0,function:function(ye,we){if(A(ye.instance.modifiers,'inner'))return ye;if(ye.flipped&&ye.placement===ye.originalPlacement)return ye;var xe=O(ye.instance.popper,ye.instance.reference,we.padding,we.boundariesElement),ve=ye.placement.split('-')[0],Oe=H(ve),Ee=ye.placement.split('-')[1]||'',Se=[];return Se='flip'===we.behavior?[ve,Oe]:we.behavior,Se.forEach(function(Le,Ne){if(ve!==Le||Se.length===Ne+1)return ye;ve=ye.placement.split('-')[0],Oe=H(ve);var Te=h(ye.offsets.popper),Pe=ye.offsets.reference,We=_Mathfloor,He='left'===ve&&We(Te.right)>We(Pe.left)||'right'===ve&&We(Te.left)We(Pe.top)||'bottom'===ve&&We(Te.top)We(xe.right),De=We(Te.top)We(xe.bottom),ke='left'===ve&&Be||'right'===ve&&Ce||'top'===ve&&De||'bottom'===ve&&Me,Ae=-1!==['top','bottom'].indexOf(ve),Re=!!we.flipVariations&&(Ae&&'start'===Ee&&Be||Ae&&'end'===Ee&&Ce||!Ae&&'start'===Ee&&De||!Ae&&'end'===Ee&&Me);(He||ke||Re)&&(ye.flipped=!0,(He||ke)&&(ve=Se[Ne+1]),Re&&(Ee=X(Ee)),ye.placement=ve+(Ee?'-'+Ee:''),ye.offsets.popper=B(ye.instance.state.position,ye.instance.popper,ye.offsets.reference,ye.placement),ye=U(ye.instance.modifiers,ye,'flip'))}),ye},behavior:'flip',padding:5,boundariesElement:'viewport'},inner:{order:700,enabled:!1,function:function(ye){var we=ye.placement,xe=we.split('-')[0],ve=h(ye.offsets.popper),Oe=h(ye.offsets.reference),Ee=-1!==['left','right'].indexOf(xe),Se=-1===['top','left'].indexOf(xe);return ve[Ee?'left':'top']=Oe[we]-(Se?ve[Ee?'width':'height']:0),ye.placement=H(we),ye.offsets.popper=h(ve),ye}},hide:{order:800,enabled:!0,function:function(ye){if(!R(ye.instance.modifiers,'hide','preventOverflow'))return console.warn('WARNING: preventOverflow modifier is required by hide modifier in order to work, be sure to include it before hide!'),ye;var we=ye.offsets.reference,xe=N(ye.instance.modifiers,function(ve){return'preventOverflow'===ve.name}).boundaries;if(we.bottomxe.right||we.top>xe.bottom||we.right { const Default = { placement : 'bottom', - offset : {} + offset : 0 } const DefaultType = { @@ -143,7 +145,7 @@ const Dropdown = (($) => { placement : context._config.placement, modifiers : { offset : { - offset : this.config.offset + offset : context._config.offset } } }) @@ -204,7 +206,7 @@ const Dropdown = (($) => { _getMenuElement() { if (!this._menu) { - let parent = Dropdown._getParentFromElement(this._element) + const parent = Dropdown._getParentFromElement(this._element) this._menu = $(parent).find(Selector.MENU)[0] } return this._menu @@ -215,7 +217,7 @@ const Dropdown = (($) => { static _jQueryInterface(config) { return this.each(function () { let data = $(this).data(DATA_KEY) - let _config = typeof config === 'object' ? config : null + const _config = typeof config === 'object' ? config : null if (!data) { data = new Dropdown(this, _config) @@ -240,7 +242,7 @@ const Dropdown = (($) => { const toggles = $.makeArray($(Selector.DATA_TOGGLE)) for (let i = 0; i < toggles.length; i++) { const parent = Dropdown._getParentFromElement(toggles[i]) - let context = $(toggles[i]).data(DATA_KEY) + const context = $(toggles[i]).data(DATA_KEY) const relatedTarget = { relatedTarget : toggles[i] } @@ -249,7 +251,7 @@ const Dropdown = (($) => { continue } - let dropdownMenu = context._menu + const dropdownMenu = context._menu if (!$(parent).hasClass(ClassName.SHOW)) { continue } diff --git a/js/src/tooltip.js b/js/src/tooltip.js index 5f5e3d7bcbe1..9995cede7480 100644 --- a/js/src/tooltip.js +++ b/js/src/tooltip.js @@ -47,7 +47,7 @@ const Tooltip = (($) => { html : false, selector : false, placement : 'top', - offset : {}, + offset : 0, container : false } diff --git a/js/tests/unit/dropdown.js b/js/tests/unit/dropdown.js index a15eb52450d6..1dd675b0b685 100644 --- a/js/tests/unit/dropdown.js +++ b/js/tests/unit/dropdown.js @@ -275,20 +275,20 @@ $(function () { $first.parent('.dropdown') .on('shown.bs.dropdown', function () { assert.strictEqual($first.parents('.show').length, 1, '"show" class added on click') - assert.strictEqual($('#qunit-fixture .show').length, 1, 'only one dropdown is shown') + assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 1, 'only one dropdown is shown') $(document.body).trigger('click') }).on('hidden.bs.dropdown', function () { - assert.strictEqual($('#qunit-fixture .show').length, 0, '"show" class removed') + assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 0, '"show" class removed') $last.trigger('click') }) $last.parent('.btn-group') .on('shown.bs.dropdown', function () { assert.strictEqual($last.parent('.show').length, 1, '"show" class added on click') - assert.strictEqual($('#qunit-fixture .show').length, 1, 'only one dropdown is shown') + assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 1, 'only one dropdown is shown') $(document.body).trigger('click') }).on('hidden.bs.dropdown', function () { - assert.strictEqual($('#qunit-fixture .show').length, 0, '"show" class removed') + assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 0, '"show" class removed') done() }) $first.trigger('click') @@ -321,24 +321,24 @@ $(function () { $first.parent('.dropdown') .on('shown.bs.dropdown', function () { assert.strictEqual($first.parents('.show').length, 1, '"show" class added on click') - assert.strictEqual($('#qunit-fixture .show').length, 1, 'only one dropdown is shown') + assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 1, 'only one dropdown is shown') var e = $.Event('keyup') e.which = 9 // Tab $(document.body).trigger(e) }).on('hidden.bs.dropdown', function () { - assert.strictEqual($('#qunit-fixture .show').length, 0, '"show" class removed') + assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 0, '"show" class removed') $last.trigger('click') }) $last.parent('.btn-group') .on('shown.bs.dropdown', function () { assert.strictEqual($last.parent('.show').length, 1, '"show" class added on click') - assert.strictEqual($('#qunit-fixture .show').length, 1, 'only one dropdown is shown') + assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 1, 'only one dropdown is shown') var e = $.Event('keyup') e.which = 9 // Tab $(document.body).trigger(e) }).on('hidden.bs.dropdown', function () { - assert.strictEqual($('#qunit-fixture .show').length, 0, '"show" class removed') + assert.strictEqual($('#qunit-fixture .dropdown-menu.show').length, 0, '"show" class removed') done() }) $first.trigger('click') @@ -552,7 +552,7 @@ $(function () { }) QUnit.test('should not close the dropdown if the user clicks on a text field', function (assert) { - assert.expect(1) + assert.expect(2) var done = assert.async() var dropdownHTML = '