From 3c4e09a34b36f6f46d80b37882ded36aa20b35f5 Mon Sep 17 00:00:00 2001 From: sam marshall Date: Mon, 28 Apr 2025 09:49:51 +0100 Subject: [PATCH] MDL-85287 User tours: Avoid scrolling while backdrop is displayed If the page scrolls while the backdrop is displayed, it looks incorrect because the backdrop does not scroll with page content. To avoid this, don't show the backdrop until scrolling has finished. --- public/admin/tool/usertours/amd/build/tour.min.js | 2 +- public/admin/tool/usertours/amd/build/tour.min.js.map | 2 +- public/admin/tool/usertours/amd/src/tour.js | 4 +--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/public/admin/tool/usertours/amd/build/tour.min.js b/public/admin/tool/usertours/amd/build/tour.min.js index dc6f6196126..9e0d8d5ebc3 100644 --- a/public/admin/tool/usertours/amd/build/tour.min.js +++ b/public/admin/tool/usertours/amd/build/tour.min.js @@ -1,3 +1,3 @@ -define("tool_usertours/tour",["exports","jquery","core/aria","core/popper","core/event_dispatcher","./events","core/str","core/prefetch","core/event","core/pending"],(function(_exports,_jquery,Aria,_popper,_event_dispatcher,_events,_str,_prefetch,_event,_pending){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _defineProperty(obj,key,value){return key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,obj}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_jquery=_interopRequireDefault(_jquery),Aria=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(Aria),_popper=_interopRequireDefault(_popper),_pending=_interopRequireDefault(_pending);var _default=class{constructor(config){_defineProperty(this,"tourRunning",!1),_defineProperty(this,"hasFixedPosition",(targetNode=>{let currentElement=targetNode[0];for(;currentElement;){if("fixed"===window.getComputedStyle(currentElement).position)return!0;currentElement=currentElement.parentElement}return!1})),this.init(config)}init(config){this.eventHandlers={},this.reset(),this.originalConfiguration=config||{},this.configure.apply(this,arguments),this.possitionNeedToBeRecalculated=!1,this.recalculatedNo=0;try{this.storage=window.sessionStorage,this.storageKey="tourstate_"+this.tourName}catch(e){this.storage=!1,this.storageKey=""}return(0,_prefetch.prefetchStrings)("tool_usertours",["nextstep_sequence","skip_tour"]),this}reset(){return this.hide(),this.eventHandlers=[],this.resetStepListeners(),this.originalConfiguration={},this.steps=[],this.currentStepNumber=0,this}configure(config){if("object"==typeof config){if(void 0!==config.tourName&&(this.tourName=config.tourName),config.eventHandlers)for(let eventName in config.eventHandlers)config.eventHandlers[eventName].forEach((function(handler){this.addEventHandler(eventName,handler)}),this);this.resetStepDefaults(!0),"object"==typeof config.steps&&(this.steps=config.steps),void 0!==config.template&&(this.templateContent=config.template)}return this.checkMinimumRequirements(),this}checkMinimumRequirements(){if(!this.tourName)throw new Error("Tour Name required");if(!this.steps||!this.steps.length)throw new Error("Steps must be specified")}resetStepDefaults(loadOriginalConfiguration){return void 0===loadOriginalConfiguration&&(loadOriginalConfiguration=!0),this.stepDefaults={},loadOriginalConfiguration&&void 0!==this.originalConfiguration.stepDefaults?this.setStepDefaults(this.originalConfiguration.stepDefaults):this.setStepDefaults({}),this}setStepDefaults(stepDefaults){return this.stepDefaults||(this.stepDefaults={}),_jquery.default.extend(this.stepDefaults,{element:"",placement:"top",delay:0,moveOnClick:!1,moveAfterTime:0,orphan:!1,direction:1},stepDefaults),this}getCurrentStepNumber(){return parseInt(this.currentStepNumber,10)}setCurrentStepNumber(stepNumber){if(this.currentStepNumber=stepNumber,this.storage)try{this.storage.setItem(this.storageKey,stepNumber)}catch(e){e.code===DOMException.QUOTA_EXCEEDED_ERR&&this.storage.removeItem(this.storageKey)}}getNextStepNumber(stepNumber){void 0===stepNumber&&(stepNumber=this.getCurrentStepNumber());let nextStepNumber=stepNumber+1;for(;nextStepNumber<=this.steps.length;){if(this.isStepPotentiallyVisible(this.getStepConfig(nextStepNumber)))return nextStepNumber;nextStepNumber++}return null}getPreviousStepNumber(stepNumber){void 0===stepNumber&&(stepNumber=this.getCurrentStepNumber());let previousStepNumber=stepNumber-1;for(;previousStepNumber>=0;){if(this.isStepPotentiallyVisible(this.getStepConfig(previousStepNumber)))return previousStepNumber;previousStepNumber--}return null}isLastStep(stepNumber){return null===this.getNextStepNumber(stepNumber)}isStepPotentiallyVisible(stepConfig){return!!stepConfig&&(!!this.isStepActuallyVisible(stepConfig)||(!(void 0===stepConfig.orphan||!stepConfig.orphan)||!(void 0===stepConfig.delay||!stepConfig.delay)))}getPotentiallyVisibleSteps(){let position=1,result=[];for(let stepNumber=0;stepNumber=this.steps.length)return null;let stepConfig=this.normalizeStepConfig(this.steps[stepNumber]);return stepConfig=_jquery.default.extend(stepConfig,{stepNumber:stepNumber}),stepConfig}normalizeStepConfig(stepConfig){return void 0!==stepConfig.reflex&&void 0===stepConfig.moveAfterClick&&(stepConfig.moveAfterClick=stepConfig.reflex),void 0!==stepConfig.element&&void 0===stepConfig.target&&(stepConfig.target=stepConfig.element),void 0!==stepConfig.content&&void 0===stepConfig.body&&(stepConfig.body=stepConfig.content),stepConfig=_jquery.default.extend({},this.stepDefaults,stepConfig),(stepConfig=_jquery.default.extend({},{attachTo:stepConfig.target,attachPoint:"after"},stepConfig)).attachTo&&(stepConfig.attachTo=(0,_jquery.default)(stepConfig.attachTo).first()),stepConfig}getStepTarget(stepConfig){return stepConfig.target?(0,_jquery.default)(stepConfig.target):null}dispatchEvent(eventName){let detail=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},cancelable=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return(0,_event_dispatcher.dispatchEvent)(eventName,{tour:this,...detail},document,{cancelable:cancelable})}addEventHandler(eventName,handler){return void 0===this.eventHandlers[eventName]&&(this.eventHandlers[eventName]=[]),this.eventHandlers[eventName].push(handler),this}processStepListeners(stepConfig){if(this.listeners.push({node:this.currentStepNode,args:["click",'[data-role="next"]',_jquery.default.proxy(this.next,this)]},{node:this.currentStepNode,args:["click",'[data-role="end"]',_jquery.default.proxy(this.endTour,this)]},{node:(0,_jquery.default)('[data-flexitour="backdrop"]'),args:["click",_jquery.default.proxy(this.hide,this)]},{node:(0,_jquery.default)("body"),args:["keydown",_jquery.default.proxy(this.handleKeyDown,this)]}),stepConfig.moveOnClick){var targetNode=this.getStepTarget(stepConfig);this.listeners.push({node:targetNode,args:["click",_jquery.default.proxy((function(e){0===(0,_jquery.default)(e.target).parents('[data-flexitour="container"]').length&&window.setTimeout(_jquery.default.proxy(this.next,this),500)}),this)]})}return this.listeners.forEach((function(listener){listener.node.on.apply(listener.node,listener.args)})),this}resetStepListeners(){return this.listeners&&this.listeners.forEach((function(listener){listener.node.off.apply(listener.node,listener.args)})),this.listeners=[],this}renderStep(stepConfig){this.currentStepConfig=stepConfig,this.setCurrentStepNumber(stepConfig.stepNumber);let template=(0,_jquery.default)(this.getTemplateContent());template.find('[data-placeholder="title"]').html(stepConfig.title),template.find('[data-placeholder="body"]').html(stepConfig.body);const nextBtn=template.find('[data-role="next"]'),endBtn=template.find('[data-role="end"]');if(this.isLastStep(stepConfig.stepNumber)?(nextBtn.hide(),endBtn.removeClass("btn-secondary").addClass("btn-primary")):(nextBtn.prop("disabled",!1),(0,_str.getString)("skip_tour","tool_usertours").then((value=>{endBtn.html(value)})).catch()),nextBtn.attr("role","button"),endBtn.attr("role","button"),this.originalConfiguration.displaystepnumbers){const stepsPotentiallyVisible=this.getPotentiallyVisibleSteps(),totalStepsPotentiallyVisible=stepsPotentiallyVisible.length,position=stepsPotentiallyVisible[stepConfig.stepNumber].position;totalStepsPotentiallyVisible>1&&(0,_str.getString)("nextstep_sequence","tool_usertours",{position:position,total:totalStepsPotentiallyVisible}).then((value=>{nextBtn.html(value)})).catch()}return stepConfig.template=template,this.addStepToPage(stepConfig),this.processStepListeners(stepConfig),this}getTemplateContent(){return(0,_jquery.default)(this.templateContent).clone()}addStepToPage(stepConfig){let currentStepNode=(0,_jquery.default)('').html(stepConfig.template).hide();(0,_event.notifyFilterContentUpdated)(currentStepNode);let animationTarget=(0,_jquery.default)("body, html").stop(!0,!0);if(this.isStepActuallyVisible(stepConfig)){this.getStepTarget(stepConfig).data("flexitour","target"),this.positionBackdrop(stepConfig),(0,_jquery.default)(document.body).append(currentStepNode),this.currentStepNode=currentStepNode,this.currentStepNode.css({top:0,left:0});const pendingPromise=new _pending.default("tool_usertours/tour:addStepToPage-".concat(stepConfig.stepNumber));animationTarget.animate({scrollTop:this.calculateScrollTop(stepConfig)}).promise().then(function(){this.positionStep(stepConfig),this.revealStep(stepConfig),pendingPromise.resolve()}.bind(this)).catch((function(){}))}else stepConfig.orphan&&(stepConfig.isOrphan=!0,stepConfig.attachTo=(0,_jquery.default)("body").first(),stepConfig.attachPoint="append",this.positionBackdrop(stepConfig),currentStepNode.addClass("orphan"),(0,_jquery.default)(document.body).append(currentStepNode),this.currentStepNode=currentStepNode,this.currentStepNode.css("position","fixed"),this.currentStepPopper=new _popper.default((0,_jquery.default)("body"),this.currentStepNode[0],{removeOnDestroy:!0,placement:stepConfig.placement+"-start",arrowElement:'[data-role="arrow"]',modifiers:{hide:{enabled:!1},applyStyle:{onLoad:null,enabled:!1}},onCreate:()=>{const images=this.currentStepNode.find("img");images.length&&images.on("load",(()=>{this.calculateStepPositionInPage(currentStepNode)})),this.calculateStepPositionInPage(currentStepNode)}}),this.revealStep(stepConfig));return this}revealStep(stepConfig){const pendingPromise=new _pending.default("tool_usertours/tour:revealStep-".concat(stepConfig.stepNumber));return this.currentStepNode.fadeIn("",_jquery.default.proxy((function(){this.announceStep(stepConfig),this.currentStepNode.focus(),window.setTimeout(_jquery.default.proxy((function(){this.currentStepNode&&this.currentStepNode.focus(),pendingPromise.resolve()}),this),100)}),this)),this}announceStep(stepConfig){let stepId="tour-step-"+this.tourName+"-"+stepConfig.stepNumber;this.currentStepNode.attr("id",stepId);let bodyRegion=this.currentStepNode.find('[data-placeholder="body"]').first();bodyRegion.attr("id",stepId+"-body"),bodyRegion.attr("role","document");let headerRegion=this.currentStepNode.find('[data-placeholder="title"]').first();headerRegion.attr("id",stepId+"-title"),headerRegion.attr("aria-labelledby",stepId+"-body"),this.currentStepNode.attr("role","dialog"),this.currentStepNode.attr("tabindex",0),this.currentStepNode.attr("aria-labelledby",stepId+"-title"),this.currentStepNode.attr("aria-describedby",stepId+"-body");let target=this.getStepTarget(stepConfig);return target&&(target.data("original-tabindex",target.attr("tabindex")),target.attr("tabindex")||target.attr("tabindex",0),target.data("original-describedby",target.attr("aria-describedby")).attr("aria-describedby",stepId+"-body")),this.accessibilityShow(stepConfig),this}handleKeyDown(e){let tabbableSelector="a[href], link[href], [draggable=true], [contenteditable=true], ";switch(tabbableSelector+=":input:enabled, [tabindex], button:enabled",e.keyCode){case 27:this.endTour();break;case 9:(function(){if(!this.currentStepConfig.hasBackdrop)return;let currentIndex,nextIndex,nextNode,focusRelevant,activeElement=(0,_jquery.default)(document.activeElement),stepTarget=this.getStepTarget(this.currentStepConfig),tabbableNodes=(0,_jquery.default)(tabbableSelector),dialogContainer=(0,_jquery.default)('span[data-flexitour="container"]');if(stepTarget&&(tabbableNodes=tabbableNodes.filter((function(index,element){return null!==stepTarget&&(stepTarget.has(element).length||dialogContainer.has(element).length||stepTarget.is(element)||dialogContainer.is(element))}))),tabbableNodes.each((function(index,element){return!activeElement.is(element)||(currentIndex=index,!1)})),null!=currentIndex){let direction=1;e.shiftKey&&(direction=-1),nextIndex=currentIndex;do{nextIndex+=direction,nextNode=(0,_jquery.default)(tabbableNodes[nextIndex])}while(nextNode.length&&nextNode.is(":disabled")||nextNode.is(":hidden"));nextNode.length?(focusRelevant=nextNode.closest(stepTarget).length,focusRelevant=focusRelevant||nextNode.closest(this.currentStepNode).length):focusRelevant=!1}focusRelevant?nextNode.focus():e.shiftKey?this.currentStepNode.find(tabbableSelector).last().focus():this.currentStepConfig.isOrphan?this.currentStepNode.focus():stepTarget.focus(),e.preventDefault()}).call(this)}}startTour(startAt){if(this.storage&&void 0===startAt){let storageStartValue=this.storage.getItem(this.storageKey);if(storageStartValue){let storageStartAt=parseInt(storageStartValue,10);storageStartAt<=this.steps.length&&(startAt=storageStartAt)}}void 0===startAt&&(startAt=this.getCurrentStepNumber());return this.dispatchEvent(_events.eventTypes.tourStart,{startAt:startAt},!0).defaultPrevented||(this.gotoStep(startAt),this.tourRunning=!0,this.dispatchEvent(_events.eventTypes.tourStarted,{startAt:startAt})),this}restartTour(){return this.startTour(0)}endTour(){if(this.dispatchEvent(_events.eventTypes.tourEnd,{},!0).defaultPrevented)return this;if(this.currentStepConfig){let previousTarget=this.getStepTarget(this.currentStepConfig);previousTarget&&(previousTarget.attr("tabindex")||previousTarget.attr("tabindex","-1"),previousTarget.first().focus())}return this.hide(!0),this.tourRunning=!1,this.dispatchEvent(_events.eventTypes.tourEnded),this}hide(transition){if(this.dispatchEvent(_events.eventTypes.stepHide,{},!0).defaultPrevented)return this;const pendingPromise=new _pending.default("tool_usertours/tour:hide");if(this.currentStepNode&&this.currentStepNode.length&&(this.currentStepNode.hide(),this.currentStepPopper&&this.currentStepPopper.destroy()),this.currentStepConfig){let target=this.getStepTarget(this.currentStepConfig);target&&(target.data("original-labelledby")&&target.attr("aria-labelledby",target.data("original-labelledby")),target.data("original-describedby")&&target.attr("aria-describedby",target.data("original-describedby")),target.data("original-tabindex")?target.attr("tabindex",target.data("tabindex")):window.setTimeout((()=>{target.removeAttr("tabindex")}),400)),this.currentStepConfig=null}(0,_jquery.default)('[data-flexitour="highlight"]').removeAttr("data-flexitour");const backdrop=(0,_jquery.default)('[data-flexitour="backdrop"]');if(backdrop.length)if(transition){const backdropRemovalPromise=new _pending.default("tool_usertours/tour:hide:backdrop");backdrop.fadeOut(400,(function(){(0,_jquery.default)(this).remove(),backdropRemovalPromise.resolve()}))}else backdrop.remove();if(this.currentStepNode&&this.currentStepNode.length){let stepId=this.currentStepNode.attr("id");if(stepId){let currentStepElement='[aria-describedby="'+stepId+'-body"]';(0,_jquery.default)(currentStepElement).removeAttr("tabindex"),(0,_jquery.default)(currentStepElement).removeAttr("aria-describedby")}}return this.resetStepListeners(),this.accessibilityHide(),this.dispatchEvent(_events.eventTypes.stepHidden),this.currentStepNode=null,this.currentStepPopper=null,pendingPromise.resolve(),this}show(){let startAt=this.getCurrentStepNumber();return this.gotoStep(startAt)}getStepContainer(){return(0,_jquery.default)(this.currentStepNode)}calculateScrollTop(stepConfig){let viewportHeight=(0,_jquery.default)(window).height(),targetNode=this.getStepTarget(stepConfig),scrollParent=(0,_jquery.default)(window);targetNode.parents('[data-usertour="scroller"]').length&&(scrollParent=targetNode.parents('[data-usertour="scroller"]'));let scrollTop=scrollParent.scrollTop();return this.hasFixedPosition(targetNode)||(scrollTop="top"===stepConfig.placement?targetNode.offset().top-viewportHeight/2:"bottom"===stepConfig.placement?targetNode.offset().top+targetNode.height()+scrollTop-viewportHeight/2:targetNode.height()<=.8*viewportHeight?targetNode.offset().top-(viewportHeight-targetNode.height())/2:targetNode.offset().top-.2*viewportHeight),scrollTop=Math.max(0,scrollTop),scrollTop=Math.min((0,_jquery.default)(document).height()-viewportHeight,scrollTop),Math.ceil(scrollTop)}calculateStepPositionInPage(currentStepNode){let top=10;const viewportHeight=(0,_jquery.default)(window).height(),stepHeight=currentStepNode.height(),viewportWidth=(0,_jquery.default)(window).width(),stepWidth=currentStepNode.width();if(viewportHeight>=stepHeight+20)top=Math.ceil((viewportHeight-stepHeight)/2);else{var _currentStepNode$find,_currentStepNode$find2;const maxHeight=viewportHeight-20-(null!==(_currentStepNode$find=currentStepNode.find(".modal-header").first().outerHeight())&&void 0!==_currentStepNode$find?_currentStepNode$find:0)-(null!==(_currentStepNode$find2=currentStepNode.find(".modal-footer").first().outerHeight())&&void 0!==_currentStepNode$find2?_currentStepNode$find2:0);currentStepNode.find('[data-placeholder="body"]').first().css({"max-height":maxHeight+"px",overflow:"auto"})}currentStepNode.offset({top:top,left:Math.ceil((viewportWidth-stepWidth)/2)})}positionStep(stepConfig){let flipBehavior,content=this.currentStepNode,thisT=this;if(!content||!content.length)return this;switch(stepConfig.placement=this.recalculatePlacement(stepConfig),stepConfig.placement){case"left":flipBehavior=["left","right","top","bottom"];break;case"right":flipBehavior=["right","left","top","bottom"];break;case"top":flipBehavior=["top","bottom","right","left"];break;case"bottom":flipBehavior=["bottom","top","right","left"];break;default:flipBehavior="flip"}let offset="0";stepConfig.backdrop&&(offset="-".concat(10,", ").concat(10));let target=this.getStepTarget(stepConfig);var config={placement:stepConfig.placement+"-start",removeOnDestroy:!0,modifiers:{flip:{behaviour:flipBehavior},arrow:{element:'[data-role="arrow"]'},offset:{offset:offset}},onCreate:function(data){recalculateArrowPosition(data),recalculateStepPosition(data)},onUpdate:function(data){recalculateArrowPosition(data),thisT.possitionNeedToBeRecalculated&&(thisT.recalculatedNo++,thisT.possitionNeedToBeRecalculated=!1,recalculateStepPosition(data)),thisT.recalculateBackdropPosition(stepConfig)}};let recalculateArrowPosition=function(data){let placement=data.placement.split("-")[0];const isVertical=-1!==["left","right"].indexOf(placement),arrowElement=data.instance.popper.querySelector('[data-role="arrow"]'),stepElement=(0,_jquery.default)(data.instance.popper.querySelector('[data-role="flexitour-step"]'));if(isVertical){let arrowHeight=parseFloat(window.getComputedStyle(arrowElement).height),arrowOffset=parseFloat(window.getComputedStyle(arrowElement).top),popperHeight=parseFloat(window.getComputedStyle(data.instance.popper).height),popperOffset=parseFloat(window.getComputedStyle(data.instance.popper).top),popperBorderWidth=parseFloat(stepElement.css("borderTopWidth")),popperBorderRadiusWidth=2*parseFloat(stepElement.css("borderTopLeftRadius")),arrowPos=arrowOffset+arrowHeight/2,maxPos=popperHeight+popperOffset-popperBorderWidth-popperBorderRadiusWidth,minPos=popperOffset+popperBorderWidth+popperBorderRadiusWidth;if(arrowPos>=maxPos||arrowPos<=minPos){let newArrowPos=0;newArrowPos=arrowPos>popperHeight/2?maxPos-arrowHeight:minPos+arrowHeight,(0,_jquery.default)(arrowElement).css("top",newArrowPos)}}else{let arrowWidth=parseFloat(window.getComputedStyle(arrowElement).width),arrowOffset=parseFloat(window.getComputedStyle(arrowElement).left),popperWidth=parseFloat(window.getComputedStyle(data.instance.popper).width),popperOffset=parseFloat(window.getComputedStyle(data.instance.popper).left),popperBorderWidth=parseFloat(stepElement.css("borderTopWidth")),popperBorderRadiusWidth=2*parseFloat(stepElement.css("borderTopLeftRadius")),arrowPos=arrowOffset+arrowWidth/2,maxPos=popperWidth+popperOffset-popperBorderWidth-popperBorderRadiusWidth,minPos=popperOffset+popperBorderWidth+popperBorderRadiusWidth;if(arrowPos>=maxPos||arrowPos<=minPos){let newArrowPos=0;newArrowPos=arrowPos>popperWidth/2?maxPos-arrowWidth:minPos+arrowWidth,(0,_jquery.default)(arrowElement).css("left",newArrowPos)}}};const recalculateStepPosition=function(data){var _headerEle$outerHeigh,_footerEle$outerHeigh;const placement=data.placement.split("-")[0],isVertical=-1!==["left","right"].indexOf(placement),popperElement=(0,_jquery.default)(data.instance.popper),targetElement=(0,_jquery.default)(data.instance.reference),arrowElement=popperElement.find('[data-role="arrow"]'),stepElement=popperElement.find('[data-role="flexitour-step"]'),viewportHeight=(0,_jquery.default)(window).height(),viewportWidth=(0,_jquery.default)(window).width(),arrowHeight=parseFloat(arrowElement.outerHeight(!0)),popperHeight=parseFloat(popperElement.outerHeight(!0)),targetHeight=parseFloat(targetElement.outerHeight(!0)),arrowWidth=parseFloat(arrowElement.outerWidth(!0)),popperWidth=parseFloat(popperElement.outerWidth(!0)),targetWidth=parseFloat(targetElement.outerWidth(!0));let maxHeight;if(thisT.recalculatedNo>1&&(thisT.currentStepPopper.options.placement=isVertical?"auto-left":"auto-bottom"),thisT.recalculatedNo>2)return;if(isVertical){const leftSpace=targetElement.offset().left>0?targetElement.offset().left:0,rightSpace=viewportWidth-leftSpace-targetWidth,remainingSpace=leftSpace>=rightSpace?leftSpace:rightSpace;if(maxHeight=viewportHeight-20,remainingSpace0&&(popperElement.css({"max-width":maxWidth+"px"}),thisT.possitionNeedToBeRecalculated=!0)}else maxHeight0?targetElement.offset().top:0,bottomSpace=viewportHeight-topSpace-targetHeight,remainingSpace=topSpace>=bottomSpace?topSpace:bottomSpace;maxHeight=remainingSpace-10-arrowHeight,remainingSpace0?(headerEle.removeClass("minimal"),footerEle.removeClass("minimal"),currentStepBody.css({"max-height":maxHeight+"px",overflow:"auto"})):(headerEle.addClass("minimal"),footerEle.addClass("minimal")),thisT.currentStepPopper.update()};let background=(0,_jquery.default)('[data-flexitour="highlight"]');return background.length&&(target=background),this.currentStepPopper=new _popper.default(target,content[0],config),this}recalculatePlacement(stepConfig){let target=this.getStepTarget(stepConfig),widthContent=this.currentStepNode.width()+16,targetOffsetLeft=target.offset().left-10,targetOffsetRight=target.offset().left+target.width()+10,placement=stepConfig.placement;return-1!==["left","right"].indexOf(placement)&&targetOffsetLeftdocument.documentElement.clientWidth&&(placement="top"),placement}recalculateBackdropPosition(stepConfig){stepConfig.backdrop&&this.positionBackdrop(stepConfig)}positionBackdrop(stepConfig){if(stepConfig.backdrop){this.currentStepConfig.hasBackdrop=!0;let backdrop=(0,_jquery.default)('div[data-flexitour="backdrop"]');if(backdrop.length||(backdrop=(0,_jquery.default)('
'),(0,_jquery.default)("body").append(backdrop)),this.isStepActuallyVisible(stepConfig)){let targetNode=this.getStepTarget(stepConfig);targetNode.attr("data-flexitour","highlight");let distanceFromTop=targetNode[0].getBoundingClientRect().top,relativeTop=targetNode.offset().top-distanceFromTop;const viewportHeight=(0,_jquery.default)(window).height(),viewportWidth=(0,_jquery.default)(window).width(),elementWidth=targetNode.outerWidth()+20;let elementHeight=targetNode.outerHeight()+20;const elementLeft=targetNode.offset().left-10;let elementTop=targetNode.offset().top-10-relativeTop,navbarOverlap=0;if(targetNode.parents('[data-usertour="scroller"]').length){const navbarHeight=targetNode.parents('[data-usertour="scroller"]').offset().top;navbarOverlap=Math.max(Math.ceil(navbarHeight-elementTop),0),elementTop+=navbarOverlap,elementHeight-=navbarOverlap}if(this.currentStepNode&&this.currentStepNode.length){const xPlacement=this.currentStepNode[0].getAttribute("x-placement");this.currentStepNode[0].style.top="top-start"===xPlacement?"".concat(navbarOverlap,"px"):"0px"}const radius=10,bottomRight={x1:elementLeft+elementWidth-radius,y1:elementTop+elementHeight,x2:elementLeft+elementWidth,y2:elementTop+elementHeight-radius},topRight={x1:elementLeft+elementWidth,y1:elementTop+radius,x2:elementLeft+elementWidth-radius,y2:elementTop},topLeft={x1:elementLeft+radius,y1:elementTop,x2:elementLeft,y2:elementTop+radius},bottomLeft={x1:elementLeft,y1:elementTop+elementHeight-radius,x2:elementLeft+radius,y2:elementTop+elementHeight};document.querySelector('div[data-flexitour="backdrop"]').style.clipPath="path('M 0 0 L ".concat(viewportWidth," 0 L ").concat(viewportWidth," ").concat(viewportHeight," L 0 ").concat(viewportHeight," L 0 ").concat(elementTop+elementHeight," L ").concat(bottomRight.x1," ").concat(bottomRight.y1," C ").concat(bottomRight.x1," ").concat(bottomRight.y1," ").concat(bottomRight.x2," ").concat(bottomRight.y1," ").concat(bottomRight.x2," ").concat(bottomRight.y2," L ").concat(topRight.x1," ").concat(topRight.y1," C ").concat(topRight.x1," ").concat(topRight.y1," ").concat(topRight.x1," ").concat(topRight.y2," ").concat(topRight.x2," ").concat(topRight.y2," L ").concat(topLeft.x1," ").concat(topLeft.y1," C ").concat(topLeft.x1," ").concat(topLeft.y1," ").concat(topLeft.x2," ").concat(topLeft.y1," ").concat(topLeft.x2," ").concat(topLeft.y2," L ").concat(bottomLeft.x1," ").concat(bottomLeft.y1," C ").concat(bottomLeft.x1," ").concat(bottomLeft.y1," ").concat(bottomLeft.x1," ").concat(bottomLeft.y2," ").concat(bottomLeft.x2," ").concat(bottomLeft.y2," L 0 ").concat(elementTop+elementHeight," Z'\n )")}}return this}calculatePosition(elem){for(elem=(0,_jquery.default)(elem);elem.length&&elem[0]!==document;){let position=elem.css("position");if("static"!==position)return position;elem=elem.parent()}return null}accessibilityShow(){let hideFunction=function(child){let flexitourRole=child.data("flexitour");if(flexitourRole)switch(flexitourRole){case"container":case"target":return}child.attr("aria-hidden")||(child.attr("data-has-hidden",!0),Aria.hide(child))};this.currentStepNode.siblings().each((function(index,node){hideFunction((0,_jquery.default)(node))})),this.currentStepNode.parentsUntil("body").siblings().each((function(index,node){hideFunction((0,_jquery.default)(node))}))}accessibilityHide(){(0,_jquery.default)("[data-has-hidden]").each((function(index,node){var child;void 0!==(child=(0,_jquery.default)(node)).attr("data-has-hidden")&&(child.removeAttr("data-has-hidden"),Aria.unhide(child))}))}};return _exports.default=_default,_exports.default})); +define("tool_usertours/tour",["exports","jquery","core/aria","core/popper","core/event_dispatcher","./events","core/str","core/prefetch","core/event","core/pending"],(function(_exports,_jquery,Aria,_popper,_event_dispatcher,_events,_str,_prefetch,_event,_pending){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _defineProperty(obj,key,value){return key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,obj}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_jquery=_interopRequireDefault(_jquery),Aria=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(Aria),_popper=_interopRequireDefault(_popper),_pending=_interopRequireDefault(_pending);var _default=class{constructor(config){_defineProperty(this,"tourRunning",!1),_defineProperty(this,"hasFixedPosition",(targetNode=>{let currentElement=targetNode[0];for(;currentElement;){if("fixed"===window.getComputedStyle(currentElement).position)return!0;currentElement=currentElement.parentElement}return!1})),this.init(config)}init(config){this.eventHandlers={},this.reset(),this.originalConfiguration=config||{},this.configure.apply(this,arguments),this.possitionNeedToBeRecalculated=!1,this.recalculatedNo=0;try{this.storage=window.sessionStorage,this.storageKey="tourstate_"+this.tourName}catch(e){this.storage=!1,this.storageKey=""}return(0,_prefetch.prefetchStrings)("tool_usertours",["nextstep_sequence","skip_tour"]),this}reset(){return this.hide(),this.eventHandlers=[],this.resetStepListeners(),this.originalConfiguration={},this.steps=[],this.currentStepNumber=0,this}configure(config){if("object"==typeof config){if(void 0!==config.tourName&&(this.tourName=config.tourName),config.eventHandlers)for(let eventName in config.eventHandlers)config.eventHandlers[eventName].forEach((function(handler){this.addEventHandler(eventName,handler)}),this);this.resetStepDefaults(!0),"object"==typeof config.steps&&(this.steps=config.steps),void 0!==config.template&&(this.templateContent=config.template)}return this.checkMinimumRequirements(),this}checkMinimumRequirements(){if(!this.tourName)throw new Error("Tour Name required");if(!this.steps||!this.steps.length)throw new Error("Steps must be specified")}resetStepDefaults(loadOriginalConfiguration){return void 0===loadOriginalConfiguration&&(loadOriginalConfiguration=!0),this.stepDefaults={},loadOriginalConfiguration&&void 0!==this.originalConfiguration.stepDefaults?this.setStepDefaults(this.originalConfiguration.stepDefaults):this.setStepDefaults({}),this}setStepDefaults(stepDefaults){return this.stepDefaults||(this.stepDefaults={}),_jquery.default.extend(this.stepDefaults,{element:"",placement:"top",delay:0,moveOnClick:!1,moveAfterTime:0,orphan:!1,direction:1},stepDefaults),this}getCurrentStepNumber(){return parseInt(this.currentStepNumber,10)}setCurrentStepNumber(stepNumber){if(this.currentStepNumber=stepNumber,this.storage)try{this.storage.setItem(this.storageKey,stepNumber)}catch(e){e.code===DOMException.QUOTA_EXCEEDED_ERR&&this.storage.removeItem(this.storageKey)}}getNextStepNumber(stepNumber){void 0===stepNumber&&(stepNumber=this.getCurrentStepNumber());let nextStepNumber=stepNumber+1;for(;nextStepNumber<=this.steps.length;){if(this.isStepPotentiallyVisible(this.getStepConfig(nextStepNumber)))return nextStepNumber;nextStepNumber++}return null}getPreviousStepNumber(stepNumber){void 0===stepNumber&&(stepNumber=this.getCurrentStepNumber());let previousStepNumber=stepNumber-1;for(;previousStepNumber>=0;){if(this.isStepPotentiallyVisible(this.getStepConfig(previousStepNumber)))return previousStepNumber;previousStepNumber--}return null}isLastStep(stepNumber){return null===this.getNextStepNumber(stepNumber)}isStepPotentiallyVisible(stepConfig){return!!stepConfig&&(!!this.isStepActuallyVisible(stepConfig)||(!(void 0===stepConfig.orphan||!stepConfig.orphan)||!(void 0===stepConfig.delay||!stepConfig.delay)))}getPotentiallyVisibleSteps(){let position=1,result=[];for(let stepNumber=0;stepNumber=this.steps.length)return null;let stepConfig=this.normalizeStepConfig(this.steps[stepNumber]);return stepConfig=_jquery.default.extend(stepConfig,{stepNumber:stepNumber}),stepConfig}normalizeStepConfig(stepConfig){return void 0!==stepConfig.reflex&&void 0===stepConfig.moveAfterClick&&(stepConfig.moveAfterClick=stepConfig.reflex),void 0!==stepConfig.element&&void 0===stepConfig.target&&(stepConfig.target=stepConfig.element),void 0!==stepConfig.content&&void 0===stepConfig.body&&(stepConfig.body=stepConfig.content),stepConfig=_jquery.default.extend({},this.stepDefaults,stepConfig),(stepConfig=_jquery.default.extend({},{attachTo:stepConfig.target,attachPoint:"after"},stepConfig)).attachTo&&(stepConfig.attachTo=(0,_jquery.default)(stepConfig.attachTo).first()),stepConfig}getStepTarget(stepConfig){return stepConfig.target?(0,_jquery.default)(stepConfig.target):null}dispatchEvent(eventName){let detail=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},cancelable=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return(0,_event_dispatcher.dispatchEvent)(eventName,{tour:this,...detail},document,{cancelable:cancelable})}addEventHandler(eventName,handler){return void 0===this.eventHandlers[eventName]&&(this.eventHandlers[eventName]=[]),this.eventHandlers[eventName].push(handler),this}processStepListeners(stepConfig){if(this.listeners.push({node:this.currentStepNode,args:["click",'[data-role="next"]',_jquery.default.proxy(this.next,this)]},{node:this.currentStepNode,args:["click",'[data-role="end"]',_jquery.default.proxy(this.endTour,this)]},{node:(0,_jquery.default)('[data-flexitour="backdrop"]'),args:["click",_jquery.default.proxy(this.hide,this)]},{node:(0,_jquery.default)("body"),args:["keydown",_jquery.default.proxy(this.handleKeyDown,this)]}),stepConfig.moveOnClick){var targetNode=this.getStepTarget(stepConfig);this.listeners.push({node:targetNode,args:["click",_jquery.default.proxy((function(e){0===(0,_jquery.default)(e.target).parents('[data-flexitour="container"]').length&&window.setTimeout(_jquery.default.proxy(this.next,this),500)}),this)]})}return this.listeners.forEach((function(listener){listener.node.on.apply(listener.node,listener.args)})),this}resetStepListeners(){return this.listeners&&this.listeners.forEach((function(listener){listener.node.off.apply(listener.node,listener.args)})),this.listeners=[],this}renderStep(stepConfig){this.currentStepConfig=stepConfig,this.setCurrentStepNumber(stepConfig.stepNumber);let template=(0,_jquery.default)(this.getTemplateContent());template.find('[data-placeholder="title"]').html(stepConfig.title),template.find('[data-placeholder="body"]').html(stepConfig.body);const nextBtn=template.find('[data-role="next"]'),endBtn=template.find('[data-role="end"]');if(this.isLastStep(stepConfig.stepNumber)?(nextBtn.hide(),endBtn.removeClass("btn-secondary").addClass("btn-primary")):(nextBtn.prop("disabled",!1),(0,_str.getString)("skip_tour","tool_usertours").then((value=>{endBtn.html(value)})).catch()),nextBtn.attr("role","button"),endBtn.attr("role","button"),this.originalConfiguration.displaystepnumbers){const stepsPotentiallyVisible=this.getPotentiallyVisibleSteps(),totalStepsPotentiallyVisible=stepsPotentiallyVisible.length,position=stepsPotentiallyVisible[stepConfig.stepNumber].position;totalStepsPotentiallyVisible>1&&(0,_str.getString)("nextstep_sequence","tool_usertours",{position:position,total:totalStepsPotentiallyVisible}).then((value=>{nextBtn.html(value)})).catch()}return stepConfig.template=template,this.addStepToPage(stepConfig),this.processStepListeners(stepConfig),this}getTemplateContent(){return(0,_jquery.default)(this.templateContent).clone()}addStepToPage(stepConfig){let currentStepNode=(0,_jquery.default)('').html(stepConfig.template).hide();(0,_event.notifyFilterContentUpdated)(currentStepNode);let animationTarget=(0,_jquery.default)("body, html").stop(!0,!0);if(this.isStepActuallyVisible(stepConfig)){this.getStepTarget(stepConfig).data("flexitour","target"),(0,_jquery.default)(document.body).append(currentStepNode),this.currentStepNode=currentStepNode,this.currentStepNode.css({top:0,left:0});const pendingPromise=new _pending.default("tool_usertours/tour:addStepToPage-".concat(stepConfig.stepNumber));animationTarget.animate({scrollTop:this.calculateScrollTop(stepConfig)}).promise().then(function(){this.positionBackdrop(stepConfig),this.positionStep(stepConfig),this.revealStep(stepConfig),pendingPromise.resolve()}.bind(this)).catch((function(){}))}else stepConfig.orphan&&(stepConfig.isOrphan=!0,stepConfig.attachTo=(0,_jquery.default)("body").first(),stepConfig.attachPoint="append",this.positionBackdrop(stepConfig),currentStepNode.addClass("orphan"),(0,_jquery.default)(document.body).append(currentStepNode),this.currentStepNode=currentStepNode,this.currentStepNode.css("position","fixed"),this.currentStepPopper=new _popper.default((0,_jquery.default)("body"),this.currentStepNode[0],{removeOnDestroy:!0,placement:stepConfig.placement+"-start",arrowElement:'[data-role="arrow"]',modifiers:{hide:{enabled:!1},applyStyle:{onLoad:null,enabled:!1}},onCreate:()=>{const images=this.currentStepNode.find("img");images.length&&images.on("load",(()=>{this.calculateStepPositionInPage(currentStepNode)})),this.calculateStepPositionInPage(currentStepNode)}}),this.revealStep(stepConfig));return this}revealStep(stepConfig){const pendingPromise=new _pending.default("tool_usertours/tour:revealStep-".concat(stepConfig.stepNumber));return this.currentStepNode.fadeIn("",_jquery.default.proxy((function(){this.announceStep(stepConfig),this.currentStepNode.focus(),window.setTimeout(_jquery.default.proxy((function(){this.currentStepNode&&this.currentStepNode.focus(),pendingPromise.resolve()}),this),100)}),this)),this}announceStep(stepConfig){let stepId="tour-step-"+this.tourName+"-"+stepConfig.stepNumber;this.currentStepNode.attr("id",stepId);let bodyRegion=this.currentStepNode.find('[data-placeholder="body"]').first();bodyRegion.attr("id",stepId+"-body"),bodyRegion.attr("role","document");let headerRegion=this.currentStepNode.find('[data-placeholder="title"]').first();headerRegion.attr("id",stepId+"-title"),headerRegion.attr("aria-labelledby",stepId+"-body"),this.currentStepNode.attr("role","dialog"),this.currentStepNode.attr("tabindex",0),this.currentStepNode.attr("aria-labelledby",stepId+"-title"),this.currentStepNode.attr("aria-describedby",stepId+"-body");let target=this.getStepTarget(stepConfig);return target&&(target.data("original-tabindex",target.attr("tabindex")),target.attr("tabindex")||target.attr("tabindex",0),target.data("original-describedby",target.attr("aria-describedby")).attr("aria-describedby",stepId+"-body")),this.accessibilityShow(stepConfig),this}handleKeyDown(e){let tabbableSelector="a[href], link[href], [draggable=true], [contenteditable=true], ";switch(tabbableSelector+=":input:enabled, [tabindex], button:enabled",e.keyCode){case 27:this.endTour();break;case 9:(function(){if(!this.currentStepConfig.hasBackdrop)return;let currentIndex,nextIndex,nextNode,focusRelevant,activeElement=(0,_jquery.default)(document.activeElement),stepTarget=this.getStepTarget(this.currentStepConfig),tabbableNodes=(0,_jquery.default)(tabbableSelector),dialogContainer=(0,_jquery.default)('span[data-flexitour="container"]');if(stepTarget&&(tabbableNodes=tabbableNodes.filter((function(index,element){return null!==stepTarget&&(stepTarget.has(element).length||dialogContainer.has(element).length||stepTarget.is(element)||dialogContainer.is(element))}))),tabbableNodes.each((function(index,element){return!activeElement.is(element)||(currentIndex=index,!1)})),null!=currentIndex){let direction=1;e.shiftKey&&(direction=-1),nextIndex=currentIndex;do{nextIndex+=direction,nextNode=(0,_jquery.default)(tabbableNodes[nextIndex])}while(nextNode.length&&nextNode.is(":disabled")||nextNode.is(":hidden"));nextNode.length?(focusRelevant=nextNode.closest(stepTarget).length,focusRelevant=focusRelevant||nextNode.closest(this.currentStepNode).length):focusRelevant=!1}focusRelevant?nextNode.focus():e.shiftKey?this.currentStepNode.find(tabbableSelector).last().focus():this.currentStepConfig.isOrphan?this.currentStepNode.focus():stepTarget.focus(),e.preventDefault()}).call(this)}}startTour(startAt){if(this.storage&&void 0===startAt){let storageStartValue=this.storage.getItem(this.storageKey);if(storageStartValue){let storageStartAt=parseInt(storageStartValue,10);storageStartAt<=this.steps.length&&(startAt=storageStartAt)}}void 0===startAt&&(startAt=this.getCurrentStepNumber());return this.dispatchEvent(_events.eventTypes.tourStart,{startAt:startAt},!0).defaultPrevented||(this.gotoStep(startAt),this.tourRunning=!0,this.dispatchEvent(_events.eventTypes.tourStarted,{startAt:startAt})),this}restartTour(){return this.startTour(0)}endTour(){if(this.dispatchEvent(_events.eventTypes.tourEnd,{},!0).defaultPrevented)return this;if(this.currentStepConfig){let previousTarget=this.getStepTarget(this.currentStepConfig);previousTarget&&(previousTarget.attr("tabindex")||previousTarget.attr("tabindex","-1"),previousTarget.first().focus())}return this.hide(!0),this.tourRunning=!1,this.dispatchEvent(_events.eventTypes.tourEnded),this}hide(transition){if(this.dispatchEvent(_events.eventTypes.stepHide,{},!0).defaultPrevented)return this;const pendingPromise=new _pending.default("tool_usertours/tour:hide");if(this.currentStepNode&&this.currentStepNode.length&&(this.currentStepNode.hide(),this.currentStepPopper&&this.currentStepPopper.destroy()),this.currentStepConfig){let target=this.getStepTarget(this.currentStepConfig);target&&(target.data("original-labelledby")&&target.attr("aria-labelledby",target.data("original-labelledby")),target.data("original-describedby")&&target.attr("aria-describedby",target.data("original-describedby")),target.data("original-tabindex")?target.attr("tabindex",target.data("tabindex")):window.setTimeout((()=>{target.removeAttr("tabindex")}),400)),this.currentStepConfig=null}(0,_jquery.default)('[data-flexitour="highlight"]').removeAttr("data-flexitour");const backdrop=(0,_jquery.default)('[data-flexitour="backdrop"]');if(backdrop.length)if(transition){const backdropRemovalPromise=new _pending.default("tool_usertours/tour:hide:backdrop");backdrop.fadeOut(400,(function(){(0,_jquery.default)(this).remove(),backdropRemovalPromise.resolve()}))}else backdrop.remove();if(this.currentStepNode&&this.currentStepNode.length){let stepId=this.currentStepNode.attr("id");if(stepId){let currentStepElement='[aria-describedby="'+stepId+'-body"]';(0,_jquery.default)(currentStepElement).removeAttr("tabindex"),(0,_jquery.default)(currentStepElement).removeAttr("aria-describedby")}}return this.resetStepListeners(),this.accessibilityHide(),this.dispatchEvent(_events.eventTypes.stepHidden),this.currentStepNode=null,this.currentStepPopper=null,pendingPromise.resolve(),this}show(){let startAt=this.getCurrentStepNumber();return this.gotoStep(startAt)}getStepContainer(){return(0,_jquery.default)(this.currentStepNode)}calculateScrollTop(stepConfig){let viewportHeight=(0,_jquery.default)(window).height(),targetNode=this.getStepTarget(stepConfig),scrollParent=(0,_jquery.default)(window);targetNode.parents('[data-usertour="scroller"]').length&&(scrollParent=targetNode.parents('[data-usertour="scroller"]'));let scrollTop=scrollParent.scrollTop();return this.hasFixedPosition(targetNode)||(scrollTop="top"===stepConfig.placement?targetNode.offset().top-viewportHeight/2:"bottom"===stepConfig.placement?targetNode.offset().top+targetNode.height()+scrollTop-viewportHeight/2:targetNode.height()<=.8*viewportHeight?targetNode.offset().top-(viewportHeight-targetNode.height())/2:targetNode.offset().top-.2*viewportHeight),scrollTop=Math.max(0,scrollTop),scrollTop=Math.min((0,_jquery.default)(document).height()-viewportHeight,scrollTop),Math.ceil(scrollTop)}calculateStepPositionInPage(currentStepNode){let top=10;const viewportHeight=(0,_jquery.default)(window).height(),stepHeight=currentStepNode.height(),viewportWidth=(0,_jquery.default)(window).width(),stepWidth=currentStepNode.width();if(viewportHeight>=stepHeight+20)top=Math.ceil((viewportHeight-stepHeight)/2);else{var _currentStepNode$find,_currentStepNode$find2;const maxHeight=viewportHeight-20-(null!==(_currentStepNode$find=currentStepNode.find(".modal-header").first().outerHeight())&&void 0!==_currentStepNode$find?_currentStepNode$find:0)-(null!==(_currentStepNode$find2=currentStepNode.find(".modal-footer").first().outerHeight())&&void 0!==_currentStepNode$find2?_currentStepNode$find2:0);currentStepNode.find('[data-placeholder="body"]').first().css({"max-height":maxHeight+"px",overflow:"auto"})}currentStepNode.offset({top:top,left:Math.ceil((viewportWidth-stepWidth)/2)})}positionStep(stepConfig){let flipBehavior,content=this.currentStepNode,thisT=this;if(!content||!content.length)return this;switch(stepConfig.placement=this.recalculatePlacement(stepConfig),stepConfig.placement){case"left":flipBehavior=["left","right","top","bottom"];break;case"right":flipBehavior=["right","left","top","bottom"];break;case"top":flipBehavior=["top","bottom","right","left"];break;case"bottom":flipBehavior=["bottom","top","right","left"];break;default:flipBehavior="flip"}let offset="0";stepConfig.backdrop&&(offset="-".concat(10,", ").concat(10));let target=this.getStepTarget(stepConfig);var config={placement:stepConfig.placement+"-start",removeOnDestroy:!0,modifiers:{flip:{behaviour:flipBehavior},arrow:{element:'[data-role="arrow"]'},offset:{offset:offset}},onCreate:function(data){recalculateArrowPosition(data),recalculateStepPosition(data)},onUpdate:function(data){recalculateArrowPosition(data),thisT.possitionNeedToBeRecalculated&&(thisT.recalculatedNo++,thisT.possitionNeedToBeRecalculated=!1,recalculateStepPosition(data)),thisT.recalculateBackdropPosition(stepConfig)}};let recalculateArrowPosition=function(data){let placement=data.placement.split("-")[0];const isVertical=-1!==["left","right"].indexOf(placement),arrowElement=data.instance.popper.querySelector('[data-role="arrow"]'),stepElement=(0,_jquery.default)(data.instance.popper.querySelector('[data-role="flexitour-step"]'));if(isVertical){let arrowHeight=parseFloat(window.getComputedStyle(arrowElement).height),arrowOffset=parseFloat(window.getComputedStyle(arrowElement).top),popperHeight=parseFloat(window.getComputedStyle(data.instance.popper).height),popperOffset=parseFloat(window.getComputedStyle(data.instance.popper).top),popperBorderWidth=parseFloat(stepElement.css("borderTopWidth")),popperBorderRadiusWidth=2*parseFloat(stepElement.css("borderTopLeftRadius")),arrowPos=arrowOffset+arrowHeight/2,maxPos=popperHeight+popperOffset-popperBorderWidth-popperBorderRadiusWidth,minPos=popperOffset+popperBorderWidth+popperBorderRadiusWidth;if(arrowPos>=maxPos||arrowPos<=minPos){let newArrowPos=0;newArrowPos=arrowPos>popperHeight/2?maxPos-arrowHeight:minPos+arrowHeight,(0,_jquery.default)(arrowElement).css("top",newArrowPos)}}else{let arrowWidth=parseFloat(window.getComputedStyle(arrowElement).width),arrowOffset=parseFloat(window.getComputedStyle(arrowElement).left),popperWidth=parseFloat(window.getComputedStyle(data.instance.popper).width),popperOffset=parseFloat(window.getComputedStyle(data.instance.popper).left),popperBorderWidth=parseFloat(stepElement.css("borderTopWidth")),popperBorderRadiusWidth=2*parseFloat(stepElement.css("borderTopLeftRadius")),arrowPos=arrowOffset+arrowWidth/2,maxPos=popperWidth+popperOffset-popperBorderWidth-popperBorderRadiusWidth,minPos=popperOffset+popperBorderWidth+popperBorderRadiusWidth;if(arrowPos>=maxPos||arrowPos<=minPos){let newArrowPos=0;newArrowPos=arrowPos>popperWidth/2?maxPos-arrowWidth:minPos+arrowWidth,(0,_jquery.default)(arrowElement).css("left",newArrowPos)}}};const recalculateStepPosition=function(data){var _headerEle$outerHeigh,_footerEle$outerHeigh;const placement=data.placement.split("-")[0],isVertical=-1!==["left","right"].indexOf(placement),popperElement=(0,_jquery.default)(data.instance.popper),targetElement=(0,_jquery.default)(data.instance.reference),arrowElement=popperElement.find('[data-role="arrow"]'),stepElement=popperElement.find('[data-role="flexitour-step"]'),viewportHeight=(0,_jquery.default)(window).height(),viewportWidth=(0,_jquery.default)(window).width(),arrowHeight=parseFloat(arrowElement.outerHeight(!0)),popperHeight=parseFloat(popperElement.outerHeight(!0)),targetHeight=parseFloat(targetElement.outerHeight(!0)),arrowWidth=parseFloat(arrowElement.outerWidth(!0)),popperWidth=parseFloat(popperElement.outerWidth(!0)),targetWidth=parseFloat(targetElement.outerWidth(!0));let maxHeight;if(thisT.recalculatedNo>1&&(thisT.currentStepPopper.options.placement=isVertical?"auto-left":"auto-bottom"),thisT.recalculatedNo>2)return;if(isVertical){const leftSpace=targetElement.offset().left>0?targetElement.offset().left:0,rightSpace=viewportWidth-leftSpace-targetWidth,remainingSpace=leftSpace>=rightSpace?leftSpace:rightSpace;if(maxHeight=viewportHeight-20,remainingSpace0&&(popperElement.css({"max-width":maxWidth+"px"}),thisT.possitionNeedToBeRecalculated=!0)}else maxHeight0?targetElement.offset().top:0,bottomSpace=viewportHeight-topSpace-targetHeight,remainingSpace=topSpace>=bottomSpace?topSpace:bottomSpace;maxHeight=remainingSpace-10-arrowHeight,remainingSpace0?(headerEle.removeClass("minimal"),footerEle.removeClass("minimal"),currentStepBody.css({"max-height":maxHeight+"px",overflow:"auto"})):(headerEle.addClass("minimal"),footerEle.addClass("minimal")),thisT.currentStepPopper.update()};let background=(0,_jquery.default)('[data-flexitour="highlight"]');return background.length&&(target=background),this.currentStepPopper=new _popper.default(target,content[0],config),this}recalculatePlacement(stepConfig){let target=this.getStepTarget(stepConfig),widthContent=this.currentStepNode.width()+16,targetOffsetLeft=target.offset().left-10,targetOffsetRight=target.offset().left+target.width()+10,placement=stepConfig.placement;return-1!==["left","right"].indexOf(placement)&&targetOffsetLeftdocument.documentElement.clientWidth&&(placement="top"),placement}recalculateBackdropPosition(stepConfig){stepConfig.backdrop&&this.positionBackdrop(stepConfig)}positionBackdrop(stepConfig){if(stepConfig.backdrop){this.currentStepConfig.hasBackdrop=!0;let backdrop=(0,_jquery.default)('div[data-flexitour="backdrop"]');if(backdrop.length||(backdrop=(0,_jquery.default)('
'),(0,_jquery.default)("body").append(backdrop)),this.isStepActuallyVisible(stepConfig)){let targetNode=this.getStepTarget(stepConfig);targetNode.attr("data-flexitour","highlight");let distanceFromTop=targetNode[0].getBoundingClientRect().top,relativeTop=targetNode.offset().top-distanceFromTop;const viewportHeight=(0,_jquery.default)(window).height(),viewportWidth=(0,_jquery.default)(window).width(),elementWidth=targetNode.outerWidth()+20;let elementHeight=targetNode.outerHeight()+20;const elementLeft=targetNode.offset().left-10;let elementTop=targetNode.offset().top-10-relativeTop,navbarOverlap=0;if(targetNode.parents('[data-usertour="scroller"]').length){const navbarHeight=targetNode.parents('[data-usertour="scroller"]').offset().top;navbarOverlap=Math.max(Math.ceil(navbarHeight-elementTop),0),elementTop+=navbarOverlap,elementHeight-=navbarOverlap}if(this.currentStepNode&&this.currentStepNode.length){const xPlacement=this.currentStepNode[0].getAttribute("x-placement");this.currentStepNode[0].style.top="top-start"===xPlacement?"".concat(navbarOverlap,"px"):"0px"}const radius=10,bottomRight={x1:elementLeft+elementWidth-radius,y1:elementTop+elementHeight,x2:elementLeft+elementWidth,y2:elementTop+elementHeight-radius},topRight={x1:elementLeft+elementWidth,y1:elementTop+radius,x2:elementLeft+elementWidth-radius,y2:elementTop},topLeft={x1:elementLeft+radius,y1:elementTop,x2:elementLeft,y2:elementTop+radius},bottomLeft={x1:elementLeft,y1:elementTop+elementHeight-radius,x2:elementLeft+radius,y2:elementTop+elementHeight};document.querySelector('div[data-flexitour="backdrop"]').style.clipPath="path('M 0 0 L ".concat(viewportWidth," 0 L ").concat(viewportWidth," ").concat(viewportHeight," L 0 ").concat(viewportHeight," L 0 ").concat(elementTop+elementHeight," L ").concat(bottomRight.x1," ").concat(bottomRight.y1," C ").concat(bottomRight.x1," ").concat(bottomRight.y1," ").concat(bottomRight.x2," ").concat(bottomRight.y1," ").concat(bottomRight.x2," ").concat(bottomRight.y2," L ").concat(topRight.x1," ").concat(topRight.y1," C ").concat(topRight.x1," ").concat(topRight.y1," ").concat(topRight.x1," ").concat(topRight.y2," ").concat(topRight.x2," ").concat(topRight.y2," L ").concat(topLeft.x1," ").concat(topLeft.y1," C ").concat(topLeft.x1," ").concat(topLeft.y1," ").concat(topLeft.x2," ").concat(topLeft.y1," ").concat(topLeft.x2," ").concat(topLeft.y2," L ").concat(bottomLeft.x1," ").concat(bottomLeft.y1," C ").concat(bottomLeft.x1," ").concat(bottomLeft.y1," ").concat(bottomLeft.x1," ").concat(bottomLeft.y2," ").concat(bottomLeft.x2," ").concat(bottomLeft.y2," L 0 ").concat(elementTop+elementHeight," Z'\n )")}}return this}calculatePosition(elem){for(elem=(0,_jquery.default)(elem);elem.length&&elem[0]!==document;){let position=elem.css("position");if("static"!==position)return position;elem=elem.parent()}return null}accessibilityShow(){let hideFunction=function(child){let flexitourRole=child.data("flexitour");if(flexitourRole)switch(flexitourRole){case"container":case"target":return}child.attr("aria-hidden")||(child.attr("data-has-hidden",!0),Aria.hide(child))};this.currentStepNode.siblings().each((function(index,node){hideFunction((0,_jquery.default)(node))})),this.currentStepNode.parentsUntil("body").siblings().each((function(index,node){hideFunction((0,_jquery.default)(node))}))}accessibilityHide(){(0,_jquery.default)("[data-has-hidden]").each((function(index,node){var child;void 0!==(child=(0,_jquery.default)(node)).attr("data-has-hidden")&&(child.removeAttr("data-has-hidden"),Aria.unhide(child))}))}};return _exports.default=_default,_exports.default})); //# sourceMappingURL=tour.min.js.map \ No newline at end of file diff --git a/public/admin/tool/usertours/amd/build/tour.min.js.map b/public/admin/tool/usertours/amd/build/tour.min.js.map index b78faff3f64..03d63fe307a 100644 --- a/public/admin/tool/usertours/amd/build/tour.min.js.map +++ b/public/admin/tool/usertours/amd/build/tour.min.js.map @@ -1 +1 @@ -{"version":3,"file":"tour.min.js","sources":["../src/tour.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * A user tour.\n *\n * @module tool_usertours/tour\n * @copyright 2018 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * A list of steps.\n *\n * @typedef {Object[]} StepList\n * @property {Number} stepId The id of the step in the database\n * @property {Number} position The position of the step within the tour (zero-indexed)\n */\n\nimport $ from 'jquery';\nimport * as Aria from 'core/aria';\nimport Popper from 'core/popper';\nimport {dispatchEvent} from 'core/event_dispatcher';\nimport {eventTypes} from './events';\nimport {getString} from 'core/str';\nimport {prefetchStrings} from 'core/prefetch';\nimport {notifyFilterContentUpdated} from 'core/event';\nimport PendingPromise from 'core/pending';\n\n/**\n * The minimum spacing for tour step to display.\n *\n * @private\n * @constant\n * @type {number}\n */\nconst MINSPACING = 10;\nconst BUFFER = 10;\n\n/**\n * A user tour.\n *\n * @class tool_usertours/tour\n * @property {boolean} tourRunning Whether the tour is currently running.\n */\nconst Tour = class {\n tourRunning = false;\n\n /**\n * @param {object} config The configuration object.\n */\n constructor(config) {\n this.init(config);\n }\n\n /**\n * Initialise the tour.\n *\n * @method init\n * @param {Object} config The configuration object.\n * @chainable\n * @return {Object} this.\n */\n init(config) {\n // Unset all handlers.\n this.eventHandlers = {};\n\n // Reset the current tour states.\n this.reset();\n\n // Store the initial configuration.\n this.originalConfiguration = config || {};\n\n // Apply configuration.\n this.configure.apply(this, arguments);\n\n // Unset recalculate state.\n this.possitionNeedToBeRecalculated = false;\n\n // Unset recalculate count.\n this.recalculatedNo = 0;\n\n try {\n this.storage = window.sessionStorage;\n this.storageKey = 'tourstate_' + this.tourName;\n } catch (e) {\n this.storage = false;\n this.storageKey = '';\n }\n\n prefetchStrings('tool_usertours', [\n 'nextstep_sequence',\n 'skip_tour'\n ]);\n\n return this;\n }\n\n /**\n * Reset the current tour state.\n *\n * @method reset\n * @chainable\n * @return {Object} this.\n */\n reset() {\n // Hide the current step.\n this.hide();\n\n // Unset all handlers.\n this.eventHandlers = [];\n\n // Unset all listeners.\n this.resetStepListeners();\n\n // Unset the original configuration.\n this.originalConfiguration = {};\n\n // Reset the current step number and list of steps.\n this.steps = [];\n\n // Reset the current step number.\n this.currentStepNumber = 0;\n\n return this;\n }\n\n /**\n * Prepare tour configuration.\n *\n * @method configure\n * @param {Object} config The configuration object.\n * @chainable\n * @return {Object} this.\n */\n configure(config) {\n if (typeof config === 'object') {\n // Tour name.\n if (typeof config.tourName !== 'undefined') {\n this.tourName = config.tourName;\n }\n\n // Set up eventHandlers.\n if (config.eventHandlers) {\n for (let eventName in config.eventHandlers) {\n config.eventHandlers[eventName].forEach(function(handler) {\n this.addEventHandler(eventName, handler);\n }, this);\n }\n }\n\n // Reset the step configuration.\n this.resetStepDefaults(true);\n\n // Configure the steps.\n if (typeof config.steps === 'object') {\n this.steps = config.steps;\n }\n\n if (typeof config.template !== 'undefined') {\n this.templateContent = config.template;\n }\n }\n\n // Check that we have enough to start the tour.\n this.checkMinimumRequirements();\n\n return this;\n }\n\n /**\n * Check that the configuration meets the minimum requirements.\n *\n * @method checkMinimumRequirements\n */\n checkMinimumRequirements() {\n // Need a tourName.\n if (!this.tourName) {\n throw new Error(\"Tour Name required\");\n }\n\n // Need a minimum of one step.\n if (!this.steps || !this.steps.length) {\n throw new Error(\"Steps must be specified\");\n }\n }\n\n /**\n * Reset step default configuration.\n *\n * @method resetStepDefaults\n * @param {Boolean} loadOriginalConfiguration Whether to load the original configuration supplied with the Tour.\n * @chainable\n * @return {Object} this.\n */\n resetStepDefaults(loadOriginalConfiguration) {\n if (typeof loadOriginalConfiguration === 'undefined') {\n loadOriginalConfiguration = true;\n }\n\n this.stepDefaults = {};\n if (!loadOriginalConfiguration || typeof this.originalConfiguration.stepDefaults === 'undefined') {\n this.setStepDefaults({});\n } else {\n this.setStepDefaults(this.originalConfiguration.stepDefaults);\n }\n\n return this;\n }\n\n /**\n * Set the step defaults.\n *\n * @method setStepDefaults\n * @param {Object} stepDefaults The step defaults to apply to all steps\n * @chainable\n * @return {Object} this.\n */\n setStepDefaults(stepDefaults) {\n if (!this.stepDefaults) {\n this.stepDefaults = {};\n }\n $.extend(\n this.stepDefaults,\n {\n element: '',\n placement: 'top',\n delay: 0,\n moveOnClick: false,\n moveAfterTime: 0,\n orphan: false,\n direction: 1,\n },\n stepDefaults\n );\n\n return this;\n }\n\n /**\n * Retrieve the current step number.\n *\n * @method getCurrentStepNumber\n * @return {Number} The current step number\n */\n getCurrentStepNumber() {\n return parseInt(this.currentStepNumber, 10);\n }\n\n /**\n * Store the current step number.\n *\n * @method setCurrentStepNumber\n * @param {Number} stepNumber The current step number\n * @chainable\n */\n setCurrentStepNumber(stepNumber) {\n this.currentStepNumber = stepNumber;\n if (this.storage) {\n try {\n this.storage.setItem(this.storageKey, stepNumber);\n } catch (e) {\n if (e.code === DOMException.QUOTA_EXCEEDED_ERR) {\n this.storage.removeItem(this.storageKey);\n }\n }\n }\n }\n\n /**\n * Get the next step number after the currently displayed step.\n *\n * @method getNextStepNumber\n * @param {Number} stepNumber The current step number\n * @return {Number} The next step number to display\n */\n getNextStepNumber(stepNumber) {\n if (typeof stepNumber === 'undefined') {\n stepNumber = this.getCurrentStepNumber();\n }\n let nextStepNumber = stepNumber + 1;\n\n // Keep checking the remaining steps.\n while (nextStepNumber <= this.steps.length) {\n if (this.isStepPotentiallyVisible(this.getStepConfig(nextStepNumber))) {\n return nextStepNumber;\n }\n nextStepNumber++;\n }\n\n return null;\n }\n\n /**\n * Get the previous step number before the currently displayed step.\n *\n * @method getPreviousStepNumber\n * @param {Number} stepNumber The current step number\n * @return {Number} The previous step number to display\n */\n getPreviousStepNumber(stepNumber) {\n if (typeof stepNumber === 'undefined') {\n stepNumber = this.getCurrentStepNumber();\n }\n let previousStepNumber = stepNumber - 1;\n\n // Keep checking the remaining steps.\n while (previousStepNumber >= 0) {\n if (this.isStepPotentiallyVisible(this.getStepConfig(previousStepNumber))) {\n return previousStepNumber;\n }\n previousStepNumber--;\n }\n\n return null;\n }\n\n /**\n * Is the step the final step number?\n *\n * @method isLastStep\n * @param {Number} stepNumber Step number to test\n * @return {Boolean} Whether the step is the final step\n */\n isLastStep(stepNumber) {\n let nextStepNumber = this.getNextStepNumber(stepNumber);\n\n return nextStepNumber === null;\n }\n\n /**\n * Is this step potentially visible?\n *\n * @method isStepPotentiallyVisible\n * @param {Object} stepConfig The step configuration to normalise\n * @return {Boolean} Whether the step is the potentially visible\n */\n isStepPotentiallyVisible(stepConfig) {\n if (!stepConfig) {\n // Without step config, there can be no step.\n return false;\n }\n\n if (this.isStepActuallyVisible(stepConfig)) {\n // If it is actually visible, it is already potentially visible.\n return true;\n }\n\n if (typeof stepConfig.orphan !== 'undefined' && stepConfig.orphan) {\n // Orphan steps have no target. They are always visible.\n return true;\n }\n\n if (typeof stepConfig.delay !== 'undefined' && stepConfig.delay) {\n // Only return true if the activated has not been used yet.\n return true;\n }\n\n // Not theoretically, or actually visible.\n return false;\n }\n\n /**\n * Get potentially visible steps in a tour.\n *\n * @returns {StepList} A list of ordered steps\n */\n getPotentiallyVisibleSteps() {\n let position = 1;\n let result = [];\n // Checking the total steps.\n for (let stepNumber = 0; stepNumber < this.steps.length; stepNumber++) {\n const stepConfig = this.getStepConfig(stepNumber);\n if (this.isStepPotentiallyVisible(stepConfig)) {\n result[stepNumber] = {stepId: stepConfig.stepid, position: position};\n position++;\n }\n }\n\n return result;\n }\n\n /**\n * Is this step actually visible?\n *\n * @method isStepActuallyVisible\n * @param {Object} stepConfig The step configuration to normalise\n * @return {Boolean} Whether the step is actually visible\n */\n isStepActuallyVisible(stepConfig) {\n if (!stepConfig) {\n // Without step config, there can be no step.\n return false;\n }\n\n // Check if the CSS styles are allowed on the browser or not.\n if (!this.isCSSAllowed()) {\n return false;\n }\n\n let target = this.getStepTarget(stepConfig);\n if (target && target.length && target.is(':visible')) {\n // Without a target, there can be no step.\n return !!target.length;\n }\n\n return false;\n }\n\n /**\n * Is the browser actually allow CSS styles?\n *\n * @returns {boolean} True if the browser is allowing CSS styles\n */\n isCSSAllowed() {\n const testCSSElement = document.createElement('div');\n testCSSElement.classList.add('hide');\n document.body.appendChild(testCSSElement);\n const styles = window.getComputedStyle(testCSSElement);\n const isAllowed = styles.display === 'none';\n testCSSElement.remove();\n\n return isAllowed;\n }\n\n /**\n * Go to the next step in the tour.\n *\n * @method next\n * @chainable\n * @return {Object} this.\n */\n next() {\n return this.gotoStep(this.getNextStepNumber());\n }\n\n /**\n * Go to the previous step in the tour.\n *\n * @method previous\n * @chainable\n * @return {Object} this.\n */\n previous() {\n return this.gotoStep(this.getPreviousStepNumber(), -1);\n }\n\n /**\n * Go to the specified step in the tour.\n *\n * @method gotoStep\n * @param {Number} stepNumber The step number to display\n * @param {Number} direction Next or previous step\n * @chainable\n * @return {Object} this.\n * @fires tool_usertours/stepRender\n * @fires tool_usertours/stepRendered\n * @fires tool_usertours/stepHide\n * @fires tool_usertours/stepHidden\n */\n gotoStep(stepNumber, direction) {\n if (stepNumber < 0) {\n return this.endTour();\n }\n\n let stepConfig = this.getStepConfig(stepNumber);\n if (stepConfig === null) {\n return this.endTour();\n }\n\n return this._gotoStep(stepConfig, direction);\n }\n\n _gotoStep(stepConfig, direction) {\n if (!stepConfig) {\n return this.endTour();\n }\n\n const pendingPromise = new PendingPromise(`tool_usertours/tour:_gotoStep-${stepConfig.stepNumber}`);\n\n if (typeof stepConfig.delay !== 'undefined' && stepConfig.delay && !stepConfig.delayed) {\n stepConfig.delayed = true;\n window.setTimeout(function(stepConfig, direction) {\n this._gotoStep(stepConfig, direction);\n pendingPromise.resolve();\n }, stepConfig.delay, stepConfig, direction);\n\n return this;\n } else if (!stepConfig.orphan && !this.isStepActuallyVisible(stepConfig)) {\n const fn = direction == -1 ? 'getPreviousStepNumber' : 'getNextStepNumber';\n this.gotoStep(this[fn](stepConfig.stepNumber), direction);\n\n pendingPromise.resolve();\n return this;\n }\n\n this.hide();\n\n const stepRenderEvent = this.dispatchEvent(eventTypes.stepRender, {stepConfig}, true);\n if (!stepRenderEvent.defaultPrevented) {\n this.renderStep(stepConfig);\n this.dispatchEvent(eventTypes.stepRendered, {stepConfig});\n }\n\n pendingPromise.resolve();\n return this;\n }\n\n /**\n * Fetch the normalised step configuration for the specified step number.\n *\n * @method getStepConfig\n * @param {Number} stepNumber The step number to fetch configuration for\n * @return {Object} The step configuration\n */\n getStepConfig(stepNumber) {\n if (stepNumber === null || stepNumber < 0 || stepNumber >= this.steps.length) {\n return null;\n }\n\n // Normalise the step configuration.\n let stepConfig = this.normalizeStepConfig(this.steps[stepNumber]);\n\n // Add the stepNumber to the stepConfig.\n stepConfig = $.extend(stepConfig, {stepNumber: stepNumber});\n\n return stepConfig;\n }\n\n /**\n * Normalise the supplied step configuration.\n *\n * @method normalizeStepConfig\n * @param {Object} stepConfig The step configuration to normalise\n * @return {Object} The normalised step configuration\n */\n normalizeStepConfig(stepConfig) {\n\n if (typeof stepConfig.reflex !== 'undefined' && typeof stepConfig.moveAfterClick === 'undefined') {\n stepConfig.moveAfterClick = stepConfig.reflex;\n }\n\n if (typeof stepConfig.element !== 'undefined' && typeof stepConfig.target === 'undefined') {\n stepConfig.target = stepConfig.element;\n }\n\n if (typeof stepConfig.content !== 'undefined' && typeof stepConfig.body === 'undefined') {\n stepConfig.body = stepConfig.content;\n }\n\n stepConfig = $.extend({}, this.stepDefaults, stepConfig);\n\n stepConfig = $.extend({}, {\n attachTo: stepConfig.target,\n attachPoint: 'after',\n }, stepConfig);\n\n if (stepConfig.attachTo) {\n stepConfig.attachTo = $(stepConfig.attachTo).first();\n }\n\n return stepConfig;\n }\n\n /**\n * Fetch the actual step target from the selector.\n *\n * This should not be called until after any delay has completed.\n *\n * @method getStepTarget\n * @param {Object} stepConfig The step configuration\n * @return {$}\n */\n getStepTarget(stepConfig) {\n if (stepConfig.target) {\n return $(stepConfig.target);\n }\n\n return null;\n }\n\n /**\n * Fire any event handlers for the specified event.\n *\n * @param {String} eventName The name of the event\n * @param {Object} [detail={}] Any additional details to pass into the eveent\n * @param {Boolean} [cancelable=false] Whether preventDefault() can be called\n * @returns {CustomEvent}\n */\n dispatchEvent(\n eventName,\n detail = {},\n cancelable = false\n ) {\n return dispatchEvent(eventName, {\n // Add the tour to the detail.\n tour: this,\n ...detail,\n }, document, {\n cancelable,\n });\n }\n\n /**\n * @method addEventHandler\n * @param {string} eventName The name of the event to listen for\n * @param {function} handler The event handler to call\n * @return {Object} this.\n */\n addEventHandler(eventName, handler) {\n if (typeof this.eventHandlers[eventName] === 'undefined') {\n this.eventHandlers[eventName] = [];\n }\n\n this.eventHandlers[eventName].push(handler);\n\n return this;\n }\n\n /**\n * Process listeners for the step being shown.\n *\n * @method processStepListeners\n * @param {object} stepConfig The configuration for the step\n * @chainable\n * @return {Object} this.\n */\n processStepListeners(stepConfig) {\n this.listeners.push(\n // Next button.\n {\n node: this.currentStepNode,\n args: ['click', '[data-role=\"next\"]', $.proxy(this.next, this)]\n },\n\n // Close and end tour buttons.\n {\n node: this.currentStepNode,\n args: ['click', '[data-role=\"end\"]', $.proxy(this.endTour, this)]\n },\n\n // Click backdrop and hide tour.\n {\n node: $('[data-flexitour=\"backdrop\"]'),\n args: ['click', $.proxy(this.hide, this)]\n },\n\n // Keypresses.\n {\n node: $('body'),\n args: ['keydown', $.proxy(this.handleKeyDown, this)]\n });\n\n if (stepConfig.moveOnClick) {\n var targetNode = this.getStepTarget(stepConfig);\n this.listeners.push({\n node: targetNode,\n args: ['click', $.proxy(function(e) {\n if ($(e.target).parents('[data-flexitour=\"container\"]').length === 0) {\n // Ignore clicks when they are in the flexitour.\n window.setTimeout($.proxy(this.next, this), 500);\n }\n }, this)]\n });\n }\n\n this.listeners.forEach(function(listener) {\n listener.node.on.apply(listener.node, listener.args);\n });\n\n return this;\n }\n\n /**\n * Reset step listeners.\n *\n * @method resetStepListeners\n * @chainable\n * @return {Object} this.\n */\n resetStepListeners() {\n // Stop listening to all external handlers.\n if (this.listeners) {\n this.listeners.forEach(function(listener) {\n listener.node.off.apply(listener.node, listener.args);\n });\n }\n this.listeners = [];\n\n return this;\n }\n\n /**\n * The standard step renderer.\n *\n * @method renderStep\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n * @return {Object} this.\n */\n renderStep(stepConfig) {\n // Store the current step configuration for later.\n this.currentStepConfig = stepConfig;\n this.setCurrentStepNumber(stepConfig.stepNumber);\n\n // Fetch the template and convert it to a $ object.\n let template = $(this.getTemplateContent());\n\n // Title.\n template.find('[data-placeholder=\"title\"]')\n .html(stepConfig.title);\n\n // Body.\n template.find('[data-placeholder=\"body\"]')\n .html(stepConfig.body);\n\n // Buttons.\n const nextBtn = template.find('[data-role=\"next\"]');\n const endBtn = template.find('[data-role=\"end\"]');\n\n // Is this the final step?\n if (this.isLastStep(stepConfig.stepNumber)) {\n nextBtn.hide();\n endBtn.removeClass(\"btn-secondary\").addClass(\"btn-primary\");\n } else {\n nextBtn.prop('disabled', false);\n // Use Skip tour label for the End tour button.\n getString('skip_tour', 'tool_usertours').then(value => {\n endBtn.html(value);\n return;\n }).catch();\n }\n\n nextBtn.attr('role', 'button');\n endBtn.attr('role', 'button');\n\n if (this.originalConfiguration.displaystepnumbers) {\n const stepsPotentiallyVisible = this.getPotentiallyVisibleSteps();\n const totalStepsPotentiallyVisible = stepsPotentiallyVisible.length;\n const position = stepsPotentiallyVisible[stepConfig.stepNumber].position;\n if (totalStepsPotentiallyVisible > 1) {\n // Change the label of the Next button to include the sequence.\n getString('nextstep_sequence', 'tool_usertours',\n {position: position, total: totalStepsPotentiallyVisible}).then(value => {\n nextBtn.html(value);\n return;\n }).catch();\n }\n }\n\n // Replace the template with the updated version.\n stepConfig.template = template;\n\n // Add to the page.\n this.addStepToPage(stepConfig);\n\n // Process step listeners after adding to the page.\n // This uses the currentNode.\n this.processStepListeners(stepConfig);\n\n return this;\n }\n\n /**\n * Getter for the template content.\n *\n * @method getTemplateContent\n * @return {$}\n */\n getTemplateContent() {\n return $(this.templateContent).clone();\n }\n\n /**\n * Helper to add a step to the page.\n *\n * @method addStepToPage\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n * @return {Object} this.\n */\n addStepToPage(stepConfig) {\n // Create the stepNode from the template data.\n let currentStepNode = $('')\n .html(stepConfig.template)\n .hide();\n // Trigger the Moodle filters.\n notifyFilterContentUpdated(currentStepNode);\n\n // The scroll animation occurs on the body or html.\n let animationTarget = $('body, html')\n .stop(true, true);\n\n if (this.isStepActuallyVisible(stepConfig)) {\n let targetNode = this.getStepTarget(stepConfig);\n\n targetNode.data('flexitour', 'target');\n\n // Add the backdrop.\n this.positionBackdrop(stepConfig);\n\n $(document.body).append(currentStepNode);\n this.currentStepNode = currentStepNode;\n\n // Ensure that the step node is positioned.\n // Some situations mean that the value is not properly calculated without this step.\n this.currentStepNode.css({\n top: 0,\n left: 0,\n });\n\n const pendingPromise = new PendingPromise(`tool_usertours/tour:addStepToPage-${stepConfig.stepNumber}`);\n animationTarget\n .animate({\n scrollTop: this.calculateScrollTop(stepConfig),\n }).promise().then(function() {\n this.positionStep(stepConfig);\n this.revealStep(stepConfig);\n pendingPromise.resolve();\n return;\n }.bind(this))\n .catch(function() {\n // Silently fail.\n });\n\n } else if (stepConfig.orphan) {\n stepConfig.isOrphan = true;\n\n // This will be appended to the body instead.\n stepConfig.attachTo = $('body').first();\n stepConfig.attachPoint = 'append';\n\n // Add the backdrop.\n this.positionBackdrop(stepConfig);\n\n // This is an orphaned step.\n currentStepNode.addClass('orphan');\n\n // It lives in the body.\n $(document.body).append(currentStepNode);\n this.currentStepNode = currentStepNode;\n\n this.currentStepNode.css('position', 'fixed');\n\n this.currentStepPopper = new Popper(\n $('body'),\n this.currentStepNode[0], {\n removeOnDestroy: true,\n placement: stepConfig.placement + '-start',\n arrowElement: '[data-role=\"arrow\"]',\n // Empty the modifiers. We've already placed the step and don't want it moved.\n modifiers: {\n hide: {\n enabled: false,\n },\n applyStyle: {\n onLoad: null,\n enabled: false,\n },\n },\n onCreate: () => {\n // First, we need to check if the step's content contains any images.\n const images = this.currentStepNode.find('img');\n if (images.length) {\n // Images found, need to calculate the position when the image is loaded.\n images.on('load', () => {\n this.calculateStepPositionInPage(currentStepNode);\n });\n }\n this.calculateStepPositionInPage(currentStepNode);\n }\n }\n );\n\n this.revealStep(stepConfig);\n }\n\n return this;\n }\n\n /**\n * Make the given step visible.\n *\n * @method revealStep\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n * @return {Object} this.\n */\n revealStep(stepConfig) {\n // Fade the step in.\n const pendingPromise = new PendingPromise(`tool_usertours/tour:revealStep-${stepConfig.stepNumber}`);\n this.currentStepNode.fadeIn('', $.proxy(function() {\n // Announce via ARIA.\n this.announceStep(stepConfig);\n\n // Focus on the current step Node.\n this.currentStepNode.focus();\n window.setTimeout($.proxy(function() {\n // After a brief delay, focus again.\n // There seems to be an issue with Jaws where it only reads the dialogue title initially.\n // This second focus helps it to read the full dialogue.\n if (this.currentStepNode) {\n this.currentStepNode.focus();\n }\n pendingPromise.resolve();\n }, this), 100);\n\n }, this));\n\n return this;\n }\n\n /**\n * Helper to announce the step on the page.\n *\n * @method announceStep\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n * @return {Object} this.\n */\n announceStep(stepConfig) {\n // Setup the step Dialogue as per:\n // * https://www.w3.org/TR/wai-aria-practices/#dialog_nonmodal\n // * https://www.w3.org/TR/wai-aria-practices/#dialog_modal\n\n // Generate an ID for the current step node.\n let stepId = 'tour-step-' + this.tourName + '-' + stepConfig.stepNumber;\n this.currentStepNode.attr('id', stepId);\n\n let bodyRegion = this.currentStepNode.find('[data-placeholder=\"body\"]').first();\n bodyRegion.attr('id', stepId + '-body');\n bodyRegion.attr('role', 'document');\n\n let headerRegion = this.currentStepNode.find('[data-placeholder=\"title\"]').first();\n headerRegion.attr('id', stepId + '-title');\n headerRegion.attr('aria-labelledby', stepId + '-body');\n\n // Generally, a modal dialog has a role of dialog.\n this.currentStepNode.attr('role', 'dialog');\n this.currentStepNode.attr('tabindex', 0);\n this.currentStepNode.attr('aria-labelledby', stepId + '-title');\n this.currentStepNode.attr('aria-describedby', stepId + '-body');\n\n // Configure ARIA attributes on the target.\n let target = this.getStepTarget(stepConfig);\n if (target) {\n target.data('original-tabindex', target.attr('tabindex'));\n if (!target.attr('tabindex')) {\n target.attr('tabindex', 0);\n }\n\n target\n .data('original-describedby', target.attr('aria-describedby'))\n .attr('aria-describedby', stepId + '-body')\n ;\n }\n\n this.accessibilityShow(stepConfig);\n\n return this;\n }\n\n /**\n * Handle key down events.\n *\n * @method handleKeyDown\n * @param {EventFacade} e\n */\n handleKeyDown(e) {\n let tabbableSelector = 'a[href], link[href], [draggable=true], [contenteditable=true], ';\n tabbableSelector += ':input:enabled, [tabindex], button:enabled';\n switch (e.keyCode) {\n case 27:\n this.endTour();\n break;\n\n // 9 == Tab - trap focus for items with a backdrop.\n case 9:\n // Tab must be handled on key up only in this instance.\n (function() {\n if (!this.currentStepConfig.hasBackdrop) {\n // Trapping tab focus is only handled for those steps with a backdrop.\n return;\n }\n\n // Find all tabbable locations.\n let activeElement = $(document.activeElement);\n let stepTarget = this.getStepTarget(this.currentStepConfig);\n let tabbableNodes = $(tabbableSelector);\n let dialogContainer = $('span[data-flexitour=\"container\"]');\n let currentIndex;\n // Filter out element which is not belong to target section or dialogue.\n if (stepTarget) {\n tabbableNodes = tabbableNodes.filter(function(index, element) {\n return stepTarget !== null\n && (stepTarget.has(element).length\n || dialogContainer.has(element).length\n || stepTarget.is(element)\n || dialogContainer.is(element));\n });\n }\n\n // Find index of focusing element.\n tabbableNodes.each(function(index, element) {\n if (activeElement.is(element)) {\n currentIndex = index;\n return false;\n }\n // Keep looping.\n return true;\n });\n\n let nextIndex;\n let nextNode;\n let focusRelevant;\n if (currentIndex != void 0) {\n let direction = 1;\n if (e.shiftKey) {\n direction = -1;\n }\n nextIndex = currentIndex;\n do {\n nextIndex += direction;\n nextNode = $(tabbableNodes[nextIndex]);\n } while (nextNode.length && nextNode.is(':disabled') || nextNode.is(':hidden'));\n if (nextNode.length) {\n // A new f\n focusRelevant = nextNode.closest(stepTarget).length;\n focusRelevant = focusRelevant || nextNode.closest(this.currentStepNode).length;\n } else {\n // Unable to find the target somehow.\n focusRelevant = false;\n }\n }\n\n if (focusRelevant) {\n nextNode.focus();\n } else {\n if (e.shiftKey) {\n // Focus on the last tabbable node in the step.\n this.currentStepNode.find(tabbableSelector).last().focus();\n } else {\n if (this.currentStepConfig.isOrphan) {\n // Focus on the step - there is no target.\n this.currentStepNode.focus();\n } else {\n // Focus on the step target.\n stepTarget.focus();\n }\n }\n }\n e.preventDefault();\n }).call(this);\n break;\n }\n }\n\n /**\n * Start the current tour.\n *\n * @method startTour\n * @param {Number} startAt Which step number to start at. If not specified, starts at the last point.\n * @chainable\n * @return {Object} this.\n * @fires tool_usertours/tourStart\n * @fires tool_usertours/tourStarted\n */\n startTour(startAt) {\n if (this.storage && typeof startAt === 'undefined') {\n let storageStartValue = this.storage.getItem(this.storageKey);\n if (storageStartValue) {\n let storageStartAt = parseInt(storageStartValue, 10);\n if (storageStartAt <= this.steps.length) {\n startAt = storageStartAt;\n }\n }\n }\n\n if (typeof startAt === 'undefined') {\n startAt = this.getCurrentStepNumber();\n }\n\n const tourStartEvent = this.dispatchEvent(eventTypes.tourStart, {startAt}, true);\n if (!tourStartEvent.defaultPrevented) {\n this.gotoStep(startAt);\n this.tourRunning = true;\n this.dispatchEvent(eventTypes.tourStarted, {startAt});\n }\n\n return this;\n }\n\n /**\n * Restart the tour from the beginning, resetting the completionlag.\n *\n * @method restartTour\n * @chainable\n * @return {Object} this.\n */\n restartTour() {\n return this.startTour(0);\n }\n\n /**\n * End the current tour.\n *\n * @method endTour\n * @chainable\n * @return {Object} this.\n * @fires tool_usertours/tourEnd\n * @fires tool_usertours/tourEnded\n */\n endTour() {\n const tourEndEvent = this.dispatchEvent(eventTypes.tourEnd, {}, true);\n if (tourEndEvent.defaultPrevented) {\n return this;\n }\n\n if (this.currentStepConfig) {\n let previousTarget = this.getStepTarget(this.currentStepConfig);\n if (previousTarget) {\n if (!previousTarget.attr('tabindex')) {\n previousTarget.attr('tabindex', '-1');\n }\n previousTarget.first().focus();\n }\n }\n\n this.hide(true);\n\n this.tourRunning = false;\n this.dispatchEvent(eventTypes.tourEnded);\n\n return this;\n }\n\n /**\n * Hide any currently visible steps.\n *\n * @method hide\n * @param {Bool} transition Animate the visibility change\n * @chainable\n * @return {Object} this.\n * @fires tool_usertours/stepHide\n * @fires tool_usertours/stepHidden\n */\n hide(transition) {\n const stepHideEvent = this.dispatchEvent(eventTypes.stepHide, {}, true);\n if (stepHideEvent.defaultPrevented) {\n return this;\n }\n\n const pendingPromise = new PendingPromise('tool_usertours/tour:hide');\n if (this.currentStepNode && this.currentStepNode.length) {\n this.currentStepNode.hide();\n if (this.currentStepPopper) {\n this.currentStepPopper.destroy();\n }\n }\n\n // Restore original target configuration.\n if (this.currentStepConfig) {\n let target = this.getStepTarget(this.currentStepConfig);\n if (target) {\n if (target.data('original-labelledby')) {\n target.attr('aria-labelledby', target.data('original-labelledby'));\n }\n\n if (target.data('original-describedby')) {\n target.attr('aria-describedby', target.data('original-describedby'));\n }\n\n if (target.data('original-tabindex')) {\n target.attr('tabindex', target.data('tabindex'));\n } else {\n // If the target does not have the tabindex attribute at the beginning. We need to remove it.\n // We should wait a little here before removing the attribute to prevent the browser from adding it again.\n window.setTimeout(() => {\n target.removeAttr('tabindex');\n }, 400);\n }\n }\n\n // Clear the step configuration.\n this.currentStepConfig = null;\n }\n\n // Remove the highlight attribute when the hide occurs.\n $('[data-flexitour=\"highlight\"]').removeAttr('data-flexitour');\n\n const backdrop = $('[data-flexitour=\"backdrop\"]');\n if (backdrop.length) {\n if (transition) {\n const backdropRemovalPromise = new PendingPromise('tool_usertours/tour:hide:backdrop');\n backdrop.fadeOut(400, function() {\n $(this).remove();\n backdropRemovalPromise.resolve();\n });\n } else {\n backdrop.remove();\n }\n }\n\n // Remove aria-describedby and tabindex attributes.\n if (this.currentStepNode && this.currentStepNode.length) {\n let stepId = this.currentStepNode.attr('id');\n if (stepId) {\n let currentStepElement = '[aria-describedby=\"' + stepId + '-body\"]';\n $(currentStepElement).removeAttr('tabindex');\n $(currentStepElement).removeAttr('aria-describedby');\n }\n }\n\n // Reset the listeners.\n this.resetStepListeners();\n\n this.accessibilityHide();\n\n this.dispatchEvent(eventTypes.stepHidden);\n\n this.currentStepNode = null;\n this.currentStepPopper = null;\n\n pendingPromise.resolve();\n return this;\n }\n\n /**\n * Show the current steps.\n *\n * @method show\n * @chainable\n * @return {Object} this.\n */\n show() {\n // Show the current step.\n let startAt = this.getCurrentStepNumber();\n\n return this.gotoStep(startAt);\n }\n\n /**\n * Return the current step node.\n *\n * @method getStepContainer\n * @return {jQuery}\n */\n getStepContainer() {\n return $(this.currentStepNode);\n }\n\n /**\n * Check whether the target node has a fixed position, or is nested within one.\n *\n * @param {Object} targetNode The target element to check.\n * @return {Boolean} Return true if fixed position found.\n */\n hasFixedPosition = (targetNode) => {\n let currentElement = targetNode[0];\n while (currentElement) {\n const computedStyle = window.getComputedStyle(currentElement);\n if (computedStyle.position === 'fixed') {\n return true;\n }\n currentElement = currentElement.parentElement;\n }\n\n return false;\n };\n\n /**\n * Calculate scrollTop.\n *\n * @method calculateScrollTop\n * @param {Object} stepConfig The step configuration of the step\n * @return {Number}\n */\n calculateScrollTop(stepConfig) {\n let viewportHeight = $(window).height();\n let targetNode = this.getStepTarget(stepConfig);\n\n let scrollParent = $(window);\n if (targetNode.parents('[data-usertour=\"scroller\"]').length) {\n scrollParent = targetNode.parents('[data-usertour=\"scroller\"]');\n }\n let scrollTop = scrollParent.scrollTop();\n\n if (this.hasFixedPosition(targetNode)) {\n // Target must be in a fixed or custom position. No need to modify the scrollTop.\n } else if (stepConfig.placement === 'top') {\n // If the placement is top, center scroll at the top of the target.\n scrollTop = targetNode.offset().top - (viewportHeight / 2);\n } else if (stepConfig.placement === 'bottom') {\n // If the placement is bottom, center scroll at the bottom of the target.\n scrollTop = targetNode.offset().top + targetNode.height() + scrollTop - (viewportHeight / 2);\n } else if (targetNode.height() <= (viewportHeight * 0.8)) {\n // If the placement is left/right, and the target fits in the viewport, centre screen on the target\n scrollTop = targetNode.offset().top - ((viewportHeight - targetNode.height()) / 2);\n } else {\n // If the placement is left/right, and the target is bigger than the viewport, set scrollTop to target.top + buffer\n // and change step attachmentTarget to top+.\n scrollTop = targetNode.offset().top - (viewportHeight * 0.2);\n }\n\n // Never scroll over the top.\n scrollTop = Math.max(0, scrollTop);\n\n // Never scroll beyond the bottom.\n scrollTop = Math.min($(document).height() - viewportHeight, scrollTop);\n\n return Math.ceil(scrollTop);\n }\n\n /**\n * Calculate dialogue position for page middle.\n *\n * @param {jQuery} currentStepNode Current step node\n * @method calculateScrollTop\n */\n calculateStepPositionInPage(currentStepNode) {\n let top = MINSPACING;\n const viewportHeight = $(window).height();\n const stepHeight = currentStepNode.height();\n const viewportWidth = $(window).width();\n const stepWidth = currentStepNode.width();\n if (viewportHeight >= (stepHeight + (MINSPACING * 2))) {\n top = Math.ceil((viewportHeight - stepHeight) / 2);\n } else {\n const headerHeight = currentStepNode.find('.modal-header').first().outerHeight() ?? 0;\n const footerHeight = currentStepNode.find('.modal-footer').first().outerHeight() ?? 0;\n const currentStepBody = currentStepNode.find('[data-placeholder=\"body\"]').first();\n const maxHeight = viewportHeight - (MINSPACING * 2) - headerHeight - footerHeight;\n currentStepBody.css({\n 'max-height': maxHeight + 'px',\n 'overflow': 'auto',\n });\n }\n currentStepNode.offset({\n top: top,\n left: Math.ceil((viewportWidth - stepWidth) / 2)\n });\n }\n\n /**\n * Position the step on the page.\n *\n * @method positionStep\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n * @return {Object} this.\n */\n positionStep(stepConfig) {\n let content = this.currentStepNode;\n let thisT = this;\n if (!content || !content.length) {\n // Unable to find the step node.\n return this;\n }\n\n stepConfig.placement = this.recalculatePlacement(stepConfig);\n let flipBehavior;\n switch (stepConfig.placement) {\n case 'left':\n flipBehavior = ['left', 'right', 'top', 'bottom'];\n break;\n case 'right':\n flipBehavior = ['right', 'left', 'top', 'bottom'];\n break;\n case 'top':\n flipBehavior = ['top', 'bottom', 'right', 'left'];\n break;\n case 'bottom':\n flipBehavior = ['bottom', 'top', 'right', 'left'];\n break;\n default:\n flipBehavior = 'flip';\n break;\n }\n\n let offset = '0';\n if (stepConfig.backdrop) {\n // Offset the arrow so that it points to the cut-out in the backdrop.\n offset = `-${BUFFER}, ${BUFFER}`;\n }\n\n let target = this.getStepTarget(stepConfig);\n var config = {\n placement: stepConfig.placement + '-start',\n removeOnDestroy: true,\n modifiers: {\n flip: {\n behaviour: flipBehavior,\n },\n arrow: {\n element: '[data-role=\"arrow\"]',\n },\n offset: {\n offset: offset\n }\n },\n onCreate: function(data) {\n recalculateArrowPosition(data);\n recalculateStepPosition(data);\n },\n onUpdate: function(data) {\n recalculateArrowPosition(data);\n if (thisT.possitionNeedToBeRecalculated) {\n thisT.recalculatedNo++;\n thisT.possitionNeedToBeRecalculated = false;\n recalculateStepPosition(data);\n }\n // Reset backdrop position when things update.\n thisT.recalculateBackdropPosition(stepConfig);\n },\n };\n\n let recalculateArrowPosition = function(data) {\n let placement = data.placement.split('-')[0];\n const isVertical = ['left', 'right'].indexOf(placement) !== -1;\n const arrowElement = data.instance.popper.querySelector('[data-role=\"arrow\"]');\n const stepElement = $(data.instance.popper.querySelector('[data-role=\"flexitour-step\"]'));\n if (isVertical) {\n let arrowHeight = parseFloat(window.getComputedStyle(arrowElement).height);\n let arrowOffset = parseFloat(window.getComputedStyle(arrowElement).top);\n let popperHeight = parseFloat(window.getComputedStyle(data.instance.popper).height);\n let popperOffset = parseFloat(window.getComputedStyle(data.instance.popper).top);\n let popperBorderWidth = parseFloat(stepElement.css('borderTopWidth'));\n let popperBorderRadiusWidth = parseFloat(stepElement.css('borderTopLeftRadius')) * 2;\n let arrowPos = arrowOffset + (arrowHeight / 2);\n let maxPos = popperHeight + popperOffset - popperBorderWidth - popperBorderRadiusWidth;\n let minPos = popperOffset + popperBorderWidth + popperBorderRadiusWidth;\n if (arrowPos >= maxPos || arrowPos <= minPos) {\n let newArrowPos = 0;\n if (arrowPos > (popperHeight / 2)) {\n newArrowPos = maxPos - arrowHeight;\n } else {\n newArrowPos = minPos + arrowHeight;\n }\n $(arrowElement).css('top', newArrowPos);\n }\n } else {\n let arrowWidth = parseFloat(window.getComputedStyle(arrowElement).width);\n let arrowOffset = parseFloat(window.getComputedStyle(arrowElement).left);\n let popperWidth = parseFloat(window.getComputedStyle(data.instance.popper).width);\n let popperOffset = parseFloat(window.getComputedStyle(data.instance.popper).left);\n let popperBorderWidth = parseFloat(stepElement.css('borderTopWidth'));\n let popperBorderRadiusWidth = parseFloat(stepElement.css('borderTopLeftRadius')) * 2;\n let arrowPos = arrowOffset + (arrowWidth / 2);\n let maxPos = popperWidth + popperOffset - popperBorderWidth - popperBorderRadiusWidth;\n let minPos = popperOffset + popperBorderWidth + popperBorderRadiusWidth;\n if (arrowPos >= maxPos || arrowPos <= minPos) {\n let newArrowPos = 0;\n if (arrowPos > (popperWidth / 2)) {\n newArrowPos = maxPos - arrowWidth;\n } else {\n newArrowPos = minPos + arrowWidth;\n }\n $(arrowElement).css('left', newArrowPos);\n }\n }\n };\n\n const recalculateStepPosition = function(data) {\n const placement = data.placement.split('-')[0];\n const isVertical = ['left', 'right'].indexOf(placement) !== -1;\n const popperElement = $(data.instance.popper);\n const targetElement = $(data.instance.reference);\n const arrowElement = popperElement.find('[data-role=\"arrow\"]');\n const stepElement = popperElement.find('[data-role=\"flexitour-step\"]');\n const viewportHeight = $(window).height();\n const viewportWidth = $(window).width();\n const arrowHeight = parseFloat(arrowElement.outerHeight(true));\n const popperHeight = parseFloat(popperElement.outerHeight(true));\n const targetHeight = parseFloat(targetElement.outerHeight(true));\n const arrowWidth = parseFloat(arrowElement.outerWidth(true));\n const popperWidth = parseFloat(popperElement.outerWidth(true));\n const targetWidth = parseFloat(targetElement.outerWidth(true));\n let maxHeight;\n\n if (thisT.recalculatedNo > 1) {\n // The current screen is too small, and cannot fit with the original placement.\n // We should set the placement to auto so the PopperJS can calculate the perfect placement.\n thisT.currentStepPopper.options.placement = isVertical ? 'auto-left' : 'auto-bottom';\n }\n if (thisT.recalculatedNo > 2) {\n // Return here to prevent recursive calling.\n return;\n }\n\n if (isVertical) {\n // Find the best place to put the tour: Left of right.\n const leftSpace = targetElement.offset().left > 0 ? targetElement.offset().left : 0;\n const rightSpace = viewportWidth - leftSpace - targetWidth;\n const remainingSpace = leftSpace >= rightSpace ? leftSpace : rightSpace;\n maxHeight = viewportHeight - MINSPACING * 2;\n if (remainingSpace < (popperWidth + arrowWidth)) {\n const maxWidth = remainingSpace - MINSPACING - arrowWidth;\n if (maxWidth > 0) {\n popperElement.css({\n 'max-width': maxWidth + 'px',\n });\n // Not enough space, flag true to make Popper to recalculate the position.\n thisT.possitionNeedToBeRecalculated = true;\n }\n } else if (maxHeight < popperHeight) {\n // Check if the Popper's height can fit the viewport height or not.\n // If not, set the correct max-height value for the Popper element.\n popperElement.css({\n 'max-height': maxHeight + 'px',\n });\n }\n } else {\n // Find the best place to put the tour: Top of bottom.\n const topSpace = targetElement.offset().top > 0 ? targetElement.offset().top : 0;\n const bottomSpace = viewportHeight - topSpace - targetHeight;\n const remainingSpace = topSpace >= bottomSpace ? topSpace : bottomSpace;\n maxHeight = remainingSpace - MINSPACING - arrowHeight;\n if (remainingSpace < (popperHeight + arrowHeight)) {\n // Not enough space, flag true to make Popper to recalculate the position.\n thisT.possitionNeedToBeRecalculated = true;\n }\n }\n\n // Check if the Popper's height can fit the viewport height or not.\n // If not, set the correct max-height value for the body.\n const currentStepBody = stepElement.find('[data-placeholder=\"body\"]').first();\n const headerEle = stepElement.find('.modal-header').first();\n const footerEle = stepElement.find('.modal-footer').first();\n const headerHeight = headerEle.outerHeight(true) ?? 0;\n const footerHeight = footerEle.outerHeight(true) ?? 0;\n maxHeight = maxHeight - headerHeight - footerHeight;\n if (maxHeight > 0) {\n headerEle.removeClass('minimal');\n footerEle.removeClass('minimal');\n currentStepBody.css({\n 'max-height': maxHeight + 'px',\n 'overflow': 'auto',\n });\n } else {\n headerEle.addClass('minimal');\n footerEle.addClass('minimal');\n }\n // Call the Popper update method to update the position.\n thisT.currentStepPopper.update();\n };\n\n let background = $('[data-flexitour=\"highlight\"]');\n if (background.length) {\n target = background;\n }\n this.currentStepPopper = new Popper(target, content[0], config);\n\n return this;\n }\n\n /**\n * For left/right placement, checks that there is room for the step at current window size.\n *\n * If there is not enough room, changes placement to 'top'.\n *\n * @method recalculatePlacement\n * @param {Object} stepConfig The step configuration of the step\n * @return {String} The placement after recalculate\n */\n recalculatePlacement(stepConfig) {\n const arrowWidth = 16;\n let target = this.getStepTarget(stepConfig);\n let widthContent = this.currentStepNode.width() + arrowWidth;\n let targetOffsetLeft = target.offset().left - BUFFER;\n let targetOffsetRight = target.offset().left + target.width() + BUFFER;\n let placement = stepConfig.placement;\n\n if (['left', 'right'].indexOf(placement) !== -1) {\n if ((targetOffsetLeft < (widthContent + BUFFER)) &&\n ((targetOffsetRight + widthContent + BUFFER) > document.documentElement.clientWidth)) {\n placement = 'top';\n }\n }\n return placement;\n }\n\n /**\n * Recaculate where the backdrop and its cut-out should be.\n *\n * This is needed when highlighted elements are off the page.\n * This can be called on update to recalculate it all.\n *\n * @method recalculateBackdropPosition\n * @param {Object} stepConfig The step configuration of the step\n */\n recalculateBackdropPosition(stepConfig) {\n if (stepConfig.backdrop) {\n this.positionBackdrop(stepConfig);\n }\n }\n\n /**\n * Add the backdrop.\n *\n * @method positionBackdrop\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n * @return {Object} this.\n */\n positionBackdrop(stepConfig) {\n if (stepConfig.backdrop) {\n this.currentStepConfig.hasBackdrop = true;\n\n // Position our backdrop above everything else.\n let backdrop = $('div[data-flexitour=\"backdrop\"]');\n if (!backdrop.length) {\n backdrop = $('
');\n $('body').append(backdrop);\n }\n\n if (this.isStepActuallyVisible(stepConfig)) {\n let targetNode = this.getStepTarget(stepConfig);\n targetNode.attr('data-flexitour', 'highlight');\n\n let distanceFromTop = targetNode[0].getBoundingClientRect().top;\n let relativeTop = targetNode.offset().top - distanceFromTop;\n\n /*\n Draw a clip-path that makes the backdrop a window.\n The clip-path is drawn with x/y coordinates in the following sequence.\n\n 1--------------------------------------------------2\n 11 |\n | |\n | 8-----------------------------7 |\n | | | |\n | | | |\n | | | |\n 10-------9 | |\n 5--------------------------------------6 |\n | |\n | |\n 4--------------------------------------------------3\n */\n\n // These values will help us draw the backdrop.\n const viewportHeight = $(window).height();\n const viewportWidth = $(window).width();\n const elementWidth = targetNode.outerWidth() + (BUFFER * 2);\n let elementHeight = targetNode.outerHeight() + (BUFFER * 2);\n const elementLeft = targetNode.offset().left - BUFFER;\n let elementTop = targetNode.offset().top - BUFFER - relativeTop;\n\n // Check the amount of navbar overlap the highlight element has.\n // We will adjust the backdrop shape to compensate for the fixed navbar.\n let navbarOverlap = 0;\n if (targetNode.parents('[data-usertour=\"scroller\"]').length) {\n // Determine the navbar height.\n const scrollerElement = targetNode.parents('[data-usertour=\"scroller\"]');\n const navbarHeight = scrollerElement.offset().top;\n navbarOverlap = Math.max(Math.ceil(navbarHeight - elementTop), 0);\n elementTop = elementTop + navbarOverlap;\n elementHeight = elementHeight - navbarOverlap;\n }\n\n // Check if the step container is in the 'top' position.\n // We will re-anchor the step container to the shifted backdrop edge as opposed to the actual element.\n if (this.currentStepNode && this.currentStepNode.length) {\n const xPlacement = this.currentStepNode[0].getAttribute('x-placement');\n if (xPlacement === 'top-start') {\n this.currentStepNode[0].style.top = `${navbarOverlap}px`;\n } else {\n this.currentStepNode[0].style.top = '0px';\n }\n }\n\n let backdropPath = document.querySelector('div[data-flexitour=\"backdrop\"]');\n const radius = 10;\n\n const bottomRight = {\n 'x1': elementLeft + elementWidth - radius,\n 'y1': elementTop + elementHeight,\n 'x2': elementLeft + elementWidth,\n 'y2': elementTop + elementHeight - radius,\n };\n\n const topRight = {\n 'x1': elementLeft + elementWidth,\n 'y1': elementTop + radius,\n 'x2': elementLeft + elementWidth - radius,\n 'y2': elementTop,\n };\n\n const topLeft = {\n 'x1': elementLeft + radius,\n 'y1': elementTop,\n 'x2': elementLeft,\n 'y2': elementTop + radius,\n };\n\n const bottomLeft = {\n 'x1': elementLeft,\n 'y1': elementTop + elementHeight - radius,\n 'x2': elementLeft + radius,\n 'y2': elementTop + elementHeight,\n };\n\n // L = line.\n // C = Bezier curve.\n // Z = Close path.\n backdropPath.style.clipPath = `path('M 0 0 \\\n L ${viewportWidth} 0 \\\n L ${viewportWidth} ${viewportHeight} \\\n L 0 ${viewportHeight} \\\n L 0 ${elementTop + elementHeight} \\\n L ${bottomRight.x1} ${bottomRight.y1} \\\n C ${bottomRight.x1} ${bottomRight.y1} ${bottomRight.x2} ${bottomRight.y1} ${bottomRight.x2} ${bottomRight.y2} \\\n L ${topRight.x1} ${topRight.y1} \\\n C ${topRight.x1} ${topRight.y1} ${topRight.x1} ${topRight.y2} ${topRight.x2} ${topRight.y2} \\\n L ${topLeft.x1} ${topLeft.y1} \\\n C ${topLeft.x1} ${topLeft.y1} ${topLeft.x2} ${topLeft.y1} ${topLeft.x2} ${topLeft.y2} \\\n L ${bottomLeft.x1} ${bottomLeft.y1} \\\n C ${bottomLeft.x1} ${bottomLeft.y1} ${bottomLeft.x1} ${bottomLeft.y2} ${bottomLeft.x2} ${bottomLeft.y2} \\\n L 0 ${elementTop + elementHeight} \\\n Z'\n )`;\n }\n }\n return this;\n }\n\n /**\n * Calculate the inheritted position.\n *\n * @method calculatePosition\n * @param {jQuery} elem The element to calculate position for\n * @return {String} Calculated position\n */\n calculatePosition(elem) {\n elem = $(elem);\n while (elem.length && elem[0] !== document) {\n let position = elem.css('position');\n if (position !== 'static') {\n return position;\n }\n elem = elem.parent();\n }\n\n return null;\n }\n\n /**\n * Perform accessibility changes for step shown.\n *\n * This will add aria-hidden=\"true\" to all siblings and parent siblings.\n *\n * @method accessibilityShow\n */\n accessibilityShow() {\n let stateHolder = 'data-has-hidden';\n let attrName = 'aria-hidden';\n let hideFunction = function(child) {\n let flexitourRole = child.data('flexitour');\n if (flexitourRole) {\n switch (flexitourRole) {\n case 'container':\n case 'target':\n return;\n }\n }\n\n let hidden = child.attr(attrName);\n if (!hidden) {\n child.attr(stateHolder, true);\n Aria.hide(child);\n }\n };\n\n this.currentStepNode.siblings().each(function(index, node) {\n hideFunction($(node));\n });\n this.currentStepNode.parentsUntil('body').siblings().each(function(index, node) {\n hideFunction($(node));\n });\n }\n\n /**\n * Perform accessibility changes for step hidden.\n *\n * This will remove any newly added aria-hidden=\"true\".\n *\n * @method accessibilityHide\n */\n accessibilityHide() {\n let stateHolder = 'data-has-hidden';\n let showFunction = function(child) {\n let hidden = child.attr(stateHolder);\n if (typeof hidden !== 'undefined') {\n child.removeAttr(stateHolder);\n Aria.unhide(child);\n }\n };\n\n $('[' + stateHolder + ']').each(function(index, node) {\n showFunction($(node));\n });\n }\n};\n\nexport default Tour;\n"],"names":["constructor","config","targetNode","currentElement","window","getComputedStyle","position","parentElement","init","eventHandlers","reset","originalConfiguration","configure","apply","this","arguments","possitionNeedToBeRecalculated","recalculatedNo","storage","sessionStorage","storageKey","tourName","e","hide","resetStepListeners","steps","currentStepNumber","eventName","forEach","handler","addEventHandler","resetStepDefaults","template","templateContent","checkMinimumRequirements","Error","length","loadOriginalConfiguration","stepDefaults","setStepDefaults","extend","element","placement","delay","moveOnClick","moveAfterTime","orphan","direction","getCurrentStepNumber","parseInt","setCurrentStepNumber","stepNumber","setItem","code","DOMException","QUOTA_EXCEEDED_ERR","removeItem","getNextStepNumber","nextStepNumber","isStepPotentiallyVisible","getStepConfig","getPreviousStepNumber","previousStepNumber","isLastStep","stepConfig","isStepActuallyVisible","getPotentiallyVisibleSteps","result","stepId","stepid","isCSSAllowed","target","getStepTarget","is","testCSSElement","document","createElement","classList","add","body","appendChild","isAllowed","display","remove","next","gotoStep","previous","endTour","_gotoStep","pendingPromise","PendingPromise","delayed","setTimeout","resolve","fn","dispatchEvent","eventTypes","stepRender","defaultPrevented","renderStep","stepRendered","normalizeStepConfig","$","reflex","moveAfterClick","content","attachTo","attachPoint","first","detail","cancelable","tour","push","processStepListeners","listeners","node","currentStepNode","args","proxy","handleKeyDown","parents","listener","on","off","currentStepConfig","getTemplateContent","find","html","title","nextBtn","endBtn","removeClass","addClass","prop","then","value","catch","attr","displaystepnumbers","stepsPotentiallyVisible","totalStepsPotentiallyVisible","total","addStepToPage","clone","animationTarget","stop","data","positionBackdrop","append","css","top","left","animate","scrollTop","calculateScrollTop","promise","positionStep","revealStep","bind","isOrphan","currentStepPopper","Popper","removeOnDestroy","arrowElement","modifiers","enabled","applyStyle","onLoad","onCreate","images","calculateStepPositionInPage","fadeIn","announceStep","focus","bodyRegion","headerRegion","accessibilityShow","tabbableSelector","keyCode","hasBackdrop","currentIndex","nextIndex","nextNode","focusRelevant","activeElement","stepTarget","tabbableNodes","dialogContainer","filter","index","has","each","shiftKey","closest","last","preventDefault","call","startTour","startAt","storageStartValue","getItem","storageStartAt","tourStart","tourRunning","tourStarted","restartTour","tourEnd","previousTarget","tourEnded","transition","stepHide","destroy","removeAttr","backdrop","backdropRemovalPromise","fadeOut","currentStepElement","accessibilityHide","stepHidden","show","getStepContainer","viewportHeight","height","scrollParent","hasFixedPosition","offset","Math","max","min","ceil","stepHeight","viewportWidth","width","stepWidth","MINSPACING","maxHeight","outerHeight","flipBehavior","thisT","recalculatePlacement","flip","behaviour","arrow","recalculateArrowPosition","recalculateStepPosition","onUpdate","recalculateBackdropPosition","split","isVertical","indexOf","instance","popper","querySelector","stepElement","arrowHeight","parseFloat","arrowOffset","popperHeight","popperOffset","popperBorderWidth","popperBorderRadiusWidth","arrowPos","maxPos","minPos","newArrowPos","arrowWidth","popperWidth","popperElement","targetElement","reference","targetHeight","outerWidth","targetWidth","options","leftSpace","rightSpace","remainingSpace","maxWidth","topSpace","bottomSpace","currentStepBody","headerEle","footerEle","update","background","widthContent","targetOffsetLeft","targetOffsetRight","documentElement","clientWidth","distanceFromTop","getBoundingClientRect","relativeTop","elementWidth","BUFFER","elementHeight","elementLeft","elementTop","navbarOverlap","navbarHeight","xPlacement","getAttribute","style","radius","bottomRight","topRight","topLeft","bottomLeft","clipPath","x1","y1","x2","y2","calculatePosition","elem","parent","hideFunction","child","flexitourRole","Aria","siblings","parentsUntil","unhide"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"tour.min.js","sources":["../src/tour.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * A user tour.\n *\n * @module tool_usertours/tour\n * @copyright 2018 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * A list of steps.\n *\n * @typedef {Object[]} StepList\n * @property {Number} stepId The id of the step in the database\n * @property {Number} position The position of the step within the tour (zero-indexed)\n */\n\nimport $ from 'jquery';\nimport * as Aria from 'core/aria';\nimport Popper from 'core/popper';\nimport {dispatchEvent} from 'core/event_dispatcher';\nimport {eventTypes} from './events';\nimport {getString} from 'core/str';\nimport {prefetchStrings} from 'core/prefetch';\nimport {notifyFilterContentUpdated} from 'core/event';\nimport PendingPromise from 'core/pending';\n\n/**\n * The minimum spacing for tour step to display.\n *\n * @private\n * @constant\n * @type {number}\n */\nconst MINSPACING = 10;\nconst BUFFER = 10;\n\n/**\n * A user tour.\n *\n * @class tool_usertours/tour\n * @property {boolean} tourRunning Whether the tour is currently running.\n */\nconst Tour = class {\n tourRunning = false;\n\n /**\n * @param {object} config The configuration object.\n */\n constructor(config) {\n this.init(config);\n }\n\n /**\n * Initialise the tour.\n *\n * @method init\n * @param {Object} config The configuration object.\n * @chainable\n * @return {Object} this.\n */\n init(config) {\n // Unset all handlers.\n this.eventHandlers = {};\n\n // Reset the current tour states.\n this.reset();\n\n // Store the initial configuration.\n this.originalConfiguration = config || {};\n\n // Apply configuration.\n this.configure.apply(this, arguments);\n\n // Unset recalculate state.\n this.possitionNeedToBeRecalculated = false;\n\n // Unset recalculate count.\n this.recalculatedNo = 0;\n\n try {\n this.storage = window.sessionStorage;\n this.storageKey = 'tourstate_' + this.tourName;\n } catch (e) {\n this.storage = false;\n this.storageKey = '';\n }\n\n prefetchStrings('tool_usertours', [\n 'nextstep_sequence',\n 'skip_tour'\n ]);\n\n return this;\n }\n\n /**\n * Reset the current tour state.\n *\n * @method reset\n * @chainable\n * @return {Object} this.\n */\n reset() {\n // Hide the current step.\n this.hide();\n\n // Unset all handlers.\n this.eventHandlers = [];\n\n // Unset all listeners.\n this.resetStepListeners();\n\n // Unset the original configuration.\n this.originalConfiguration = {};\n\n // Reset the current step number and list of steps.\n this.steps = [];\n\n // Reset the current step number.\n this.currentStepNumber = 0;\n\n return this;\n }\n\n /**\n * Prepare tour configuration.\n *\n * @method configure\n * @param {Object} config The configuration object.\n * @chainable\n * @return {Object} this.\n */\n configure(config) {\n if (typeof config === 'object') {\n // Tour name.\n if (typeof config.tourName !== 'undefined') {\n this.tourName = config.tourName;\n }\n\n // Set up eventHandlers.\n if (config.eventHandlers) {\n for (let eventName in config.eventHandlers) {\n config.eventHandlers[eventName].forEach(function(handler) {\n this.addEventHandler(eventName, handler);\n }, this);\n }\n }\n\n // Reset the step configuration.\n this.resetStepDefaults(true);\n\n // Configure the steps.\n if (typeof config.steps === 'object') {\n this.steps = config.steps;\n }\n\n if (typeof config.template !== 'undefined') {\n this.templateContent = config.template;\n }\n }\n\n // Check that we have enough to start the tour.\n this.checkMinimumRequirements();\n\n return this;\n }\n\n /**\n * Check that the configuration meets the minimum requirements.\n *\n * @method checkMinimumRequirements\n */\n checkMinimumRequirements() {\n // Need a tourName.\n if (!this.tourName) {\n throw new Error(\"Tour Name required\");\n }\n\n // Need a minimum of one step.\n if (!this.steps || !this.steps.length) {\n throw new Error(\"Steps must be specified\");\n }\n }\n\n /**\n * Reset step default configuration.\n *\n * @method resetStepDefaults\n * @param {Boolean} loadOriginalConfiguration Whether to load the original configuration supplied with the Tour.\n * @chainable\n * @return {Object} this.\n */\n resetStepDefaults(loadOriginalConfiguration) {\n if (typeof loadOriginalConfiguration === 'undefined') {\n loadOriginalConfiguration = true;\n }\n\n this.stepDefaults = {};\n if (!loadOriginalConfiguration || typeof this.originalConfiguration.stepDefaults === 'undefined') {\n this.setStepDefaults({});\n } else {\n this.setStepDefaults(this.originalConfiguration.stepDefaults);\n }\n\n return this;\n }\n\n /**\n * Set the step defaults.\n *\n * @method setStepDefaults\n * @param {Object} stepDefaults The step defaults to apply to all steps\n * @chainable\n * @return {Object} this.\n */\n setStepDefaults(stepDefaults) {\n if (!this.stepDefaults) {\n this.stepDefaults = {};\n }\n $.extend(\n this.stepDefaults,\n {\n element: '',\n placement: 'top',\n delay: 0,\n moveOnClick: false,\n moveAfterTime: 0,\n orphan: false,\n direction: 1,\n },\n stepDefaults\n );\n\n return this;\n }\n\n /**\n * Retrieve the current step number.\n *\n * @method getCurrentStepNumber\n * @return {Number} The current step number\n */\n getCurrentStepNumber() {\n return parseInt(this.currentStepNumber, 10);\n }\n\n /**\n * Store the current step number.\n *\n * @method setCurrentStepNumber\n * @param {Number} stepNumber The current step number\n * @chainable\n */\n setCurrentStepNumber(stepNumber) {\n this.currentStepNumber = stepNumber;\n if (this.storage) {\n try {\n this.storage.setItem(this.storageKey, stepNumber);\n } catch (e) {\n if (e.code === DOMException.QUOTA_EXCEEDED_ERR) {\n this.storage.removeItem(this.storageKey);\n }\n }\n }\n }\n\n /**\n * Get the next step number after the currently displayed step.\n *\n * @method getNextStepNumber\n * @param {Number} stepNumber The current step number\n * @return {Number} The next step number to display\n */\n getNextStepNumber(stepNumber) {\n if (typeof stepNumber === 'undefined') {\n stepNumber = this.getCurrentStepNumber();\n }\n let nextStepNumber = stepNumber + 1;\n\n // Keep checking the remaining steps.\n while (nextStepNumber <= this.steps.length) {\n if (this.isStepPotentiallyVisible(this.getStepConfig(nextStepNumber))) {\n return nextStepNumber;\n }\n nextStepNumber++;\n }\n\n return null;\n }\n\n /**\n * Get the previous step number before the currently displayed step.\n *\n * @method getPreviousStepNumber\n * @param {Number} stepNumber The current step number\n * @return {Number} The previous step number to display\n */\n getPreviousStepNumber(stepNumber) {\n if (typeof stepNumber === 'undefined') {\n stepNumber = this.getCurrentStepNumber();\n }\n let previousStepNumber = stepNumber - 1;\n\n // Keep checking the remaining steps.\n while (previousStepNumber >= 0) {\n if (this.isStepPotentiallyVisible(this.getStepConfig(previousStepNumber))) {\n return previousStepNumber;\n }\n previousStepNumber--;\n }\n\n return null;\n }\n\n /**\n * Is the step the final step number?\n *\n * @method isLastStep\n * @param {Number} stepNumber Step number to test\n * @return {Boolean} Whether the step is the final step\n */\n isLastStep(stepNumber) {\n let nextStepNumber = this.getNextStepNumber(stepNumber);\n\n return nextStepNumber === null;\n }\n\n /**\n * Is this step potentially visible?\n *\n * @method isStepPotentiallyVisible\n * @param {Object} stepConfig The step configuration to normalise\n * @return {Boolean} Whether the step is the potentially visible\n */\n isStepPotentiallyVisible(stepConfig) {\n if (!stepConfig) {\n // Without step config, there can be no step.\n return false;\n }\n\n if (this.isStepActuallyVisible(stepConfig)) {\n // If it is actually visible, it is already potentially visible.\n return true;\n }\n\n if (typeof stepConfig.orphan !== 'undefined' && stepConfig.orphan) {\n // Orphan steps have no target. They are always visible.\n return true;\n }\n\n if (typeof stepConfig.delay !== 'undefined' && stepConfig.delay) {\n // Only return true if the activated has not been used yet.\n return true;\n }\n\n // Not theoretically, or actually visible.\n return false;\n }\n\n /**\n * Get potentially visible steps in a tour.\n *\n * @returns {StepList} A list of ordered steps\n */\n getPotentiallyVisibleSteps() {\n let position = 1;\n let result = [];\n // Checking the total steps.\n for (let stepNumber = 0; stepNumber < this.steps.length; stepNumber++) {\n const stepConfig = this.getStepConfig(stepNumber);\n if (this.isStepPotentiallyVisible(stepConfig)) {\n result[stepNumber] = {stepId: stepConfig.stepid, position: position};\n position++;\n }\n }\n\n return result;\n }\n\n /**\n * Is this step actually visible?\n *\n * @method isStepActuallyVisible\n * @param {Object} stepConfig The step configuration to normalise\n * @return {Boolean} Whether the step is actually visible\n */\n isStepActuallyVisible(stepConfig) {\n if (!stepConfig) {\n // Without step config, there can be no step.\n return false;\n }\n\n // Check if the CSS styles are allowed on the browser or not.\n if (!this.isCSSAllowed()) {\n return false;\n }\n\n let target = this.getStepTarget(stepConfig);\n if (target && target.length && target.is(':visible')) {\n // Without a target, there can be no step.\n return !!target.length;\n }\n\n return false;\n }\n\n /**\n * Is the browser actually allow CSS styles?\n *\n * @returns {boolean} True if the browser is allowing CSS styles\n */\n isCSSAllowed() {\n const testCSSElement = document.createElement('div');\n testCSSElement.classList.add('hide');\n document.body.appendChild(testCSSElement);\n const styles = window.getComputedStyle(testCSSElement);\n const isAllowed = styles.display === 'none';\n testCSSElement.remove();\n\n return isAllowed;\n }\n\n /**\n * Go to the next step in the tour.\n *\n * @method next\n * @chainable\n * @return {Object} this.\n */\n next() {\n return this.gotoStep(this.getNextStepNumber());\n }\n\n /**\n * Go to the previous step in the tour.\n *\n * @method previous\n * @chainable\n * @return {Object} this.\n */\n previous() {\n return this.gotoStep(this.getPreviousStepNumber(), -1);\n }\n\n /**\n * Go to the specified step in the tour.\n *\n * @method gotoStep\n * @param {Number} stepNumber The step number to display\n * @param {Number} direction Next or previous step\n * @chainable\n * @return {Object} this.\n * @fires tool_usertours/stepRender\n * @fires tool_usertours/stepRendered\n * @fires tool_usertours/stepHide\n * @fires tool_usertours/stepHidden\n */\n gotoStep(stepNumber, direction) {\n if (stepNumber < 0) {\n return this.endTour();\n }\n\n let stepConfig = this.getStepConfig(stepNumber);\n if (stepConfig === null) {\n return this.endTour();\n }\n\n return this._gotoStep(stepConfig, direction);\n }\n\n _gotoStep(stepConfig, direction) {\n if (!stepConfig) {\n return this.endTour();\n }\n\n const pendingPromise = new PendingPromise(`tool_usertours/tour:_gotoStep-${stepConfig.stepNumber}`);\n\n if (typeof stepConfig.delay !== 'undefined' && stepConfig.delay && !stepConfig.delayed) {\n stepConfig.delayed = true;\n window.setTimeout(function(stepConfig, direction) {\n this._gotoStep(stepConfig, direction);\n pendingPromise.resolve();\n }, stepConfig.delay, stepConfig, direction);\n\n return this;\n } else if (!stepConfig.orphan && !this.isStepActuallyVisible(stepConfig)) {\n const fn = direction == -1 ? 'getPreviousStepNumber' : 'getNextStepNumber';\n this.gotoStep(this[fn](stepConfig.stepNumber), direction);\n\n pendingPromise.resolve();\n return this;\n }\n\n this.hide();\n\n const stepRenderEvent = this.dispatchEvent(eventTypes.stepRender, {stepConfig}, true);\n if (!stepRenderEvent.defaultPrevented) {\n this.renderStep(stepConfig);\n this.dispatchEvent(eventTypes.stepRendered, {stepConfig});\n }\n\n pendingPromise.resolve();\n return this;\n }\n\n /**\n * Fetch the normalised step configuration for the specified step number.\n *\n * @method getStepConfig\n * @param {Number} stepNumber The step number to fetch configuration for\n * @return {Object} The step configuration\n */\n getStepConfig(stepNumber) {\n if (stepNumber === null || stepNumber < 0 || stepNumber >= this.steps.length) {\n return null;\n }\n\n // Normalise the step configuration.\n let stepConfig = this.normalizeStepConfig(this.steps[stepNumber]);\n\n // Add the stepNumber to the stepConfig.\n stepConfig = $.extend(stepConfig, {stepNumber: stepNumber});\n\n return stepConfig;\n }\n\n /**\n * Normalise the supplied step configuration.\n *\n * @method normalizeStepConfig\n * @param {Object} stepConfig The step configuration to normalise\n * @return {Object} The normalised step configuration\n */\n normalizeStepConfig(stepConfig) {\n\n if (typeof stepConfig.reflex !== 'undefined' && typeof stepConfig.moveAfterClick === 'undefined') {\n stepConfig.moveAfterClick = stepConfig.reflex;\n }\n\n if (typeof stepConfig.element !== 'undefined' && typeof stepConfig.target === 'undefined') {\n stepConfig.target = stepConfig.element;\n }\n\n if (typeof stepConfig.content !== 'undefined' && typeof stepConfig.body === 'undefined') {\n stepConfig.body = stepConfig.content;\n }\n\n stepConfig = $.extend({}, this.stepDefaults, stepConfig);\n\n stepConfig = $.extend({}, {\n attachTo: stepConfig.target,\n attachPoint: 'after',\n }, stepConfig);\n\n if (stepConfig.attachTo) {\n stepConfig.attachTo = $(stepConfig.attachTo).first();\n }\n\n return stepConfig;\n }\n\n /**\n * Fetch the actual step target from the selector.\n *\n * This should not be called until after any delay has completed.\n *\n * @method getStepTarget\n * @param {Object} stepConfig The step configuration\n * @return {$}\n */\n getStepTarget(stepConfig) {\n if (stepConfig.target) {\n return $(stepConfig.target);\n }\n\n return null;\n }\n\n /**\n * Fire any event handlers for the specified event.\n *\n * @param {String} eventName The name of the event\n * @param {Object} [detail={}] Any additional details to pass into the eveent\n * @param {Boolean} [cancelable=false] Whether preventDefault() can be called\n * @returns {CustomEvent}\n */\n dispatchEvent(\n eventName,\n detail = {},\n cancelable = false\n ) {\n return dispatchEvent(eventName, {\n // Add the tour to the detail.\n tour: this,\n ...detail,\n }, document, {\n cancelable,\n });\n }\n\n /**\n * @method addEventHandler\n * @param {string} eventName The name of the event to listen for\n * @param {function} handler The event handler to call\n * @return {Object} this.\n */\n addEventHandler(eventName, handler) {\n if (typeof this.eventHandlers[eventName] === 'undefined') {\n this.eventHandlers[eventName] = [];\n }\n\n this.eventHandlers[eventName].push(handler);\n\n return this;\n }\n\n /**\n * Process listeners for the step being shown.\n *\n * @method processStepListeners\n * @param {object} stepConfig The configuration for the step\n * @chainable\n * @return {Object} this.\n */\n processStepListeners(stepConfig) {\n this.listeners.push(\n // Next button.\n {\n node: this.currentStepNode,\n args: ['click', '[data-role=\"next\"]', $.proxy(this.next, this)]\n },\n\n // Close and end tour buttons.\n {\n node: this.currentStepNode,\n args: ['click', '[data-role=\"end\"]', $.proxy(this.endTour, this)]\n },\n\n // Click backdrop and hide tour.\n {\n node: $('[data-flexitour=\"backdrop\"]'),\n args: ['click', $.proxy(this.hide, this)]\n },\n\n // Keypresses.\n {\n node: $('body'),\n args: ['keydown', $.proxy(this.handleKeyDown, this)]\n });\n\n if (stepConfig.moveOnClick) {\n var targetNode = this.getStepTarget(stepConfig);\n this.listeners.push({\n node: targetNode,\n args: ['click', $.proxy(function(e) {\n if ($(e.target).parents('[data-flexitour=\"container\"]').length === 0) {\n // Ignore clicks when they are in the flexitour.\n window.setTimeout($.proxy(this.next, this), 500);\n }\n }, this)]\n });\n }\n\n this.listeners.forEach(function(listener) {\n listener.node.on.apply(listener.node, listener.args);\n });\n\n return this;\n }\n\n /**\n * Reset step listeners.\n *\n * @method resetStepListeners\n * @chainable\n * @return {Object} this.\n */\n resetStepListeners() {\n // Stop listening to all external handlers.\n if (this.listeners) {\n this.listeners.forEach(function(listener) {\n listener.node.off.apply(listener.node, listener.args);\n });\n }\n this.listeners = [];\n\n return this;\n }\n\n /**\n * The standard step renderer.\n *\n * @method renderStep\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n * @return {Object} this.\n */\n renderStep(stepConfig) {\n // Store the current step configuration for later.\n this.currentStepConfig = stepConfig;\n this.setCurrentStepNumber(stepConfig.stepNumber);\n\n // Fetch the template and convert it to a $ object.\n let template = $(this.getTemplateContent());\n\n // Title.\n template.find('[data-placeholder=\"title\"]')\n .html(stepConfig.title);\n\n // Body.\n template.find('[data-placeholder=\"body\"]')\n .html(stepConfig.body);\n\n // Buttons.\n const nextBtn = template.find('[data-role=\"next\"]');\n const endBtn = template.find('[data-role=\"end\"]');\n\n // Is this the final step?\n if (this.isLastStep(stepConfig.stepNumber)) {\n nextBtn.hide();\n endBtn.removeClass(\"btn-secondary\").addClass(\"btn-primary\");\n } else {\n nextBtn.prop('disabled', false);\n // Use Skip tour label for the End tour button.\n getString('skip_tour', 'tool_usertours').then(value => {\n endBtn.html(value);\n return;\n }).catch();\n }\n\n nextBtn.attr('role', 'button');\n endBtn.attr('role', 'button');\n\n if (this.originalConfiguration.displaystepnumbers) {\n const stepsPotentiallyVisible = this.getPotentiallyVisibleSteps();\n const totalStepsPotentiallyVisible = stepsPotentiallyVisible.length;\n const position = stepsPotentiallyVisible[stepConfig.stepNumber].position;\n if (totalStepsPotentiallyVisible > 1) {\n // Change the label of the Next button to include the sequence.\n getString('nextstep_sequence', 'tool_usertours',\n {position: position, total: totalStepsPotentiallyVisible}).then(value => {\n nextBtn.html(value);\n return;\n }).catch();\n }\n }\n\n // Replace the template with the updated version.\n stepConfig.template = template;\n\n // Add to the page.\n this.addStepToPage(stepConfig);\n\n // Process step listeners after adding to the page.\n // This uses the currentNode.\n this.processStepListeners(stepConfig);\n\n return this;\n }\n\n /**\n * Getter for the template content.\n *\n * @method getTemplateContent\n * @return {$}\n */\n getTemplateContent() {\n return $(this.templateContent).clone();\n }\n\n /**\n * Helper to add a step to the page.\n *\n * @method addStepToPage\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n * @return {Object} this.\n */\n addStepToPage(stepConfig) {\n // Create the stepNode from the template data.\n let currentStepNode = $('')\n .html(stepConfig.template)\n .hide();\n // Trigger the Moodle filters.\n notifyFilterContentUpdated(currentStepNode);\n\n // The scroll animation occurs on the body or html.\n let animationTarget = $('body, html')\n .stop(true, true);\n\n if (this.isStepActuallyVisible(stepConfig)) {\n let targetNode = this.getStepTarget(stepConfig);\n\n targetNode.data('flexitour', 'target');\n\n $(document.body).append(currentStepNode);\n this.currentStepNode = currentStepNode;\n\n // Ensure that the step node is positioned.\n // Some situations mean that the value is not properly calculated without this step.\n this.currentStepNode.css({\n top: 0,\n left: 0,\n });\n\n const pendingPromise = new PendingPromise(`tool_usertours/tour:addStepToPage-${stepConfig.stepNumber}`);\n animationTarget\n .animate({\n scrollTop: this.calculateScrollTop(stepConfig),\n }).promise().then(function() {\n this.positionBackdrop(stepConfig);\n this.positionStep(stepConfig);\n this.revealStep(stepConfig);\n pendingPromise.resolve();\n return;\n }.bind(this))\n .catch(function() {\n // Silently fail.\n });\n\n } else if (stepConfig.orphan) {\n stepConfig.isOrphan = true;\n\n // This will be appended to the body instead.\n stepConfig.attachTo = $('body').first();\n stepConfig.attachPoint = 'append';\n\n // Add the backdrop.\n this.positionBackdrop(stepConfig);\n\n // This is an orphaned step.\n currentStepNode.addClass('orphan');\n\n // It lives in the body.\n $(document.body).append(currentStepNode);\n this.currentStepNode = currentStepNode;\n\n this.currentStepNode.css('position', 'fixed');\n\n this.currentStepPopper = new Popper(\n $('body'),\n this.currentStepNode[0], {\n removeOnDestroy: true,\n placement: stepConfig.placement + '-start',\n arrowElement: '[data-role=\"arrow\"]',\n // Empty the modifiers. We've already placed the step and don't want it moved.\n modifiers: {\n hide: {\n enabled: false,\n },\n applyStyle: {\n onLoad: null,\n enabled: false,\n },\n },\n onCreate: () => {\n // First, we need to check if the step's content contains any images.\n const images = this.currentStepNode.find('img');\n if (images.length) {\n // Images found, need to calculate the position when the image is loaded.\n images.on('load', () => {\n this.calculateStepPositionInPage(currentStepNode);\n });\n }\n this.calculateStepPositionInPage(currentStepNode);\n }\n }\n );\n\n this.revealStep(stepConfig);\n }\n\n return this;\n }\n\n /**\n * Make the given step visible.\n *\n * @method revealStep\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n * @return {Object} this.\n */\n revealStep(stepConfig) {\n // Fade the step in.\n const pendingPromise = new PendingPromise(`tool_usertours/tour:revealStep-${stepConfig.stepNumber}`);\n this.currentStepNode.fadeIn('', $.proxy(function() {\n // Announce via ARIA.\n this.announceStep(stepConfig);\n\n // Focus on the current step Node.\n this.currentStepNode.focus();\n window.setTimeout($.proxy(function() {\n // After a brief delay, focus again.\n // There seems to be an issue with Jaws where it only reads the dialogue title initially.\n // This second focus helps it to read the full dialogue.\n if (this.currentStepNode) {\n this.currentStepNode.focus();\n }\n pendingPromise.resolve();\n }, this), 100);\n\n }, this));\n\n return this;\n }\n\n /**\n * Helper to announce the step on the page.\n *\n * @method announceStep\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n * @return {Object} this.\n */\n announceStep(stepConfig) {\n // Setup the step Dialogue as per:\n // * https://www.w3.org/TR/wai-aria-practices/#dialog_nonmodal\n // * https://www.w3.org/TR/wai-aria-practices/#dialog_modal\n\n // Generate an ID for the current step node.\n let stepId = 'tour-step-' + this.tourName + '-' + stepConfig.stepNumber;\n this.currentStepNode.attr('id', stepId);\n\n let bodyRegion = this.currentStepNode.find('[data-placeholder=\"body\"]').first();\n bodyRegion.attr('id', stepId + '-body');\n bodyRegion.attr('role', 'document');\n\n let headerRegion = this.currentStepNode.find('[data-placeholder=\"title\"]').first();\n headerRegion.attr('id', stepId + '-title');\n headerRegion.attr('aria-labelledby', stepId + '-body');\n\n // Generally, a modal dialog has a role of dialog.\n this.currentStepNode.attr('role', 'dialog');\n this.currentStepNode.attr('tabindex', 0);\n this.currentStepNode.attr('aria-labelledby', stepId + '-title');\n this.currentStepNode.attr('aria-describedby', stepId + '-body');\n\n // Configure ARIA attributes on the target.\n let target = this.getStepTarget(stepConfig);\n if (target) {\n target.data('original-tabindex', target.attr('tabindex'));\n if (!target.attr('tabindex')) {\n target.attr('tabindex', 0);\n }\n\n target\n .data('original-describedby', target.attr('aria-describedby'))\n .attr('aria-describedby', stepId + '-body')\n ;\n }\n\n this.accessibilityShow(stepConfig);\n\n return this;\n }\n\n /**\n * Handle key down events.\n *\n * @method handleKeyDown\n * @param {EventFacade} e\n */\n handleKeyDown(e) {\n let tabbableSelector = 'a[href], link[href], [draggable=true], [contenteditable=true], ';\n tabbableSelector += ':input:enabled, [tabindex], button:enabled';\n switch (e.keyCode) {\n case 27:\n this.endTour();\n break;\n\n // 9 == Tab - trap focus for items with a backdrop.\n case 9:\n // Tab must be handled on key up only in this instance.\n (function() {\n if (!this.currentStepConfig.hasBackdrop) {\n // Trapping tab focus is only handled for those steps with a backdrop.\n return;\n }\n\n // Find all tabbable locations.\n let activeElement = $(document.activeElement);\n let stepTarget = this.getStepTarget(this.currentStepConfig);\n let tabbableNodes = $(tabbableSelector);\n let dialogContainer = $('span[data-flexitour=\"container\"]');\n let currentIndex;\n // Filter out element which is not belong to target section or dialogue.\n if (stepTarget) {\n tabbableNodes = tabbableNodes.filter(function(index, element) {\n return stepTarget !== null\n && (stepTarget.has(element).length\n || dialogContainer.has(element).length\n || stepTarget.is(element)\n || dialogContainer.is(element));\n });\n }\n\n // Find index of focusing element.\n tabbableNodes.each(function(index, element) {\n if (activeElement.is(element)) {\n currentIndex = index;\n return false;\n }\n // Keep looping.\n return true;\n });\n\n let nextIndex;\n let nextNode;\n let focusRelevant;\n if (currentIndex != void 0) {\n let direction = 1;\n if (e.shiftKey) {\n direction = -1;\n }\n nextIndex = currentIndex;\n do {\n nextIndex += direction;\n nextNode = $(tabbableNodes[nextIndex]);\n } while (nextNode.length && nextNode.is(':disabled') || nextNode.is(':hidden'));\n if (nextNode.length) {\n // A new f\n focusRelevant = nextNode.closest(stepTarget).length;\n focusRelevant = focusRelevant || nextNode.closest(this.currentStepNode).length;\n } else {\n // Unable to find the target somehow.\n focusRelevant = false;\n }\n }\n\n if (focusRelevant) {\n nextNode.focus();\n } else {\n if (e.shiftKey) {\n // Focus on the last tabbable node in the step.\n this.currentStepNode.find(tabbableSelector).last().focus();\n } else {\n if (this.currentStepConfig.isOrphan) {\n // Focus on the step - there is no target.\n this.currentStepNode.focus();\n } else {\n // Focus on the step target.\n stepTarget.focus();\n }\n }\n }\n e.preventDefault();\n }).call(this);\n break;\n }\n }\n\n /**\n * Start the current tour.\n *\n * @method startTour\n * @param {Number} startAt Which step number to start at. If not specified, starts at the last point.\n * @chainable\n * @return {Object} this.\n * @fires tool_usertours/tourStart\n * @fires tool_usertours/tourStarted\n */\n startTour(startAt) {\n if (this.storage && typeof startAt === 'undefined') {\n let storageStartValue = this.storage.getItem(this.storageKey);\n if (storageStartValue) {\n let storageStartAt = parseInt(storageStartValue, 10);\n if (storageStartAt <= this.steps.length) {\n startAt = storageStartAt;\n }\n }\n }\n\n if (typeof startAt === 'undefined') {\n startAt = this.getCurrentStepNumber();\n }\n\n const tourStartEvent = this.dispatchEvent(eventTypes.tourStart, {startAt}, true);\n if (!tourStartEvent.defaultPrevented) {\n this.gotoStep(startAt);\n this.tourRunning = true;\n this.dispatchEvent(eventTypes.tourStarted, {startAt});\n }\n\n return this;\n }\n\n /**\n * Restart the tour from the beginning, resetting the completionlag.\n *\n * @method restartTour\n * @chainable\n * @return {Object} this.\n */\n restartTour() {\n return this.startTour(0);\n }\n\n /**\n * End the current tour.\n *\n * @method endTour\n * @chainable\n * @return {Object} this.\n * @fires tool_usertours/tourEnd\n * @fires tool_usertours/tourEnded\n */\n endTour() {\n const tourEndEvent = this.dispatchEvent(eventTypes.tourEnd, {}, true);\n if (tourEndEvent.defaultPrevented) {\n return this;\n }\n\n if (this.currentStepConfig) {\n let previousTarget = this.getStepTarget(this.currentStepConfig);\n if (previousTarget) {\n if (!previousTarget.attr('tabindex')) {\n previousTarget.attr('tabindex', '-1');\n }\n previousTarget.first().focus();\n }\n }\n\n this.hide(true);\n\n this.tourRunning = false;\n this.dispatchEvent(eventTypes.tourEnded);\n\n return this;\n }\n\n /**\n * Hide any currently visible steps.\n *\n * @method hide\n * @param {Bool} transition Animate the visibility change\n * @chainable\n * @return {Object} this.\n * @fires tool_usertours/stepHide\n * @fires tool_usertours/stepHidden\n */\n hide(transition) {\n const stepHideEvent = this.dispatchEvent(eventTypes.stepHide, {}, true);\n if (stepHideEvent.defaultPrevented) {\n return this;\n }\n\n const pendingPromise = new PendingPromise('tool_usertours/tour:hide');\n if (this.currentStepNode && this.currentStepNode.length) {\n this.currentStepNode.hide();\n if (this.currentStepPopper) {\n this.currentStepPopper.destroy();\n }\n }\n\n // Restore original target configuration.\n if (this.currentStepConfig) {\n let target = this.getStepTarget(this.currentStepConfig);\n if (target) {\n if (target.data('original-labelledby')) {\n target.attr('aria-labelledby', target.data('original-labelledby'));\n }\n\n if (target.data('original-describedby')) {\n target.attr('aria-describedby', target.data('original-describedby'));\n }\n\n if (target.data('original-tabindex')) {\n target.attr('tabindex', target.data('tabindex'));\n } else {\n // If the target does not have the tabindex attribute at the beginning. We need to remove it.\n // We should wait a little here before removing the attribute to prevent the browser from adding it again.\n window.setTimeout(() => {\n target.removeAttr('tabindex');\n }, 400);\n }\n }\n\n // Clear the step configuration.\n this.currentStepConfig = null;\n }\n\n // Remove the highlight attribute when the hide occurs.\n $('[data-flexitour=\"highlight\"]').removeAttr('data-flexitour');\n\n const backdrop = $('[data-flexitour=\"backdrop\"]');\n if (backdrop.length) {\n if (transition) {\n const backdropRemovalPromise = new PendingPromise('tool_usertours/tour:hide:backdrop');\n backdrop.fadeOut(400, function() {\n $(this).remove();\n backdropRemovalPromise.resolve();\n });\n } else {\n backdrop.remove();\n }\n }\n\n // Remove aria-describedby and tabindex attributes.\n if (this.currentStepNode && this.currentStepNode.length) {\n let stepId = this.currentStepNode.attr('id');\n if (stepId) {\n let currentStepElement = '[aria-describedby=\"' + stepId + '-body\"]';\n $(currentStepElement).removeAttr('tabindex');\n $(currentStepElement).removeAttr('aria-describedby');\n }\n }\n\n // Reset the listeners.\n this.resetStepListeners();\n\n this.accessibilityHide();\n\n this.dispatchEvent(eventTypes.stepHidden);\n\n this.currentStepNode = null;\n this.currentStepPopper = null;\n\n pendingPromise.resolve();\n return this;\n }\n\n /**\n * Show the current steps.\n *\n * @method show\n * @chainable\n * @return {Object} this.\n */\n show() {\n // Show the current step.\n let startAt = this.getCurrentStepNumber();\n\n return this.gotoStep(startAt);\n }\n\n /**\n * Return the current step node.\n *\n * @method getStepContainer\n * @return {jQuery}\n */\n getStepContainer() {\n return $(this.currentStepNode);\n }\n\n /**\n * Check whether the target node has a fixed position, or is nested within one.\n *\n * @param {Object} targetNode The target element to check.\n * @return {Boolean} Return true if fixed position found.\n */\n hasFixedPosition = (targetNode) => {\n let currentElement = targetNode[0];\n while (currentElement) {\n const computedStyle = window.getComputedStyle(currentElement);\n if (computedStyle.position === 'fixed') {\n return true;\n }\n currentElement = currentElement.parentElement;\n }\n\n return false;\n };\n\n /**\n * Calculate scrollTop.\n *\n * @method calculateScrollTop\n * @param {Object} stepConfig The step configuration of the step\n * @return {Number}\n */\n calculateScrollTop(stepConfig) {\n let viewportHeight = $(window).height();\n let targetNode = this.getStepTarget(stepConfig);\n\n let scrollParent = $(window);\n if (targetNode.parents('[data-usertour=\"scroller\"]').length) {\n scrollParent = targetNode.parents('[data-usertour=\"scroller\"]');\n }\n let scrollTop = scrollParent.scrollTop();\n\n if (this.hasFixedPosition(targetNode)) {\n // Target must be in a fixed or custom position. No need to modify the scrollTop.\n } else if (stepConfig.placement === 'top') {\n // If the placement is top, center scroll at the top of the target.\n scrollTop = targetNode.offset().top - (viewportHeight / 2);\n } else if (stepConfig.placement === 'bottom') {\n // If the placement is bottom, center scroll at the bottom of the target.\n scrollTop = targetNode.offset().top + targetNode.height() + scrollTop - (viewportHeight / 2);\n } else if (targetNode.height() <= (viewportHeight * 0.8)) {\n // If the placement is left/right, and the target fits in the viewport, centre screen on the target\n scrollTop = targetNode.offset().top - ((viewportHeight - targetNode.height()) / 2);\n } else {\n // If the placement is left/right, and the target is bigger than the viewport, set scrollTop to target.top + buffer\n // and change step attachmentTarget to top+.\n scrollTop = targetNode.offset().top - (viewportHeight * 0.2);\n }\n\n // Never scroll over the top.\n scrollTop = Math.max(0, scrollTop);\n\n // Never scroll beyond the bottom.\n scrollTop = Math.min($(document).height() - viewportHeight, scrollTop);\n\n return Math.ceil(scrollTop);\n }\n\n /**\n * Calculate dialogue position for page middle.\n *\n * @param {jQuery} currentStepNode Current step node\n * @method calculateScrollTop\n */\n calculateStepPositionInPage(currentStepNode) {\n let top = MINSPACING;\n const viewportHeight = $(window).height();\n const stepHeight = currentStepNode.height();\n const viewportWidth = $(window).width();\n const stepWidth = currentStepNode.width();\n if (viewportHeight >= (stepHeight + (MINSPACING * 2))) {\n top = Math.ceil((viewportHeight - stepHeight) / 2);\n } else {\n const headerHeight = currentStepNode.find('.modal-header').first().outerHeight() ?? 0;\n const footerHeight = currentStepNode.find('.modal-footer').first().outerHeight() ?? 0;\n const currentStepBody = currentStepNode.find('[data-placeholder=\"body\"]').first();\n const maxHeight = viewportHeight - (MINSPACING * 2) - headerHeight - footerHeight;\n currentStepBody.css({\n 'max-height': maxHeight + 'px',\n 'overflow': 'auto',\n });\n }\n currentStepNode.offset({\n top: top,\n left: Math.ceil((viewportWidth - stepWidth) / 2)\n });\n }\n\n /**\n * Position the step on the page.\n *\n * @method positionStep\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n * @return {Object} this.\n */\n positionStep(stepConfig) {\n let content = this.currentStepNode;\n let thisT = this;\n if (!content || !content.length) {\n // Unable to find the step node.\n return this;\n }\n\n stepConfig.placement = this.recalculatePlacement(stepConfig);\n let flipBehavior;\n switch (stepConfig.placement) {\n case 'left':\n flipBehavior = ['left', 'right', 'top', 'bottom'];\n break;\n case 'right':\n flipBehavior = ['right', 'left', 'top', 'bottom'];\n break;\n case 'top':\n flipBehavior = ['top', 'bottom', 'right', 'left'];\n break;\n case 'bottom':\n flipBehavior = ['bottom', 'top', 'right', 'left'];\n break;\n default:\n flipBehavior = 'flip';\n break;\n }\n\n let offset = '0';\n if (stepConfig.backdrop) {\n // Offset the arrow so that it points to the cut-out in the backdrop.\n offset = `-${BUFFER}, ${BUFFER}`;\n }\n\n let target = this.getStepTarget(stepConfig);\n var config = {\n placement: stepConfig.placement + '-start',\n removeOnDestroy: true,\n modifiers: {\n flip: {\n behaviour: flipBehavior,\n },\n arrow: {\n element: '[data-role=\"arrow\"]',\n },\n offset: {\n offset: offset\n }\n },\n onCreate: function(data) {\n recalculateArrowPosition(data);\n recalculateStepPosition(data);\n },\n onUpdate: function(data) {\n recalculateArrowPosition(data);\n if (thisT.possitionNeedToBeRecalculated) {\n thisT.recalculatedNo++;\n thisT.possitionNeedToBeRecalculated = false;\n recalculateStepPosition(data);\n }\n // Reset backdrop position when things update.\n thisT.recalculateBackdropPosition(stepConfig);\n },\n };\n\n let recalculateArrowPosition = function(data) {\n let placement = data.placement.split('-')[0];\n const isVertical = ['left', 'right'].indexOf(placement) !== -1;\n const arrowElement = data.instance.popper.querySelector('[data-role=\"arrow\"]');\n const stepElement = $(data.instance.popper.querySelector('[data-role=\"flexitour-step\"]'));\n if (isVertical) {\n let arrowHeight = parseFloat(window.getComputedStyle(arrowElement).height);\n let arrowOffset = parseFloat(window.getComputedStyle(arrowElement).top);\n let popperHeight = parseFloat(window.getComputedStyle(data.instance.popper).height);\n let popperOffset = parseFloat(window.getComputedStyle(data.instance.popper).top);\n let popperBorderWidth = parseFloat(stepElement.css('borderTopWidth'));\n let popperBorderRadiusWidth = parseFloat(stepElement.css('borderTopLeftRadius')) * 2;\n let arrowPos = arrowOffset + (arrowHeight / 2);\n let maxPos = popperHeight + popperOffset - popperBorderWidth - popperBorderRadiusWidth;\n let minPos = popperOffset + popperBorderWidth + popperBorderRadiusWidth;\n if (arrowPos >= maxPos || arrowPos <= minPos) {\n let newArrowPos = 0;\n if (arrowPos > (popperHeight / 2)) {\n newArrowPos = maxPos - arrowHeight;\n } else {\n newArrowPos = minPos + arrowHeight;\n }\n $(arrowElement).css('top', newArrowPos);\n }\n } else {\n let arrowWidth = parseFloat(window.getComputedStyle(arrowElement).width);\n let arrowOffset = parseFloat(window.getComputedStyle(arrowElement).left);\n let popperWidth = parseFloat(window.getComputedStyle(data.instance.popper).width);\n let popperOffset = parseFloat(window.getComputedStyle(data.instance.popper).left);\n let popperBorderWidth = parseFloat(stepElement.css('borderTopWidth'));\n let popperBorderRadiusWidth = parseFloat(stepElement.css('borderTopLeftRadius')) * 2;\n let arrowPos = arrowOffset + (arrowWidth / 2);\n let maxPos = popperWidth + popperOffset - popperBorderWidth - popperBorderRadiusWidth;\n let minPos = popperOffset + popperBorderWidth + popperBorderRadiusWidth;\n if (arrowPos >= maxPos || arrowPos <= minPos) {\n let newArrowPos = 0;\n if (arrowPos > (popperWidth / 2)) {\n newArrowPos = maxPos - arrowWidth;\n } else {\n newArrowPos = minPos + arrowWidth;\n }\n $(arrowElement).css('left', newArrowPos);\n }\n }\n };\n\n const recalculateStepPosition = function(data) {\n const placement = data.placement.split('-')[0];\n const isVertical = ['left', 'right'].indexOf(placement) !== -1;\n const popperElement = $(data.instance.popper);\n const targetElement = $(data.instance.reference);\n const arrowElement = popperElement.find('[data-role=\"arrow\"]');\n const stepElement = popperElement.find('[data-role=\"flexitour-step\"]');\n const viewportHeight = $(window).height();\n const viewportWidth = $(window).width();\n const arrowHeight = parseFloat(arrowElement.outerHeight(true));\n const popperHeight = parseFloat(popperElement.outerHeight(true));\n const targetHeight = parseFloat(targetElement.outerHeight(true));\n const arrowWidth = parseFloat(arrowElement.outerWidth(true));\n const popperWidth = parseFloat(popperElement.outerWidth(true));\n const targetWidth = parseFloat(targetElement.outerWidth(true));\n let maxHeight;\n\n if (thisT.recalculatedNo > 1) {\n // The current screen is too small, and cannot fit with the original placement.\n // We should set the placement to auto so the PopperJS can calculate the perfect placement.\n thisT.currentStepPopper.options.placement = isVertical ? 'auto-left' : 'auto-bottom';\n }\n if (thisT.recalculatedNo > 2) {\n // Return here to prevent recursive calling.\n return;\n }\n\n if (isVertical) {\n // Find the best place to put the tour: Left of right.\n const leftSpace = targetElement.offset().left > 0 ? targetElement.offset().left : 0;\n const rightSpace = viewportWidth - leftSpace - targetWidth;\n const remainingSpace = leftSpace >= rightSpace ? leftSpace : rightSpace;\n maxHeight = viewportHeight - MINSPACING * 2;\n if (remainingSpace < (popperWidth + arrowWidth)) {\n const maxWidth = remainingSpace - MINSPACING - arrowWidth;\n if (maxWidth > 0) {\n popperElement.css({\n 'max-width': maxWidth + 'px',\n });\n // Not enough space, flag true to make Popper to recalculate the position.\n thisT.possitionNeedToBeRecalculated = true;\n }\n } else if (maxHeight < popperHeight) {\n // Check if the Popper's height can fit the viewport height or not.\n // If not, set the correct max-height value for the Popper element.\n popperElement.css({\n 'max-height': maxHeight + 'px',\n });\n }\n } else {\n // Find the best place to put the tour: Top of bottom.\n const topSpace = targetElement.offset().top > 0 ? targetElement.offset().top : 0;\n const bottomSpace = viewportHeight - topSpace - targetHeight;\n const remainingSpace = topSpace >= bottomSpace ? topSpace : bottomSpace;\n maxHeight = remainingSpace - MINSPACING - arrowHeight;\n if (remainingSpace < (popperHeight + arrowHeight)) {\n // Not enough space, flag true to make Popper to recalculate the position.\n thisT.possitionNeedToBeRecalculated = true;\n }\n }\n\n // Check if the Popper's height can fit the viewport height or not.\n // If not, set the correct max-height value for the body.\n const currentStepBody = stepElement.find('[data-placeholder=\"body\"]').first();\n const headerEle = stepElement.find('.modal-header').first();\n const footerEle = stepElement.find('.modal-footer').first();\n const headerHeight = headerEle.outerHeight(true) ?? 0;\n const footerHeight = footerEle.outerHeight(true) ?? 0;\n maxHeight = maxHeight - headerHeight - footerHeight;\n if (maxHeight > 0) {\n headerEle.removeClass('minimal');\n footerEle.removeClass('minimal');\n currentStepBody.css({\n 'max-height': maxHeight + 'px',\n 'overflow': 'auto',\n });\n } else {\n headerEle.addClass('minimal');\n footerEle.addClass('minimal');\n }\n // Call the Popper update method to update the position.\n thisT.currentStepPopper.update();\n };\n\n let background = $('[data-flexitour=\"highlight\"]');\n if (background.length) {\n target = background;\n }\n this.currentStepPopper = new Popper(target, content[0], config);\n\n return this;\n }\n\n /**\n * For left/right placement, checks that there is room for the step at current window size.\n *\n * If there is not enough room, changes placement to 'top'.\n *\n * @method recalculatePlacement\n * @param {Object} stepConfig The step configuration of the step\n * @return {String} The placement after recalculate\n */\n recalculatePlacement(stepConfig) {\n const arrowWidth = 16;\n let target = this.getStepTarget(stepConfig);\n let widthContent = this.currentStepNode.width() + arrowWidth;\n let targetOffsetLeft = target.offset().left - BUFFER;\n let targetOffsetRight = target.offset().left + target.width() + BUFFER;\n let placement = stepConfig.placement;\n\n if (['left', 'right'].indexOf(placement) !== -1) {\n if ((targetOffsetLeft < (widthContent + BUFFER)) &&\n ((targetOffsetRight + widthContent + BUFFER) > document.documentElement.clientWidth)) {\n placement = 'top';\n }\n }\n return placement;\n }\n\n /**\n * Recaculate where the backdrop and its cut-out should be.\n *\n * This is needed when highlighted elements are off the page.\n * This can be called on update to recalculate it all.\n *\n * @method recalculateBackdropPosition\n * @param {Object} stepConfig The step configuration of the step\n */\n recalculateBackdropPosition(stepConfig) {\n if (stepConfig.backdrop) {\n this.positionBackdrop(stepConfig);\n }\n }\n\n /**\n * Add the backdrop.\n *\n * @method positionBackdrop\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n * @return {Object} this.\n */\n positionBackdrop(stepConfig) {\n if (stepConfig.backdrop) {\n this.currentStepConfig.hasBackdrop = true;\n\n // Position our backdrop above everything else.\n let backdrop = $('div[data-flexitour=\"backdrop\"]');\n if (!backdrop.length) {\n backdrop = $('
');\n $('body').append(backdrop);\n }\n\n if (this.isStepActuallyVisible(stepConfig)) {\n let targetNode = this.getStepTarget(stepConfig);\n targetNode.attr('data-flexitour', 'highlight');\n\n let distanceFromTop = targetNode[0].getBoundingClientRect().top;\n let relativeTop = targetNode.offset().top - distanceFromTop;\n\n /*\n Draw a clip-path that makes the backdrop a window.\n The clip-path is drawn with x/y coordinates in the following sequence.\n\n 1--------------------------------------------------2\n 11 |\n | |\n | 8-----------------------------7 |\n | | | |\n | | | |\n | | | |\n 10-------9 | |\n 5--------------------------------------6 |\n | |\n | |\n 4--------------------------------------------------3\n */\n\n // These values will help us draw the backdrop.\n const viewportHeight = $(window).height();\n const viewportWidth = $(window).width();\n const elementWidth = targetNode.outerWidth() + (BUFFER * 2);\n let elementHeight = targetNode.outerHeight() + (BUFFER * 2);\n const elementLeft = targetNode.offset().left - BUFFER;\n let elementTop = targetNode.offset().top - BUFFER - relativeTop;\n\n // Check the amount of navbar overlap the highlight element has.\n // We will adjust the backdrop shape to compensate for the fixed navbar.\n let navbarOverlap = 0;\n if (targetNode.parents('[data-usertour=\"scroller\"]').length) {\n // Determine the navbar height.\n const scrollerElement = targetNode.parents('[data-usertour=\"scroller\"]');\n const navbarHeight = scrollerElement.offset().top;\n navbarOverlap = Math.max(Math.ceil(navbarHeight - elementTop), 0);\n elementTop = elementTop + navbarOverlap;\n elementHeight = elementHeight - navbarOverlap;\n }\n\n // Check if the step container is in the 'top' position.\n // We will re-anchor the step container to the shifted backdrop edge as opposed to the actual element.\n if (this.currentStepNode && this.currentStepNode.length) {\n const xPlacement = this.currentStepNode[0].getAttribute('x-placement');\n if (xPlacement === 'top-start') {\n this.currentStepNode[0].style.top = `${navbarOverlap}px`;\n } else {\n this.currentStepNode[0].style.top = '0px';\n }\n }\n\n let backdropPath = document.querySelector('div[data-flexitour=\"backdrop\"]');\n const radius = 10;\n\n const bottomRight = {\n 'x1': elementLeft + elementWidth - radius,\n 'y1': elementTop + elementHeight,\n 'x2': elementLeft + elementWidth,\n 'y2': elementTop + elementHeight - radius,\n };\n\n const topRight = {\n 'x1': elementLeft + elementWidth,\n 'y1': elementTop + radius,\n 'x2': elementLeft + elementWidth - radius,\n 'y2': elementTop,\n };\n\n const topLeft = {\n 'x1': elementLeft + radius,\n 'y1': elementTop,\n 'x2': elementLeft,\n 'y2': elementTop + radius,\n };\n\n const bottomLeft = {\n 'x1': elementLeft,\n 'y1': elementTop + elementHeight - radius,\n 'x2': elementLeft + radius,\n 'y2': elementTop + elementHeight,\n };\n\n // L = line.\n // C = Bezier curve.\n // Z = Close path.\n backdropPath.style.clipPath = `path('M 0 0 \\\n L ${viewportWidth} 0 \\\n L ${viewportWidth} ${viewportHeight} \\\n L 0 ${viewportHeight} \\\n L 0 ${elementTop + elementHeight} \\\n L ${bottomRight.x1} ${bottomRight.y1} \\\n C ${bottomRight.x1} ${bottomRight.y1} ${bottomRight.x2} ${bottomRight.y1} ${bottomRight.x2} ${bottomRight.y2} \\\n L ${topRight.x1} ${topRight.y1} \\\n C ${topRight.x1} ${topRight.y1} ${topRight.x1} ${topRight.y2} ${topRight.x2} ${topRight.y2} \\\n L ${topLeft.x1} ${topLeft.y1} \\\n C ${topLeft.x1} ${topLeft.y1} ${topLeft.x2} ${topLeft.y1} ${topLeft.x2} ${topLeft.y2} \\\n L ${bottomLeft.x1} ${bottomLeft.y1} \\\n C ${bottomLeft.x1} ${bottomLeft.y1} ${bottomLeft.x1} ${bottomLeft.y2} ${bottomLeft.x2} ${bottomLeft.y2} \\\n L 0 ${elementTop + elementHeight} \\\n Z'\n )`;\n }\n }\n return this;\n }\n\n /**\n * Calculate the inheritted position.\n *\n * @method calculatePosition\n * @param {jQuery} elem The element to calculate position for\n * @return {String} Calculated position\n */\n calculatePosition(elem) {\n elem = $(elem);\n while (elem.length && elem[0] !== document) {\n let position = elem.css('position');\n if (position !== 'static') {\n return position;\n }\n elem = elem.parent();\n }\n\n return null;\n }\n\n /**\n * Perform accessibility changes for step shown.\n *\n * This will add aria-hidden=\"true\" to all siblings and parent siblings.\n *\n * @method accessibilityShow\n */\n accessibilityShow() {\n let stateHolder = 'data-has-hidden';\n let attrName = 'aria-hidden';\n let hideFunction = function(child) {\n let flexitourRole = child.data('flexitour');\n if (flexitourRole) {\n switch (flexitourRole) {\n case 'container':\n case 'target':\n return;\n }\n }\n\n let hidden = child.attr(attrName);\n if (!hidden) {\n child.attr(stateHolder, true);\n Aria.hide(child);\n }\n };\n\n this.currentStepNode.siblings().each(function(index, node) {\n hideFunction($(node));\n });\n this.currentStepNode.parentsUntil('body').siblings().each(function(index, node) {\n hideFunction($(node));\n });\n }\n\n /**\n * Perform accessibility changes for step hidden.\n *\n * This will remove any newly added aria-hidden=\"true\".\n *\n * @method accessibilityHide\n */\n accessibilityHide() {\n let stateHolder = 'data-has-hidden';\n let showFunction = function(child) {\n let hidden = child.attr(stateHolder);\n if (typeof hidden !== 'undefined') {\n child.removeAttr(stateHolder);\n Aria.unhide(child);\n }\n };\n\n $('[' + stateHolder + ']').each(function(index, node) {\n showFunction($(node));\n });\n }\n};\n\nexport default Tour;\n"],"names":["constructor","config","targetNode","currentElement","window","getComputedStyle","position","parentElement","init","eventHandlers","reset","originalConfiguration","configure","apply","this","arguments","possitionNeedToBeRecalculated","recalculatedNo","storage","sessionStorage","storageKey","tourName","e","hide","resetStepListeners","steps","currentStepNumber","eventName","forEach","handler","addEventHandler","resetStepDefaults","template","templateContent","checkMinimumRequirements","Error","length","loadOriginalConfiguration","stepDefaults","setStepDefaults","extend","element","placement","delay","moveOnClick","moveAfterTime","orphan","direction","getCurrentStepNumber","parseInt","setCurrentStepNumber","stepNumber","setItem","code","DOMException","QUOTA_EXCEEDED_ERR","removeItem","getNextStepNumber","nextStepNumber","isStepPotentiallyVisible","getStepConfig","getPreviousStepNumber","previousStepNumber","isLastStep","stepConfig","isStepActuallyVisible","getPotentiallyVisibleSteps","result","stepId","stepid","isCSSAllowed","target","getStepTarget","is","testCSSElement","document","createElement","classList","add","body","appendChild","isAllowed","display","remove","next","gotoStep","previous","endTour","_gotoStep","pendingPromise","PendingPromise","delayed","setTimeout","resolve","fn","dispatchEvent","eventTypes","stepRender","defaultPrevented","renderStep","stepRendered","normalizeStepConfig","$","reflex","moveAfterClick","content","attachTo","attachPoint","first","detail","cancelable","tour","push","processStepListeners","listeners","node","currentStepNode","args","proxy","handleKeyDown","parents","listener","on","off","currentStepConfig","getTemplateContent","find","html","title","nextBtn","endBtn","removeClass","addClass","prop","then","value","catch","attr","displaystepnumbers","stepsPotentiallyVisible","totalStepsPotentiallyVisible","total","addStepToPage","clone","animationTarget","stop","data","append","css","top","left","animate","scrollTop","calculateScrollTop","promise","positionBackdrop","positionStep","revealStep","bind","isOrphan","currentStepPopper","Popper","removeOnDestroy","arrowElement","modifiers","enabled","applyStyle","onLoad","onCreate","images","calculateStepPositionInPage","fadeIn","announceStep","focus","bodyRegion","headerRegion","accessibilityShow","tabbableSelector","keyCode","hasBackdrop","currentIndex","nextIndex","nextNode","focusRelevant","activeElement","stepTarget","tabbableNodes","dialogContainer","filter","index","has","each","shiftKey","closest","last","preventDefault","call","startTour","startAt","storageStartValue","getItem","storageStartAt","tourStart","tourRunning","tourStarted","restartTour","tourEnd","previousTarget","tourEnded","transition","stepHide","destroy","removeAttr","backdrop","backdropRemovalPromise","fadeOut","currentStepElement","accessibilityHide","stepHidden","show","getStepContainer","viewportHeight","height","scrollParent","hasFixedPosition","offset","Math","max","min","ceil","stepHeight","viewportWidth","width","stepWidth","MINSPACING","maxHeight","outerHeight","flipBehavior","thisT","recalculatePlacement","flip","behaviour","arrow","recalculateArrowPosition","recalculateStepPosition","onUpdate","recalculateBackdropPosition","split","isVertical","indexOf","instance","popper","querySelector","stepElement","arrowHeight","parseFloat","arrowOffset","popperHeight","popperOffset","popperBorderWidth","popperBorderRadiusWidth","arrowPos","maxPos","minPos","newArrowPos","arrowWidth","popperWidth","popperElement","targetElement","reference","targetHeight","outerWidth","targetWidth","options","leftSpace","rightSpace","remainingSpace","maxWidth","topSpace","bottomSpace","currentStepBody","headerEle","footerEle","update","background","widthContent","targetOffsetLeft","targetOffsetRight","documentElement","clientWidth","distanceFromTop","getBoundingClientRect","relativeTop","elementWidth","BUFFER","elementHeight","elementLeft","elementTop","navbarOverlap","navbarHeight","xPlacement","getAttribute","style","radius","bottomRight","topRight","topLeft","bottomLeft","clipPath","x1","y1","x2","y2","calculatePosition","elem","parent","hideFunction","child","flexitourRole","Aria","siblings","parentsUntil","unhide"],"mappings":"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"} \ No newline at end of file diff --git a/public/admin/tool/usertours/amd/src/tour.js b/public/admin/tool/usertours/amd/src/tour.js index 2bee5296661..5a3abbb377d 100644 --- a/public/admin/tool/usertours/amd/src/tour.js +++ b/public/admin/tool/usertours/amd/src/tour.js @@ -808,9 +808,6 @@ const Tour = class { targetNode.data('flexitour', 'target'); - // Add the backdrop. - this.positionBackdrop(stepConfig); - $(document.body).append(currentStepNode); this.currentStepNode = currentStepNode; @@ -826,6 +823,7 @@ const Tour = class { .animate({ scrollTop: this.calculateScrollTop(stepConfig), }).promise().then(function() { + this.positionBackdrop(stepConfig); this.positionStep(stepConfig); this.revealStep(stepConfig); pendingPromise.resolve();