diff --git a/.eslintignore b/.eslintignore index 43118690567..e6454729c3f 100644 --- a/.eslintignore +++ b/.eslintignore @@ -4,7 +4,6 @@ node_modules/ vendor/ admin/tool/policy/amd/src/jquery-eu-cookie-law-popup.js -admin/tool/usertours/amd/src/tour.js auth/cas/CAS/ cache/stores/mongodb/MongoDB/ enrol/lti/ims-blti/ diff --git a/.stylelintignore b/.stylelintignore index 218b9654a64..e0b754edefe 100644 --- a/.stylelintignore +++ b/.stylelintignore @@ -5,7 +5,6 @@ theme/classic/style/moodle.css node_modules/ vendor/ admin/tool/policy/amd/src/jquery-eu-cookie-law-popup.js -admin/tool/usertours/amd/src/tour.js auth/cas/CAS/ cache/stores/mongodb/MongoDB/ enrol/lti/ims-blti/ diff --git a/admin/tool/usertours/amd/build/tour.min.js b/admin/tool/usertours/amd/build/tour.min.js index 5f967551a1c..dcf72ce4e98 100644 --- a/admin/tool/usertours/amd/build/tour.min.js +++ b/admin/tool/usertours/amd/build/tour.min.js @@ -1,2 +1,2 @@ -function _typeof2(a){if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof2=function(a){return typeof a}}else{_typeof2=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof2(a)}(function(a,b){if("function"==typeof define&&define.amd){define ("tool_usertours/tour",["jquery","core/popper"],function(c,d){return a.Tour=b(c,d)})}else if("object"===("undefined"==typeof module?"undefined":_typeof2(module))&&module.exports){module.exports=b(require("jquery"),require("popper.js"))}else{a.Tour=b(a.$,a.Popper)}})(this,function(a,b){"use strict";var d="function"==typeof Symbol&&"symbol"===_typeof2(Symbol.iterator)?function(a){return _typeof2(a)}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":_typeof2(a)};function c(a){this.init(a)}c.prototype.tourName;c.prototype.storageKey;c.prototype.storage;c.prototype.originalConfiguration;c.prototype.listeners;c.prototype.eventHandlers;c.prototype.steps;c.prototype.currentStepNode;c.prototype.currentStepNumber;c.prototype.currentStepPopper;c.prototype.currentStepConfig;c.prototype.templateContent;c.prototype.init=function(a){this.eventHandlers={};this.reset();this.originalConfiguration=a||{};this.configure.apply(this,arguments);try{this.storage=window.sessionStorage;this.storageKey="tourstate_"+this.tourName}catch(a){this.storage=!1;this.storageKey=""}return this};c.prototype.reset=function(){this.hide();this.eventHandlers=[];this.resetStepListeners();this.originalConfiguration={};this.steps=[];this.currentStepNumber=0;return this};c.prototype.configure=function(a){var b=this;if("object"===("undefined"==typeof a?"undefined":d(a))){if("undefined"!=typeof a.tourName){this.tourName=a.tourName}if(a.eventHandlers){(function(){for(var c in a.eventHandlers){a.eventHandlers[c].forEach(function(a){this.addEventHandler(c,a)},b)}})()}this.resetStepDefaults(!0);if("object"===d(a.steps)){this.steps=a.steps}if("undefined"!=typeof a.template){this.templateContent=a.template}}this.checkMinimumRequirements();return this};c.prototype.checkMinimumRequirements=function(){if(!this.tourName){throw new Error("Tour Name required")}if(!this.steps||!this.steps.length){throw new Error("Steps must be specified")}};c.prototype.resetStepDefaults=function(a){if("undefined"==typeof a){a=!0}this.stepDefaults={};if(!a||"undefined"==typeof this.originalConfiguration.stepDefaults){this.setStepDefaults({})}else{this.setStepDefaults(this.originalConfiguration.stepDefaults)}return this};c.prototype.setStepDefaults=function(b){if(!this.stepDefaults){this.stepDefaults={}}a.extend(this.stepDefaults,{element:"",placement:"top",delay:0,moveOnClick:!1,moveAfterTime:0,orphan:!1,direction:1},b);return this};c.prototype.getCurrentStepNumber=function(){return parseInt(this.currentStepNumber,10)};c.prototype.setCurrentStepNumber=function(a){this.currentStepNumber=a;if(this.storage){try{this.storage.setItem(this.storageKey,a)}catch(a){if(a.code===DOMException.QUOTA_EXCEEDED_ERR){this.storage.removeItem(this.storageKey)}}}};c.prototype.getNextStepNumber=function(a){if("undefined"==typeof a){a=this.getCurrentStepNumber()}var b=a+1;while(b<=this.steps.length){if(this.isStepPotentiallyVisible(this.getStepConfig(b))){return b}b++}return null};c.prototype.getPreviousStepNumber=function(a){if("undefined"==typeof a){a=this.getCurrentStepNumber()}var b=a-1;while(0<=b){if(this.isStepPotentiallyVisible(this.getStepConfig(b))){return b}b--}return null};c.prototype.isLastStep=function(a){var b=this.getNextStepNumber(a);return null===b};c.prototype.isFirstStep=function(a){var b=this.getPreviousStepNumber(a);return null===b};c.prototype.isStepPotentiallyVisible=function(a){if(!a){return!1}if(this.isStepActuallyVisible(a)){return!0}if("undefined"!=typeof a.orphan&&a.orphan){return!0}if("undefined"!=typeof a.delay&&a.delay){return!0}return!1};c.prototype.isStepActuallyVisible=function(a){if(!a){return!1}var b=this.getStepTarget(a);if(b&&b.length&&b.is(":visible")){return!!b.length}return!1};c.prototype.next=function(){return this.gotoStep(this.getNextStepNumber())};c.prototype.previous=function(){return this.gotoStep(this.getPreviousStepNumber(),-1)};c.prototype.gotoStep=function(a,b){if(0>a){return this.endTour()}var c=this.getStepConfig(a);if(null===c){return this.endTour()}return this._gotoStep(c,b)};c.prototype._gotoStep=function(a,b){if(!a){return this.endTour()}if("undefined"!=typeof a.delay&&a.delay&&!a.delayed){a.delayed=!0;window.setTimeout(this._gotoStep.bind(this),a.delay,a,b);return this}else if(!a.orphan&&!this.isStepActuallyVisible(a)){var c=-1==b?"getPreviousStepNumber":"getNextStepNumber";return this.gotoStep(this[c](a.stepNumber),b)}this.hide();this.fireEventHandlers("beforeRender",a);this.renderStep(a);this.fireEventHandlers("afterRender",a);return this};c.prototype.getStepConfig=function(b){if(null===b||0>b||b>=this.steps.length){return null}var c=this.normalizeStepConfig(this.steps[b]);c=a.extend(c,{stepNumber:b});return c};c.prototype.normalizeStepConfig=function(b){if("undefined"!=typeof b.reflex&&"undefined"==typeof b.moveAfterClick){b.moveAfterClick=b.reflex}if("undefined"!=typeof b.element&&"undefined"==typeof b.target){b.target=b.element}if("undefined"!=typeof b.content&&"undefined"==typeof b.body){b.body=b.content}b=a.extend({},this.stepDefaults,b);b=a.extend({},{attachTo:b.target,attachPoint:"after"},b);if(b.attachTo){b.attachTo=a(b.attachTo).first()}return b};c.prototype.getStepTarget=function(b){if(b.target){return a(b.target)}return null};c.prototype.fireEventHandlers=function(a,b){if("undefined"==typeof this.eventHandlers[a]){return this}this.eventHandlers[a].forEach(function(a){a.call(this,b)},this);return this};c.prototype.addEventHandler=function(a,b){if("undefined"==typeof this.eventHandlers[a]){this.eventHandlers[a]=[]}this.eventHandlers[a].push(b);return this};c.prototype.processStepListeners=function(b){this.listeners.push({node:this.currentStepNode,args:["click","[data-role=\"next\"]",a.proxy(this.next,this)]},{node:this.currentStepNode,args:["click","[data-role=\"previous\"]",a.proxy(this.previous,this)]},{node:this.currentStepNode,args:["click","[data-role=\"end\"]",a.proxy(this.endTour,this)]},{node:a("[data-flexitour=\"backdrop\"]"),args:["click",a.proxy(this.hide,this)]},{node:a("body"),args:["keydown",a.proxy(this.handleKeyDown,this)]});if(b.moveOnClick){var c=this.getStepTarget(b);this.listeners.push({node:c,args:["click",a.proxy(function(b){if(0===a(b.target).parents("[data-flexitour=\"container\"]").length){window.setTimeout(a.proxy(this.next,this),500)}},this)]})}this.listeners.forEach(function(a){a.node.on.apply(a.node,a.args)});return this};c.prototype.resetStepListeners=function(){if(this.listeners){this.listeners.forEach(function(a){a.node.off.apply(a.node,a.args)})}this.listeners=[];return this};c.prototype.renderStep=function(b){this.currentStepConfig=b;this.setCurrentStepNumber(b.stepNumber);var c=a(this.getTemplateContent());c.find("[data-placeholder=\"title\"]").html(b.title);c.find("[data-placeholder=\"body\"]").html(b.body);if(this.isFirstStep(b.stepNumber)){c.find("[data-role=\"previous\"]").prop("disabled",!0)}else{c.find("[data-role=\"previous\"]").prop("disabled",!1)}if(this.isLastStep(b.stepNumber)){c.find("[data-role=\"next\"]").prop("disabled",!0)}else{c.find("[data-role=\"next\"]").prop("disabled",!1)}c.find("[data-role=\"previous\"]").attr("role","button");c.find("[data-role=\"next\"]").attr("role","button");c.find("[data-role=\"end\"]").attr("role","button");b.template=c;this.addStepToPage(b);this.processStepListeners(b);return this};c.prototype.getTemplateContent=function(){return a(this.templateContent).clone()};c.prototype.addStepToPage=function(c){var d=c.template,e=a("").html(c.template).hide(),f=a("body, html").stop(!0,!0);if(this.isStepActuallyVisible(c)){var g=this.getStepTarget(c);g.data("flexitour","target");var h=this.calculateZIndex(g);if(h){c.zIndex=h+1}if(c.zIndex){e.css("zIndex",c.zIndex+1)}this.positionBackdrop(c);a(document.body).append(e);this.currentStepNode=e;this.currentStepNode.css({top:0,left:0});f.animate({scrollTop:this.calculateScrollTop(c)}).promise().then(function(){this.positionStep(c);this.revealStep(c)}.bind(this))}else if(c.orphan){c.isOrphan=!0;c.attachTo=a("body").first();c.attachPoint="append";this.positionBackdrop(c);e.addClass("orphan");a(document.body).append(e);this.currentStepNode=e;this.currentStepNode.offset(this.calculateStepPositionInPage());this.currentStepNode.css("position","fixed");this.currentStepPopper=new b(a("body"),this.currentStepNode[0],{removeOnDestroy:!0,placement:c.placement+"-start",arrowElement:"[data-role=\"arrow\"]",modifiers:{hide:{enabled:!1},applyStyle:{onLoad:null,enabled:!1}}});this.revealStep(c)}return this};c.prototype.revealStep=function(b){this.currentStepNode.fadeIn("",a.proxy(function(){this.announceStep(b);this.currentStepNode.focus();window.setTimeout(a.proxy(function(){if(this.currentStepNode){this.currentStepNode.focus()}},this),100)},this));return this};c.prototype.announceStep=function(a){var b="tour-step-"+this.tourName+"-"+a.stepNumber;this.currentStepNode.attr("id",b);var c=this.currentStepNode.find("[data-placeholder=\"body\"]").first();c.attr("id",b+"-body");c.attr("role","document");var d=this.currentStepNode.find("[data-placeholder=\"title\"]").first();d.attr("id",b+"-title");d.attr("aria-labelledby",b+"-body");this.currentStepNode.attr("role","dialog");this.currentStepNode.attr("tabindex",0);this.currentStepNode.attr("aria-labelledby",b+"-title");this.currentStepNode.attr("aria-describedby",b+"-body");var e=this.getStepTarget(a);if(e){if(!e.attr("tabindex")){e.attr("tabindex",0)}e.data("original-describedby",e.attr("aria-describedby")).attr("aria-describedby",b+"-body")}this.accessibilityShow(a);return this};c.prototype.handleKeyDown=function(b){switch(b.keyCode){case 27:this.endTour();break;case 9:(function(){if(!this.currentStepConfig.hasBackdrop){return}var c=a(document.activeElement),d=this.getStepTarget(this.currentStepConfig),e=a("a[href], link[href], [draggable=true], [contenteditable=true], :input:enabled, [tabindex], button:enabled"),f=a("span[data-flexitour=\"container\"]"),g=void 0;if(d){e=e.filter(function(a,b){return null!=d&&(d.has(b).length||f.has(b).length||d.is(b)||f.is(b))})}e.each(function(a,b){if(c.is(b)){g=a;return!1}});var h=void 0,i=void 0,j=void 0;if(void 0!=g){var k=1;if(b.shiftKey){k=-1}h=g;do{h+=k;i=a(e[h])}while(i.length&&i.is(":disabled")||i.is(":hidden"));if(i.length){j=i.closest(d).length;j=j||i.closest(this.currentStepNode).length}else{j=!1}}if(j){i.focus()}else{if(b.shiftKey){this.currentStepNode.find("a[href], link[href], [draggable=true], [contenteditable=true], :input:enabled, [tabindex], button:enabled").last().focus()}else{if(this.currentStepConfig.isOrphan){this.currentStepNode.focus()}else{d.focus()}}}b.preventDefault()}).call(this);break;}};c.prototype.startTour=function(a){if(this.storage&&"undefined"==typeof a){var b=this.storage.getItem(this.storageKey);if(b){var c=parseInt(b,10);if(c<=this.steps.length){a=c}}}if("undefined"==typeof a){a=this.getCurrentStepNumber()}this.fireEventHandlers("beforeStart",a);this.gotoStep(a);this.fireEventHandlers("afterStart",a);return this};c.prototype.restartTour=function(){return this.startTour(0)};c.prototype.endTour=function(){this.fireEventHandlers("beforeEnd");if(this.currentStepConfig){var a=this.getStepTarget(this.currentStepConfig);if(a){if(!a.attr("tabindex")){a.attr("tabindex","-1")}a.focus()}}this.hide(!0);this.fireEventHandlers("afterEnd");return this};c.prototype.hide=function(b){this.fireEventHandlers("beforeHide");if(this.currentStepNode&&this.currentStepNode.length){this.currentStepNode.hide();if(this.currentStepPopper){this.currentStepPopper.destroy()}}if(this.currentStepConfig){var c=this.getStepTarget(this.currentStepConfig);if(c){if(c.data("original-labelledby")){c.attr("aria-labelledby",c.data("original-labelledby"))}if(c.data("original-describedby")){c.attr("aria-describedby",c.data("original-describedby"))}if(c.data("original-tabindex")){c.attr("tabindex",c.data("tabindex"))}}this.currentStepConfig=null}var d=0;if(b){d=400}a("[data-flexitour=\"step-background\"]").remove();a("[data-flexitour=\"step-backdrop\"]").removeAttr("data-flexitour");a("[data-flexitour=\"backdrop\"]").fadeOut(d,function(){a(this).remove()});if(this.currentStepNode&&this.currentStepNode.length){var e=this.currentStepNode.attr("id");if(e){var f="[aria-describedby=\""+e+"-body\"]";a(f).removeAttr("tabindex");a(f).removeAttr("aria-describedby")}}this.resetStepListeners();this.accessibilityHide();this.fireEventHandlers("afterHide");this.currentStepNode=null;this.currentStepPopper=null;return this};c.prototype.show=function(){var a=this.getCurrentStepNumber();return this.gotoStep(a)};c.prototype.getStepContainer=function(){return a(this.currentStepNode)};c.prototype.calculateScrollTop=function(b){var c=a(window).scrollTop(),d=a(window).height(),e=this.getStepTarget(b);if("top"===b.placement){c=e.offset().top-d/2}else if("bottom"===b.placement){c=e.offset().top+e.height()-d/2}else if(e.height()<=.8*d){c=e.offset().top-(d-e.height())/2}else{c=e.offset().top-.2*d}c=Math.max(0,c);c=Math.min(a(document).height()-d,c);return Math.ceil(c)};c.prototype.calculateStepPositionInPage=function(){var b=a(window).height(),c=this.currentStepNode.height(),d=a(window).width(),e=this.currentStepNode.width();return{top:Math.ceil((b-c)/2),left:Math.ceil((d-e)/2)}};c.prototype.positionStep=function(c){var d=this.currentStepNode;if(!d||!d.length){return this}var e;switch(c.placement){case"left":e=["left","right","top","bottom"];break;case"right":e=["right","left","top","bottom"];break;case"top":e=["top","bottom","right","left"];break;case"bottom":e=["bottom","top","right","left"];break;default:e="flip";break;}var f=this.getStepTarget(c),g={placement:c.placement+"-start",removeOnDestroy:!0,modifiers:{flip:{behaviour:e},arrow:{element:"[data-role=\"arrow\"]"}},onCreate:function(a){h(a)},onUpdate:function(a){h(a)}},h=function(b){var c=b.placement.split("-")[0],d=-1!==["left","right"].indexOf(c),e=b.instance.popper.querySelector("[data-role=\"arrow\"]"),f=a(b.instance.popper.querySelector("[data-role=\"flexitour-step\"]"));if(d){var g=parseFloat(window.getComputedStyle(e).height),h=parseFloat(window.getComputedStyle(e).top),i=parseFloat(window.getComputedStyle(b.instance.popper).height),j=parseFloat(window.getComputedStyle(b.instance.popper).top),k=parseFloat(f.css("borderTopWidth")),l=2*parseFloat(f.css("borderTopLeftRadius")),m=h+g/2,n=i+j-k-l,o=j+k+l;if(m>=n||m<=o){var p=0;if(m>i/2){p=n-g}else{p=o+g}a(e).css("top",p)}}else{var q=parseFloat(window.getComputedStyle(e).width),r=parseFloat(window.getComputedStyle(e).left),s=parseFloat(window.getComputedStyle(b.instance.popper).width),t=parseFloat(window.getComputedStyle(b.instance.popper).left),u=parseFloat(f.css("borderTopWidth")),v=2*parseFloat(f.css("borderTopLeftRadius")),w=r+q/2,x=s+t-u-v,y=t+u+v;if(w>=x||w<=y){var z=0;if(w>s/2){z=x-q}else{z=y+q}a(e).css("left",z)}}},i=a("[data-flexitour=\"step-background\"]");if(i.length){f=i}this.currentStepPopper=new b(f,d[0],g);return this};c.prototype.positionBackdrop=function(b){if(b.backdrop){this.currentStepConfig.hasBackdrop=!0;var c=a("
");if(b.zIndex){if("append"===b.attachPoint){b.attachTo.append(c)}else{c.insertAfter(b.attachTo)}}else{a("body").append(c)}if(this.isStepActuallyVisible(b)){var d=a("
"),e=this.getStepTarget(b),f=10,g=e;if(f){g=a("body")}d.css({width:e.outerWidth()+f+f,height:e.outerHeight()+f+f,left:e.offset().left-f,top:e.offset().top-f,backgroundColor:this.calculateInherittedBackgroundColor(g)});if(e.offset().left").hide();a("body").append(c);var d=c.css("backgroundColor");c.remove();b=a(b);while(b.length&&b[0]!==document){var e=b.css("backgroundColor");if(e!==d){return e}b=b.parent()}return null};c.prototype.calculatePosition=function(b){b=a(b);while(b.length&&b[0]!==document){var c=b.css("position");if("static"!==c){return c}b=b.parent()}return null};c.prototype.accessibilityShow=function(){var b="aria-hidden",c=function(a){var c=a.data("flexitour");if(c){switch(c){case"container":case"target":return;}}var d=a.attr(b);if(!d){a.attr("data-has-hidden",!0);a.attr(b,!0)}};this.currentStepNode.siblings().each(function(b,d){c(a(d))});this.currentStepNode.parentsUntil("body").siblings().each(function(b,d){c(a(d))})};c.prototype.accessibilityHide=function(){var b=function(a){var b=a.attr("data-has-hidden");if("undefined"!=typeof b){a.removeAttr("data-has-hidden");a.removeAttr("aria-hidden")}};a("[data-has-hidden]").each(function(c,d){b(a(d))})};if("object"===("undefined"==typeof exports?"undefined":d(exports))){module.exports=c}return c}); +define ("tool_usertours/tour",["exports","jquery","core/popper"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;b=d(b);c=d(c);function d(a){return a&&a.__esModule?a:{default:a}}function e(a){if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){e=function(a){return typeof a}}else{e=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return e(a)}function f(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function g(a,b){for(var c=0,d;ca){return this.endTour()}var c=this.getStepConfig(a);if(null===c){return this.endTour()}return this._gotoStep(c,b)}},{key:"_gotoStep",value:function _gotoStep(a,b){if(!a){return this.endTour()}if("undefined"!=typeof a.delay&&a.delay&&!a.delayed){a.delayed=!0;window.setTimeout(this._gotoStep.bind(this),a.delay,a,b);return this}else if(!a.orphan&&!this.isStepActuallyVisible(a)){var c=-1==b?"getPreviousStepNumber":"getNextStepNumber";return this.gotoStep(this[c](a.stepNumber),b)}this.hide();this.fireEventHandlers("beforeRender",a);this.renderStep(a);this.fireEventHandlers("afterRender",a);return this}},{key:"getStepConfig",value:function getStepConfig(a){if(null===a||0>a||a>=this.steps.length){return null}var c=this.normalizeStepConfig(this.steps[a]);c=b.default.extend(c,{stepNumber:a});return c}},{key:"normalizeStepConfig",value:function normalizeStepConfig(a){if("undefined"!=typeof a.reflex&&"undefined"==typeof a.moveAfterClick){a.moveAfterClick=a.reflex}if("undefined"!=typeof a.element&&"undefined"==typeof a.target){a.target=a.element}if("undefined"!=typeof a.content&&"undefined"==typeof a.body){a.body=a.content}a=b.default.extend({},this.stepDefaults,a);a=b.default.extend({},{attachTo:a.target,attachPoint:"after"},a);if(a.attachTo){a.attachTo=(0,b.default)(a.attachTo).first()}return a}},{key:"getStepTarget",value:function getStepTarget(a){if(a.target){return(0,b.default)(a.target)}return null}},{key:"fireEventHandlers",value:function fireEventHandlers(a,b){if("undefined"==typeof this.eventHandlers[a]){return this}this.eventHandlers[a].forEach(function(a){a.call(this,b)},this);return this}},{key:"addEventHandler",value:function addEventHandler(a,b){if("undefined"==typeof this.eventHandlers[a]){this.eventHandlers[a]=[]}this.eventHandlers[a].push(b);return this}},{key:"processStepListeners",value:function processStepListeners(a){this.listeners.push({node:this.currentStepNode,args:["click","[data-role=\"next\"]",b.default.proxy(this.next,this)]},{node:this.currentStepNode,args:["click","[data-role=\"previous\"]",b.default.proxy(this.previous,this)]},{node:this.currentStepNode,args:["click","[data-role=\"end\"]",b.default.proxy(this.endTour,this)]},{node:(0,b.default)("[data-flexitour=\"backdrop\"]"),args:["click",b.default.proxy(this.hide,this)]},{node:(0,b.default)("body"),args:["keydown",b.default.proxy(this.handleKeyDown,this)]});if(a.moveOnClick){var c=this.getStepTarget(a);this.listeners.push({node:c,args:["click",b.default.proxy(function(a){if(0===(0,b.default)(a.target).parents("[data-flexitour=\"container\"]").length){window.setTimeout(b.default.proxy(this.next,this),500)}},this)]})}this.listeners.forEach(function(a){a.node.on.apply(a.node,a.args)});return this}},{key:"resetStepListeners",value:function resetStepListeners(){if(this.listeners){this.listeners.forEach(function(a){a.node.off.apply(a.node,a.args)})}this.listeners=[];return this}},{key:"renderStep",value:function renderStep(a){this.currentStepConfig=a;this.setCurrentStepNumber(a.stepNumber);var c=(0,b.default)(this.getTemplateContent());c.find("[data-placeholder=\"title\"]").html(a.title);c.find("[data-placeholder=\"body\"]").html(a.body);if(this.isFirstStep(a.stepNumber)){c.find("[data-role=\"previous\"]").prop("disabled",!0)}else{c.find("[data-role=\"previous\"]").prop("disabled",!1)}if(this.isLastStep(a.stepNumber)){c.find("[data-role=\"next\"]").prop("disabled",!0)}else{c.find("[data-role=\"next\"]").prop("disabled",!1)}c.find("[data-role=\"previous\"]").attr("role","button");c.find("[data-role=\"next\"]").attr("role","button");c.find("[data-role=\"end\"]").attr("role","button");a.template=c;this.addStepToPage(a);this.processStepListeners(a);return this}},{key:"getTemplateContent",value:function getTemplateContent(){return(0,b.default)(this.templateContent).clone()}},{key:"addStepToPage",value:function addStepToPage(a){var d=(0,b.default)("").html(a.template).hide(),e=(0,b.default)("body, html").stop(!0,!0);if(this.isStepActuallyVisible(a)){var f=this.getStepTarget(a);f.data("flexitour","target");var g=this.calculateZIndex(f);if(g){a.zIndex=g+1}if(a.zIndex){d.css("zIndex",a.zIndex+1)}this.positionBackdrop(a);(0,b.default)(document.body).append(d);this.currentStepNode=d;this.currentStepNode.css({top:0,left:0});e.animate({scrollTop:this.calculateScrollTop(a)}).promise().then(function(){this.positionStep(a);this.revealStep(a)}.bind(this)).catch(function(){})}else if(a.orphan){a.isOrphan=!0;a.attachTo=(0,b.default)("body").first();a.attachPoint="append";this.positionBackdrop(a);d.addClass("orphan");(0,b.default)(document.body).append(d);this.currentStepNode=d;this.currentStepNode.offset(this.calculateStepPositionInPage());this.currentStepNode.css("position","fixed");this.currentStepPopper=new c.default((0,b.default)("body"),this.currentStepNode[0],{removeOnDestroy:!0,placement:a.placement+"-start",arrowElement:"[data-role=\"arrow\"]",modifiers:{hide:{enabled:!1},applyStyle:{onLoad:null,enabled:!1}}});this.revealStep(a)}return this}},{key:"revealStep",value:function revealStep(a){this.currentStepNode.fadeIn("",b.default.proxy(function(){this.announceStep(a);this.currentStepNode.focus();window.setTimeout(b.default.proxy(function(){if(this.currentStepNode){this.currentStepNode.focus()}},this),100)},this));return this}},{key:"announceStep",value:function announceStep(a){var b="tour-step-"+this.tourName+"-"+a.stepNumber;this.currentStepNode.attr("id",b);var c=this.currentStepNode.find("[data-placeholder=\"body\"]").first();c.attr("id",b+"-body");c.attr("role","document");var d=this.currentStepNode.find("[data-placeholder=\"title\"]").first();d.attr("id",b+"-title");d.attr("aria-labelledby",b+"-body");this.currentStepNode.attr("role","dialog");this.currentStepNode.attr("tabindex",0);this.currentStepNode.attr("aria-labelledby",b+"-title");this.currentStepNode.attr("aria-describedby",b+"-body");var e=this.getStepTarget(a);if(e){if(!e.attr("tabindex")){e.attr("tabindex",0)}e.data("original-describedby",e.attr("aria-describedby")).attr("aria-describedby",b+"-body")}this.accessibilityShow(a);return this}},{key:"handleKeyDown",value:function handleKeyDown(a){var c="a[href], link[href], [draggable=true], [contenteditable=true], ";c+=":input:enabled, [tabindex], button:enabled";switch(a.keyCode){case 27:this.endTour();break;case 9:(function(){if(!this.currentStepConfig.hasBackdrop){return}var d=(0,b.default)(document.activeElement),e=this.getStepTarget(this.currentStepConfig),f=(0,b.default)(c),g=(0,b.default)("span[data-flexitour=\"container\"]"),h;if(e){f=f.filter(function(a,b){return null!==e&&(e.has(b).length||g.has(b).length||e.is(b)||g.is(b))})}f.each(function(a,b){if(d.is(b)){h=a;return!1}return!0});var i,j,k;if(void 0!=h){var l=1;if(a.shiftKey){l=-1}i=h;do{i+=l;j=(0,b.default)(f[i])}while(j.length&&j.is(":disabled")||j.is(":hidden"));if(j.length){k=j.closest(e).length;k=k||j.closest(this.currentStepNode).length}else{k=!1}}if(k){j.focus()}else{if(a.shiftKey){this.currentStepNode.find(c).last().focus()}else{if(this.currentStepConfig.isOrphan){this.currentStepNode.focus()}else{e.focus()}}}a.preventDefault()}).call(this);break;}}},{key:"startTour",value:function startTour(a){if(this.storage&&"undefined"==typeof a){var b=this.storage.getItem(this.storageKey);if(b){var c=parseInt(b,10);if(c<=this.steps.length){a=c}}}if("undefined"==typeof a){a=this.getCurrentStepNumber()}this.fireEventHandlers("beforeStart",a);this.gotoStep(a);this.fireEventHandlers("afterStart",a);return this}},{key:"restartTour",value:function restartTour(){return this.startTour(0)}},{key:"endTour",value:function endTour(){this.fireEventHandlers("beforeEnd");if(this.currentStepConfig){var a=this.getStepTarget(this.currentStepConfig);if(a){if(!a.attr("tabindex")){a.attr("tabindex","-1")}a.focus()}}this.hide(!0);this.fireEventHandlers("afterEnd");return this}},{key:"hide",value:function hide(a){this.fireEventHandlers("beforeHide");if(this.currentStepNode&&this.currentStepNode.length){this.currentStepNode.hide();if(this.currentStepPopper){this.currentStepPopper.destroy()}}if(this.currentStepConfig){var d=this.getStepTarget(this.currentStepConfig);if(d){if(d.data("original-labelledby")){d.attr("aria-labelledby",d.data("original-labelledby"))}if(d.data("original-describedby")){d.attr("aria-describedby",d.data("original-describedby"))}if(d.data("original-tabindex")){d.attr("tabindex",d.data("tabindex"))}}this.currentStepConfig=null}var c=0;if(a){c=400}(0,b.default)("[data-flexitour=\"step-background\"]").remove();(0,b.default)("[data-flexitour=\"step-backdrop\"]").removeAttr("data-flexitour");(0,b.default)("[data-flexitour=\"backdrop\"]").fadeOut(c,function(){(0,b.default)(this).remove()});if(this.currentStepNode&&this.currentStepNode.length){var e=this.currentStepNode.attr("id");if(e){var f="[aria-describedby=\""+e+"-body\"]";(0,b.default)(f).removeAttr("tabindex");(0,b.default)(f).removeAttr("aria-describedby")}}this.resetStepListeners();this.accessibilityHide();this.fireEventHandlers("afterHide");this.currentStepNode=null;this.currentStepPopper=null;return this}},{key:"show",value:function show(){var a=this.getCurrentStepNumber();return this.gotoStep(a)}},{key:"getStepContainer",value:function getStepContainer(){return(0,b.default)(this.currentStepNode)}},{key:"calculateScrollTop",value:function calculateScrollTop(a){var c=(0,b.default)(window).scrollTop(),d=(0,b.default)(window).height(),e=this.getStepTarget(a);if("top"===a.placement){c=e.offset().top-d/2}else if("bottom"===a.placement){c=e.offset().top+e.height()-d/2}else if(e.height()<=.8*d){c=e.offset().top-(d-e.height())/2}else{c=e.offset().top-.2*d}c=Math.max(0,c);c=Math.min((0,b.default)(document).height()-d,c);return Math.ceil(c)}},{key:"calculateStepPositionInPage",value:function calculateStepPositionInPage(){var a=(0,b.default)(window).height(),c=this.currentStepNode.height(),d=(0,b.default)(window).width(),e=this.currentStepNode.width();return{top:Math.ceil((a-c)/2),left:Math.ceil((d-e)/2)}}},{key:"positionStep",value:function positionStep(a){var d=this.currentStepNode;if(!d||!d.length){return this}var e;switch(a.placement){case"left":e=["left","right","top","bottom"];break;case"right":e=["right","left","top","bottom"];break;case"top":e=["top","bottom","right","left"];break;case"bottom":e=["bottom","top","right","left"];break;default:e="flip";break;}var f=this.getStepTarget(a),g={placement:a.placement+"-start",removeOnDestroy:!0,modifiers:{flip:{behaviour:e},arrow:{element:"[data-role=\"arrow\"]"}},onCreate:function onCreate(a){h(a)},onUpdate:function onUpdate(a){h(a)}},h=function(a){var c=a.placement.split("-")[0],d=-1!==["left","right"].indexOf(c),e=a.instance.popper.querySelector("[data-role=\"arrow\"]"),f=(0,b.default)(a.instance.popper.querySelector("[data-role=\"flexitour-step\"]"));if(d){var g=parseFloat(window.getComputedStyle(e).height),h=parseFloat(window.getComputedStyle(e).top),i=parseFloat(window.getComputedStyle(a.instance.popper).height),j=parseFloat(window.getComputedStyle(a.instance.popper).top),k=parseFloat(f.css("borderTopWidth")),l=2*parseFloat(f.css("borderTopLeftRadius")),m=h+g/2,n=i+j-k-l,o=j+k+l;if(m>=n||m<=o){var y=0;if(m>i/2){y=n-g}else{y=o+g}(0,b.default)(e).css("top",y)}}else{var p=parseFloat(window.getComputedStyle(e).width),q=parseFloat(window.getComputedStyle(e).left),r=parseFloat(window.getComputedStyle(a.instance.popper).width),s=parseFloat(window.getComputedStyle(a.instance.popper).left),t=parseFloat(f.css("borderTopWidth")),u=2*parseFloat(f.css("borderTopLeftRadius")),v=q+p/2,w=r+s-t-u,x=s+t+u;if(v>=w||v<=x){var z=0;if(v>r/2){z=w-p}else{z=x+p}(0,b.default)(e).css("left",z)}}},i=(0,b.default)("[data-flexitour=\"step-background\"]");if(i.length){f=i}this.currentStepPopper=new c.default(f,d[0],g);return this}},{key:"positionBackdrop",value:function positionBackdrop(a){if(a.backdrop){this.currentStepConfig.hasBackdrop=!0;var g=(0,b.default)("
");if(a.zIndex){if("append"===a.attachPoint){a.attachTo.append(g)}else{g.insertAfter(a.attachTo)}}else{(0,b.default)("body").append(g)}if(this.isStepActuallyVisible(a)){var c=(0,b.default)("
"),d=this.getStepTarget(a),e=10,f=d;if(e){f=(0,b.default)("body")}c.css({width:d.outerWidth()+e+e,height:d.outerHeight()+e+e,left:d.offset().left-e,top:d.offset().top-e,backgroundColor:this.calculateInherittedBackgroundColor(f)});if(d.offset().left").hide();(0,b.default)("body").append(c);var d=c.css("backgroundColor");c.remove();a=(0,b.default)(a);while(a.length&&a[0]!==document){var e=a.css("backgroundColor");if(e!==d){return e}a=a.parent()}return null}},{key:"calculatePosition",value:function calculatePosition(a){a=(0,b.default)(a);while(a.length&&a[0]!==document){var c=a.css("position");if("static"!==c){return c}a=a.parent()}return null}},{key:"accessibilityShow",value:function accessibilityShow(){var a="aria-hidden",c=function(b){var c=b.data("flexitour");if(c){switch(c){case"container":case"target":return;}}var d=b.attr(a);if(!d){b.attr("data-has-hidden",!0);b.attr(a,!0)}};this.currentStepNode.siblings().each(function(a,d){c((0,b.default)(d))});this.currentStepNode.parentsUntil("body").siblings().each(function(a,d){c((0,b.default)(d))})}},{key:"accessibilityHide",value:function accessibilityHide(){var a=function(a){var b=a.attr("data-has-hidden");if("undefined"!=typeof b){a.removeAttr("data-has-hidden");a.removeAttr("aria-hidden")}};(0,b.default)("[data-has-hidden]").each(function(c,d){a((0,b.default)(d))})}}]);return a}();a.default=i;return a.default}); //# sourceMappingURL=tour.min.js.map diff --git a/admin/tool/usertours/amd/build/tour.min.js.map b/admin/tool/usertours/amd/build/tour.min.js.map index 1ff8ed8f908..9ebad305b36 100644 --- a/admin/tool/usertours/amd/build/tour.min.js.map +++ b/admin/tool/usertours/amd/build/tour.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/tour.js"],"names":["root","factory","define","amd","a0","b1","module","exports","require","$","Popper","_typeof","Symbol","iterator","obj","constructor","prototype","Tour","config","init","tourName","storageKey","storage","originalConfiguration","listeners","eventHandlers","steps","currentStepNode","currentStepNumber","currentStepPopper","currentStepConfig","templateContent","reset","configure","apply","arguments","window","sessionStorage","e","hide","resetStepListeners","_this","eventName","forEach","handler","addEventHandler","resetStepDefaults","template","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","isFirstStep","stepConfig","isStepActuallyVisible","target","getStepTarget","is","next","gotoStep","previous","endTour","_gotoStep","delayed","setTimeout","bind","fn","fireEventHandlers","renderStep","normalizeStepConfig","reflex","moveAfterClick","content","body","attachTo","attachPoint","first","data","thisEvent","call","push","processStepListeners","node","args","proxy","handleKeyDown","targetNode","parents","listener","on","off","getTemplateContent","find","html","title","prop","attr","addStepToPage","clone","stepContent","animationTarget","stop","zIndex","calculateZIndex","css","positionBackdrop","document","append","top","left","animate","scrollTop","calculateScrollTop","promise","then","positionStep","revealStep","isOrphan","addClass","offset","calculateStepPositionInPage","removeOnDestroy","arrowElement","modifiers","enabled","applyStyle","onLoad","fadeIn","announceStep","focus","stepId","bodyRegion","headerRegion","accessibilityShow","keyCode","hasBackdrop","activeElement","stepTarget","tabbableNodes","dialogContainer","currentIndex","filter","index","has","each","nextIndex","nextNode","focusRelevant","shiftKey","closest","last","preventDefault","startTour","startAt","storageStartValue","getItem","storageStartAt","restartTour","previousTarget","transition","destroy","fadeTime","remove","removeAttr","fadeOut","currentStepElement","accessibilityHide","show","getStepContainer","viewportHeight","height","Math","max","min","ceil","stepHeight","viewportWidth","width","stepWidth","flipBehavior","flip","behaviour","arrow","onCreate","recalculateArrowPosition","onUpdate","split","isVertical","indexOf","instance","popper","querySelector","stepElement","arrowHeight","parseFloat","getComputedStyle","arrowOffset","popperHeight","popperOffset","popperBorderWidth","popperBorderRadiusWidth","arrowPos","maxPos","minPos","newArrowPos","arrowWidth","_arrowOffset","popperWidth","_popperOffset","_popperBorderWidth","_popperBorderRadiusWidth","_arrowPos","_maxPos","_minPos","_newArrowPos","background","backdrop","insertAfter","buffer","colorNode","outerWidth","outerHeight","backgroundColor","calculateInherittedBackgroundColor","targetRadius","targetPosition","calculatePosition","fader","opacity","elem","position","value","isNaN","parent","fakeNode","fakeElemColor","color","attrName","hideFunction","child","flexitourRole","hidden","siblings","parentsUntil","showFunction"],"mappings":"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","sourcesContent":["// jshint ignore: start\n(function (root, factory) {\n if (typeof define === 'function' && define.amd) {\n // AMD. Register as an anonymous module unless amdModuleId is set\n define([\"jquery\",\"core/popper\"], function (a0,b1) {\n return (root['Tour'] = factory(a0,b1));\n });\n } else if (typeof module === 'object' && module.exports) {\n // Node. Does not work with strict CommonJS, but\n // only CommonJS-like environments that support module.exports,\n // like Node.\n module.exports = factory(require(\"jquery\"),require(\"popper.js\"));\n } else {\n root['Tour'] = factory(root[\"$\"],root[\"Popper\"]);\n }\n}(this, function ($, Popper) {\n\n\"use strict\";\n\n/**\n * A Tour.\n *\n * @class Tour\n * @param {object} config The configuration object.\n */\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\nfunction Tour(config) {\n this.init(config);\n}\n\n/**\n * The name of the tour.\n *\n * @property {String} tourName\n */\nTour.prototype.tourName;\n\n/**\n * The name of the tour storage key.\n *\n * @property {String} storageKey\n */\nTour.prototype.storageKey;\n\n/**\n * The session storage object\n *\n * @property {Storage} storage\n */\nTour.prototype.storage;\n\n/**\n * The original configuration as passed into the constructor.\n *\n * @property {Object} originalConfiguration\n */\nTour.prototype.originalConfiguration;\n\n/**\n * The list of step listeners.\n *\n * @property {Array} listeners\n */\nTour.prototype.listeners;\n\n/**\n * The list of event handlers.\n *\n * @property {Object} eventHandlers\n */\nTour.prototype.eventHandlers;\n\n/**\n * The list of steps.\n *\n * @property {Object[]} steps\n */\nTour.prototype.steps;\n\n/**\n * The current step node.\n *\n * @property {jQuery} currentStepNode\n */\nTour.prototype.currentStepNode;\n\n/**\n * The current step number.\n *\n * @property {Number} currentStepNumber\n */\nTour.prototype.currentStepNumber;\n\n/**\n * The popper for the current step.\n *\n * @property {Popper} currentStepPopper\n */\nTour.prototype.currentStepPopper;\n\n/**\n * The config for the current step.\n *\n * @property {Object} currentStepConfig\n */\nTour.prototype.currentStepConfig;\n\n/**\n * The template content.\n *\n * @property {String} templateContent\n */\nTour.prototype.templateContent;\n\n/**\n * Initialise the tour.\n *\n * @method init\n * @param {Object} config The configuration object.\n * @chainable\n */\nTour.prototype.init = function (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 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 return this;\n};\n\n/**\n * Reset the current tour state.\n *\n * @method reset\n * @chainable\n */\nTour.prototype.reset = function () {\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 * @chainable\n */\nTour.prototype.configure = function (config) {\n var _this = this;\n\n if ((typeof config === 'undefined' ? 'undefined' : _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 (function () {\n var eventName = void 0;\n for (eventName in config.eventHandlers) {\n config.eventHandlers[eventName].forEach(function (handler) {\n this.addEventHandler(eventName, handler);\n }, _this);\n }\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 * @chainable\n */\nTour.prototype.checkMinimumRequirements = function () {\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 */\nTour.prototype.resetStepDefaults = function (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 */\nTour.prototype.setStepDefaults = function (stepDefaults) {\n if (!this.stepDefaults) {\n this.stepDefaults = {};\n }\n $.extend(this.stepDefaults, {\n element: '',\n placement: 'top',\n delay: 0,\n moveOnClick: false,\n moveAfterTime: 0,\n orphan: false,\n direction: 1\n }, stepDefaults);\n\n return this;\n};\n\n/**\n * Retrieve the current step number.\n *\n * @method getCurrentStepNumber\n * @return {Integer} The current step number\n */\nTour.prototype.getCurrentStepNumber = function () {\n return parseInt(this.currentStepNumber, 10);\n};\n\n/**\n * Store the current step number.\n *\n * @method setCurrentStepNumber\n * @param {Integer} stepNumber The current step number\n * @chainable\n */\nTour.prototype.setCurrentStepNumber = function (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 * @return {Integer} The next step number to display\n */\nTour.prototype.getNextStepNumber = function (stepNumber) {\n if (typeof stepNumber === 'undefined') {\n stepNumber = this.getCurrentStepNumber();\n }\n var 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 * @return {Integer} The previous step number to display\n */\nTour.prototype.getPreviousStepNumber = function (stepNumber) {\n if (typeof stepNumber === 'undefined') {\n stepNumber = this.getCurrentStepNumber();\n }\n var 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 {Integer} stepNumber Step number to test\n * @return {Boolean} Whether the step is the final step\n */\nTour.prototype.isLastStep = function (stepNumber) {\n var nextStepNumber = this.getNextStepNumber(stepNumber);\n\n return nextStepNumber === null;\n};\n\n/**\n * Is the step the first step number?\n *\n * @method isFirstStep\n * @param {Integer} stepNumber Step number to test\n * @return {Boolean} Whether the step is the first step\n */\nTour.prototype.isFirstStep = function (stepNumber) {\n var previousStepNumber = this.getPreviousStepNumber(stepNumber);\n\n return previousStepNumber === null;\n};\n\n/**\n * Is this step potentially visible?\n *\n * @method isStepPotentiallyVisible\n * @param {Integer} stepNumber Step number to test\n * @return {Boolean} Whether the step is the potentially visible\n */\nTour.prototype.isStepPotentiallyVisible = function (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 * Is this step actually visible?\n *\n * @method isStepActuallyVisible\n * @param {Integer} stepNumber Step number to test\n * @return {Boolean} Whether the step is actually visible\n */\nTour.prototype.isStepActuallyVisible = function (stepConfig) {\n if (!stepConfig) {\n // Without step config, there can be no step.\n return false;\n }\n\n var 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 * Go to the next step in the tour.\n *\n * @method next\n * @chainable\n */\nTour.prototype.next = function () {\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 */\nTour.prototype.previous = function () {\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 {Integer} stepNumber The step number to display\n * @chainable\n */\nTour.prototype.gotoStep = function (stepNumber, direction) {\n if (stepNumber < 0) {\n return this.endTour();\n }\n\n var stepConfig = this.getStepConfig(stepNumber);\n if (stepConfig === null) {\n return this.endTour();\n }\n\n return this._gotoStep(stepConfig, direction);\n};\n\nTour.prototype._gotoStep = function (stepConfig, direction) {\n if (!stepConfig) {\n return this.endTour();\n }\n\n if (typeof stepConfig.delay !== 'undefined' && stepConfig.delay && !stepConfig.delayed) {\n stepConfig.delayed = true;\n window.setTimeout(this._gotoStep.bind(this), stepConfig.delay, stepConfig, direction);\n\n return this;\n } else if (!stepConfig.orphan && !this.isStepActuallyVisible(stepConfig)) {\n var fn = direction == -1 ? 'getPreviousStepNumber' : 'getNextStepNumber';\n return this.gotoStep(this[fn](stepConfig.stepNumber), direction);\n }\n\n this.hide();\n\n this.fireEventHandlers('beforeRender', stepConfig);\n this.renderStep(stepConfig);\n this.fireEventHandlers('afterRender', stepConfig);\n\n return this;\n};\n\n/**\n * Fetch the normalised step configuration for the specified step number.\n *\n * @method getStepConfig\n * @param {Integer} stepNumber The step number to fetch configuration for\n * @return {Object} The step configuration\n */\nTour.prototype.getStepConfig = function (stepNumber) {\n if (stepNumber === null || stepNumber < 0 || stepNumber >= this.steps.length) {\n return null;\n }\n\n // Normalise the step configuration.\n var 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 */\nTour.prototype.normalizeStepConfig = function (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 */\nTour.prototype.getStepTarget = function (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 to handle\n * @param {Object} data Any data to pass to the event\n * @chainable\n */\nTour.prototype.fireEventHandlers = function (eventName, data) {\n if (typeof this.eventHandlers[eventName] === 'undefined') {\n return this;\n }\n\n this.eventHandlers[eventName].forEach(function (thisEvent) {\n thisEvent.call(this, data);\n }, this);\n\n return this;\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 */\nTour.prototype.addEventHandler = function (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 */\nTour.prototype.processStepListeners = function (stepConfig) {\n this.listeners.push(\n // Next/Previous buttons.\n {\n node: this.currentStepNode,\n args: ['click', '[data-role=\"next\"]', $.proxy(this.next, this)]\n }, {\n node: this.currentStepNode,\n args: ['click', '[data-role=\"previous\"]', $.proxy(this.previous, 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 */\nTour.prototype.resetStepListeners = function () {\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 */\nTour.prototype.renderStep = function (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 var template = $(this.getTemplateContent());\n\n // Title.\n template.find('[data-placeholder=\"title\"]').html(stepConfig.title);\n\n // Body.\n template.find('[data-placeholder=\"body\"]').html(stepConfig.body);\n\n // Is this the first step?\n if (this.isFirstStep(stepConfig.stepNumber)) {\n template.find('[data-role=\"previous\"]').prop('disabled', true);\n } else {\n template.find('[data-role=\"previous\"]').prop('disabled', false);\n }\n\n // Is this the final step?\n if (this.isLastStep(stepConfig.stepNumber)) {\n template.find('[data-role=\"next\"]').prop('disabled', true);\n } else {\n template.find('[data-role=\"next\"]').prop('disabled', false);\n }\n\n template.find('[data-role=\"previous\"]').attr('role', 'button');\n template.find('[data-role=\"next\"]').attr('role', 'button');\n template.find('[data-role=\"end\"]').attr('role', 'button');\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 */\nTour.prototype.getTemplateContent = function () {\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 */\nTour.prototype.addStepToPage = function (stepConfig) {\n var stepContent = stepConfig.template;\n\n // Create the stepNode from the template data.\n var currentStepNode = $('').html(stepConfig.template).hide();\n\n // The scroll animation occurs on the body or html.\n var animationTarget = $('body, html').stop(true, true);\n\n if (this.isStepActuallyVisible(stepConfig)) {\n var targetNode = this.getStepTarget(stepConfig);\n\n targetNode.data('flexitour', 'target');\n\n var zIndex = this.calculateZIndex(targetNode);\n if (zIndex) {\n stepConfig.zIndex = zIndex + 1;\n }\n\n if (stepConfig.zIndex) {\n currentStepNode.css('zIndex', stepConfig.zIndex + 1);\n }\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 animationTarget.animate({\n scrollTop: this.calculateScrollTop(stepConfig)\n }).promise().then(function () {\n this.positionStep(stepConfig);\n this.revealStep(stepConfig);\n }.bind(this));\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.offset(this.calculateStepPositionInPage());\n this.currentStepNode.css('position', 'fixed');\n\n this.currentStepPopper = new Popper($('body'), 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 });\n\n this.revealStep(stepConfig);\n }\n\n return this;\n};\n\nTour.prototype.revealStep = function (stepConfig) {\n // Fade the step in.\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 }, this), 100);\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 */\nTour.prototype.announceStep = function (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 var stepId = 'tour-step-' + this.tourName + '-' + stepConfig.stepNumber;\n this.currentStepNode.attr('id', stepId);\n\n var bodyRegion = this.currentStepNode.find('[data-placeholder=\"body\"]').first();\n bodyRegion.attr('id', stepId + '-body');\n bodyRegion.attr('role', 'document');\n\n var 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 var target = this.getStepTarget(stepConfig);\n if (target) {\n if (!target.attr('tabindex')) {\n target.attr('tabindex', 0);\n }\n\n target.data('original-describedby', target.attr('aria-describedby')).attr('aria-describedby', stepId + '-body');\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 */\nTour.prototype.handleKeyDown = function (e) {\n var tabbableSelector = 'a[href], link[href], [draggable=true], [contenteditable=true], :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 var activeElement = $(document.activeElement);\n var stepTarget = this.getStepTarget(this.currentStepConfig);\n var tabbableNodes = $(tabbableSelector);\n var dialogContainer = $('span[data-flexitour=\"container\"]');\n var currentIndex = void 0;\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 && (stepTarget.has(element).length || dialogContainer.has(element).length || stepTarget.is(element) || 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 });\n\n var nextIndex = void 0;\n var nextNode = void 0;\n var focusRelevant = void 0;\n if (currentIndex != void 0) {\n var 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 {Integer} startAt Which step number to start at. If not specified, starts at the last point.\n * @chainable\n */\nTour.prototype.startTour = function (startAt) {\n if (this.storage && typeof startAt === 'undefined') {\n var storageStartValue = this.storage.getItem(this.storageKey);\n if (storageStartValue) {\n var 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 this.fireEventHandlers('beforeStart', startAt);\n this.gotoStep(startAt);\n this.fireEventHandlers('afterStart', startAt);\n\n return this;\n};\n\n/**\n * Restart the tour from the beginning, resetting the completionlag.\n *\n * @method restartTour\n * @chainable\n */\nTour.prototype.restartTour = function () {\n return this.startTour(0);\n};\n\n/**\n * End the current tour.\n *\n * @method endTour\n * @chainable\n */\nTour.prototype.endTour = function () {\n this.fireEventHandlers('beforeEnd');\n\n if (this.currentStepConfig) {\n var previousTarget = this.getStepTarget(this.currentStepConfig);\n if (previousTarget) {\n if (!previousTarget.attr('tabindex')) {\n previousTarget.attr('tabindex', '-1');\n }\n previousTarget.focus();\n }\n }\n\n this.hide(true);\n\n this.fireEventHandlers('afterEnd');\n\n return this;\n};\n\n/**\n * Hide any currently visible steps.\n *\n * @method hide\n * @chainable\n */\nTour.prototype.hide = function (transition) {\n this.fireEventHandlers('beforeHide');\n\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 var 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 }\n }\n\n // Clear the step configuration.\n this.currentStepConfig = null;\n }\n\n var fadeTime = 0;\n if (transition) {\n fadeTime = 400;\n }\n\n // Remove the backdrop features.\n $('[data-flexitour=\"step-background\"]').remove();\n $('[data-flexitour=\"step-backdrop\"]').removeAttr('data-flexitour');\n $('[data-flexitour=\"backdrop\"]').fadeOut(fadeTime, function () {\n $(this).remove();\n });\n\n // Remove aria-describedby and tabindex attributes.\n if (this.currentStepNode && this.currentStepNode.length) {\n var stepId = this.currentStepNode.attr('id');\n if (stepId) {\n var 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.fireEventHandlers('afterHide');\n\n this.currentStepNode = null;\n this.currentStepPopper = null;\n return this;\n};\n\n/**\n * Show the current steps.\n *\n * @method show\n * @chainable\n */\nTour.prototype.show = function () {\n // Show the current step.\n var 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 */\nTour.prototype.getStepContainer = function () {\n return $(this.currentStepNode);\n};\n\n/**\n * Calculate scrollTop.\n *\n * @method calculateScrollTop\n * @param {Object} stepConfig The step configuration of the step\n * @return {Number}\n */\nTour.prototype.calculateScrollTop = function (stepConfig) {\n var scrollTop = $(window).scrollTop();\n var viewportHeight = $(window).height();\n var targetNode = this.getStepTarget(stepConfig);\n\n 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() - 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 * @method calculateScrollTop\n * @return {Number}\n */\nTour.prototype.calculateStepPositionInPage = function () {\n var viewportHeight = $(window).height();\n var stepHeight = this.currentStepNode.height();\n\n var viewportWidth = $(window).width();\n var stepWidth = this.currentStepNode.width();\n\n return {\n top: Math.ceil((viewportHeight - stepHeight) / 2),\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 */\nTour.prototype.positionStep = function (stepConfig) {\n var content = this.currentStepNode;\n if (!content || !content.length) {\n // Unable to find the step node.\n return this;\n }\n\n var flipBehavior = void 0;\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 var 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 },\n onCreate: function onCreate(data) {\n recalculateArrowPosition(data);\n },\n onUpdate: function onUpdate(data) {\n recalculateArrowPosition(data);\n }\n };\n\n var recalculateArrowPosition = function recalculateArrowPosition(data) {\n var placement = data.placement.split('-')[0];\n var isVertical = ['left', 'right'].indexOf(placement) !== -1;\n var arrowElement = data.instance.popper.querySelector('[data-role=\"arrow\"]');\n var stepElement = $(data.instance.popper.querySelector('[data-role=\"flexitour-step\"]'));\n if (isVertical) {\n var arrowHeight = parseFloat(window.getComputedStyle(arrowElement).height);\n var arrowOffset = parseFloat(window.getComputedStyle(arrowElement).top);\n var popperHeight = parseFloat(window.getComputedStyle(data.instance.popper).height);\n var popperOffset = parseFloat(window.getComputedStyle(data.instance.popper).top);\n var popperBorderWidth = parseFloat(stepElement.css('borderTopWidth'));\n var popperBorderRadiusWidth = parseFloat(stepElement.css('borderTopLeftRadius')) * 2;\n var arrowPos = arrowOffset + arrowHeight / 2;\n var maxPos = popperHeight + popperOffset - popperBorderWidth - popperBorderRadiusWidth;\n var minPos = popperOffset + popperBorderWidth + popperBorderRadiusWidth;\n if (arrowPos >= maxPos || arrowPos <= minPos) {\n var 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 var arrowWidth = parseFloat(window.getComputedStyle(arrowElement).width);\n var _arrowOffset = parseFloat(window.getComputedStyle(arrowElement).left);\n var popperWidth = parseFloat(window.getComputedStyle(data.instance.popper).width);\n var _popperOffset = parseFloat(window.getComputedStyle(data.instance.popper).left);\n var _popperBorderWidth = parseFloat(stepElement.css('borderTopWidth'));\n var _popperBorderRadiusWidth = parseFloat(stepElement.css('borderTopLeftRadius')) * 2;\n var _arrowPos = _arrowOffset + arrowWidth / 2;\n var _maxPos = popperWidth + _popperOffset - _popperBorderWidth - _popperBorderRadiusWidth;\n var _minPos = _popperOffset + _popperBorderWidth + _popperBorderRadiusWidth;\n if (_arrowPos >= _maxPos || _arrowPos <= _minPos) {\n var _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 var background = $('[data-flexitour=\"step-background\"]');\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 * Add the backdrop.\n *\n * @method positionBackdrop\n * @param {Object} stepConfig The step configuration of the step\n * @chainable\n */\nTour.prototype.positionBackdrop = function (stepConfig) {\n if (stepConfig.backdrop) {\n this.currentStepConfig.hasBackdrop = true;\n var backdrop = $('
');\n\n if (stepConfig.zIndex) {\n if (stepConfig.attachPoint === 'append') {\n stepConfig.attachTo.append(backdrop);\n } else {\n backdrop.insertAfter(stepConfig.attachTo);\n }\n } else {\n $('body').append(backdrop);\n }\n\n if (this.isStepActuallyVisible(stepConfig)) {\n // The step has a visible target.\n // Punch a hole through the backdrop.\n var background = $('
');\n\n var targetNode = this.getStepTarget(stepConfig);\n\n var buffer = 10;\n\n var colorNode = targetNode;\n if (buffer) {\n colorNode = $('body');\n }\n\n background.css({\n width: targetNode.outerWidth() + buffer + buffer,\n height: targetNode.outerHeight() + buffer + buffer,\n left: targetNode.offset().left - buffer,\n top: targetNode.offset().top - buffer,\n backgroundColor: this.calculateInherittedBackgroundColor(colorNode)\n });\n\n if (targetNode.offset().left < buffer) {\n background.css({\n width: targetNode.outerWidth() + targetNode.offset().left + buffer,\n left: targetNode.offset().left\n });\n }\n\n if (targetNode.offset().top < buffer) {\n background.css({\n height: targetNode.outerHeight() + targetNode.offset().top + buffer,\n top: targetNode.offset().top\n });\n }\n\n var targetRadius = targetNode.css('borderRadius');\n if (targetRadius && targetRadius !== $('body').css('borderRadius')) {\n background.css('borderRadius', targetRadius);\n }\n\n var targetPosition = this.calculatePosition(targetNode);\n if (targetPosition === 'fixed') {\n background.css('top', 0);\n } else if (targetPosition === 'absolute') {\n background.css('position', 'fixed');\n }\n\n var fader = background.clone();\n fader.css({\n backgroundColor: backdrop.css('backgroundColor'),\n opacity: backdrop.css('opacity')\n });\n fader.attr('data-flexitour', 'step-background-fader');\n\n if (stepConfig.zIndex) {\n if (stepConfig.attachPoint === 'append') {\n stepConfig.attachTo.append(background);\n } else {\n fader.insertAfter(stepConfig.attachTo);\n background.insertAfter(stepConfig.attachTo);\n }\n } else {\n $('body').append(fader);\n $('body').append(background);\n }\n\n // Add the backdrop data to the actual target.\n // This is the part which actually does the work.\n targetNode.attr('data-flexitour', 'step-backdrop');\n\n if (stepConfig.zIndex) {\n backdrop.css('zIndex', stepConfig.zIndex);\n background.css('zIndex', stepConfig.zIndex + 1);\n targetNode.css('zIndex', stepConfig.zIndex + 2);\n }\n\n fader.fadeOut('2000', function () {\n $(this).remove();\n });\n }\n }\n return this;\n};\n\n/**\n * Calculate the inheritted z-index.\n *\n * @method calculateZIndex\n * @param {jQuery} elem The element to calculate z-index for\n * @return {Number} Calculated z-index\n */\nTour.prototype.calculateZIndex = function (elem) {\n elem = $(elem);\n while (elem.length && elem[0] !== document) {\n // Ignore z-index if position is set to a value where z-index is ignored by the browser\n // This makes behavior of this function consistent across browsers\n // WebKit always returns auto if the element is positioned.\n var position = elem.css(\"position\");\n if (position === \"absolute\" || position === \"relative\" || position === \"fixed\") {\n // IE returns 0 when zIndex is not specified\n // other browsers return a string\n // we ignore the case of nested elements with an explicit value of 0\n //
\n var value = parseInt(elem.css(\"zIndex\"), 10);\n if (!isNaN(value) && value !== 0) {\n return value;\n }\n }\n elem = elem.parent();\n }\n\n return 0;\n};\n\n/**\n * Calculate the inheritted background colour.\n *\n * @method calculateInherittedBackgroundColor\n * @param {jQuery} elem The element to calculate colour for\n * @return {String} Calculated background colour\n */\nTour.prototype.calculateInherittedBackgroundColor = function (elem) {\n // Use a fake node to compare each element against.\n var fakeNode = $('
').hide();\n $('body').append(fakeNode);\n var fakeElemColor = fakeNode.css('backgroundColor');\n fakeNode.remove();\n\n elem = $(elem);\n while (elem.length && elem[0] !== document) {\n var color = elem.css('backgroundColor');\n if (color !== fakeElemColor) {\n return color;\n }\n elem = elem.parent();\n }\n\n return null;\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 */\nTour.prototype.calculatePosition = function (elem) {\n elem = $(elem);\n while (elem.length && elem[0] !== document) {\n var 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 */\nTour.prototype.accessibilityShow = function () {\n var stateHolder = 'data-has-hidden';\n var attrName = 'aria-hidden';\n var hideFunction = function hideFunction(child) {\n var flexitourRole = child.data('flexitour');\n if (flexitourRole) {\n switch (flexitourRole) {\n case 'container':\n case 'target':\n return;\n }\n }\n\n var hidden = child.attr(attrName);\n if (!hidden) {\n child.attr(stateHolder, true);\n child.attr(attrName, true);\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 */\nTour.prototype.accessibilityHide = function () {\n var stateHolder = 'data-has-hidden';\n var attrName = 'aria-hidden';\n var showFunction = function showFunction(child) {\n var hidden = child.attr(stateHolder);\n if (typeof hidden !== 'undefined') {\n child.removeAttr(stateHolder);\n child.removeAttr(attrName);\n }\n };\n\n $('[' + stateHolder + ']').each(function (index, node) {\n showFunction($(node));\n });\n};\n\nif ((typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object') {\n module.exports = Tour;\n}\n\nreturn Tour;\n\n}));\n"],"file":"tour.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/tour.js"],"names":["Tour","config","init","eventHandlers","reset","originalConfiguration","configure","apply","arguments","storage","window","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","parseInt","stepNumber","setItem","code","DOMException","QUOTA_EXCEEDED_ERR","removeItem","getCurrentStepNumber","nextStepNumber","isStepPotentiallyVisible","getStepConfig","previousStepNumber","getNextStepNumber","getPreviousStepNumber","stepConfig","isStepActuallyVisible","target","getStepTarget","is","gotoStep","endTour","_gotoStep","delayed","setTimeout","bind","fn","fireEventHandlers","renderStep","normalizeStepConfig","reflex","moveAfterClick","content","body","attachTo","attachPoint","first","data","thisEvent","call","push","listeners","node","currentStepNode","args","proxy","next","previous","handleKeyDown","targetNode","parents","listener","on","off","currentStepConfig","setCurrentStepNumber","getTemplateContent","find","html","title","isFirstStep","prop","isLastStep","attr","addStepToPage","processStepListeners","clone","animationTarget","stop","zIndex","calculateZIndex","css","positionBackdrop","document","append","top","left","animate","scrollTop","calculateScrollTop","promise","then","positionStep","revealStep","catch","isOrphan","addClass","offset","calculateStepPositionInPage","currentStepPopper","Popper","removeOnDestroy","arrowElement","modifiers","enabled","applyStyle","onLoad","fadeIn","announceStep","focus","stepId","bodyRegion","headerRegion","accessibilityShow","tabbableSelector","keyCode","hasBackdrop","activeElement","stepTarget","tabbableNodes","dialogContainer","currentIndex","filter","index","has","each","nextIndex","nextNode","focusRelevant","shiftKey","closest","last","preventDefault","startAt","storageStartValue","getItem","storageStartAt","startTour","previousTarget","transition","destroy","fadeTime","remove","removeAttr","fadeOut","currentStepElement","accessibilityHide","viewportHeight","height","Math","max","min","ceil","stepHeight","viewportWidth","width","stepWidth","flipBehavior","flip","behaviour","arrow","onCreate","recalculateArrowPosition","onUpdate","split","isVertical","indexOf","instance","popper","querySelector","stepElement","arrowHeight","parseFloat","getComputedStyle","arrowOffset","popperHeight","popperOffset","popperBorderWidth","popperBorderRadiusWidth","arrowPos","maxPos","minPos","newArrowPos","arrowWidth","popperWidth","background","backdrop","insertAfter","buffer","colorNode","outerWidth","outerHeight","backgroundColor","calculateInherittedBackgroundColor","targetRadius","targetPosition","calculatePosition","fader","opacity","elem","position","value","isNaN","parent","fakeNode","fakeElemColor","color","attrName","hideFunction","child","flexitourRole","hidden","siblings","parentsUntil","showFunction"],"mappings":"gKAsBA,OACA,O,wmBAOqBA,CAAAA,C,YAIjB,WAAYC,CAAZ,CAAoB,WAChB,KAAKC,IAAL,CAAUD,CAAV,CACH,C,qCAUIA,C,CAAQ,CAET,KAAKE,aAAL,CAAqB,EAArB,CAGA,KAAKC,KAAL,GAGA,KAAKC,qBAAL,CAA6BJ,CAAM,EAAI,EAAvC,CAGA,KAAKK,SAAL,CAAeC,KAAf,CAAqB,IAArB,CAA2BC,SAA3B,EAEA,GAAI,CACA,KAAKC,OAAL,CAAeC,MAAM,CAACC,cAAtB,CACA,KAAKC,UAAL,CAAkB,aAAe,KAAKC,QACzC,CAAC,MAAOC,CAAP,CAAU,CACR,KAAKL,OAAL,IACA,KAAKG,UAAL,CAAkB,EACrB,CAED,MAAO,KACV,C,qCASO,CAEJ,KAAKG,IAAL,GAGA,KAAKZ,aAAL,CAAqB,EAArB,CAGA,KAAKa,kBAAL,GAGA,KAAKX,qBAAL,CAA6B,EAA7B,CAGA,KAAKY,KAAL,CAAa,EAAb,CAGA,KAAKC,iBAAL,CAAyB,CAAzB,CAEA,MAAO,KACV,C,4CAUSjB,C,CAAQ,YACd,GAAsB,QAAlB,KAAOA,CAAP,CAAJ,CAAgC,CAE5B,GAA+B,WAA3B,QAAOA,CAAAA,CAAM,CAACY,QAAlB,CAA4C,CACxC,KAAKA,QAAL,CAAgBZ,CAAM,CAACY,QAC1B,CAGD,GAAIZ,CAAM,CAACE,aAAX,CAA0B,gBACbgB,CADa,EAElBlB,CAAM,CAACE,aAAP,CAAqBgB,CAArB,EAAgCC,OAAhC,CAAwC,SAASC,CAAT,CAAkB,CACtD,KAAKC,eAAL,CAAqBH,CAArB,CAAgCE,CAAhC,CACH,CAFD,CAEG,CAFH,CAFkB,EACtB,IAAK,GAAIF,CAAAA,CAAT,GAAsBlB,CAAAA,CAAM,CAACE,aAA7B,CAA4C,GAAnCgB,CAAmC,CAI3C,CACJ,CAGD,KAAKI,iBAAL,KAGA,GAA4B,QAAxB,KAAOtB,CAAM,CAACgB,KAAd,CAAJ,CAAsC,CAClC,KAAKA,KAAL,CAAahB,CAAM,CAACgB,KACvB,CAED,GAA+B,WAA3B,QAAOhB,CAAAA,CAAM,CAACuB,QAAlB,CAA4C,CACxC,KAAKC,eAAL,CAAuBxB,CAAM,CAACuB,QACjC,CACJ,CAGD,KAAKE,wBAAL,GAEA,MAAO,KACV,C,2EAO0B,CAEvB,GAAI,CAAC,KAAKb,QAAV,CAAoB,CAChB,KAAM,IAAIc,CAAAA,KAAJ,CAAU,oBAAV,CACT,CAGD,GAAI,CAAC,KAAKV,KAAN,EAAe,CAAC,KAAKA,KAAL,CAAWW,MAA/B,CAAuC,CACnC,KAAM,IAAID,CAAAA,KAAJ,CAAU,yBAAV,CACT,CACJ,C,4DAUiBE,C,CAA2B,CACzC,GAAyC,WAArC,QAAOA,CAAAA,CAAX,CAAsD,CAClDA,CAAyB,GAC5B,CAED,KAAKC,YAAL,CAAoB,EAApB,CACA,GAAI,CAACD,CAAD,EAAiF,WAAnD,QAAO,MAAKxB,qBAAL,CAA2ByB,YAApE,CAAkG,CAC9F,KAAKC,eAAL,CAAqB,EAArB,CACH,CAFD,IAEO,CACH,KAAKA,eAAL,CAAqB,KAAK1B,qBAAL,CAA2ByB,YAAhD,CACH,CAED,MAAO,KACV,C,wDAUeA,C,CAAc,CAC1B,GAAI,CAAC,KAAKA,YAAV,CAAwB,CACpB,KAAKA,YAAL,CAAoB,EACvB,CACDE,UAAEC,MAAF,CACI,KAAKH,YADT,CAEI,CACII,OAAO,CAAS,EADpB,CAEIC,SAAS,CAAO,KAFpB,CAGIC,KAAK,CAAW,CAHpB,CAIIC,WAAW,GAJf,CAKIC,aAAa,CAAG,CALpB,CAMIC,MAAM,GANV,CAOIC,SAAS,CAAO,CAPpB,CAFJ,CAWIV,CAXJ,EAcA,MAAO,KACV,C,mEAQsB,CACnB,MAAOW,CAAAA,QAAQ,CAAC,KAAKvB,iBAAN,CAAyB,EAAzB,CAClB,C,kEASoBwB,C,CAAY,CAC7B,KAAKxB,iBAAL,CAAyBwB,CAAzB,CACA,GAAI,KAAKjC,OAAT,CAAkB,CACd,GAAI,CACA,KAAKA,OAAL,CAAakC,OAAb,CAAqB,KAAK/B,UAA1B,CAAsC8B,CAAtC,CACH,CAAC,MAAO5B,CAAP,CAAU,CACR,GAAIA,CAAC,CAAC8B,IAAF,GAAWC,YAAY,CAACC,kBAA5B,CAAgD,CAC5C,KAAKrC,OAAL,CAAasC,UAAb,CAAwB,KAAKnC,UAA7B,CACH,CACJ,CACJ,CACJ,C,4DASiB8B,C,CAAY,CAC1B,GAA0B,WAAtB,QAAOA,CAAAA,CAAX,CAAuC,CACnCA,CAAU,CAAG,KAAKM,oBAAL,EAChB,CACD,GAAIC,CAAAA,CAAc,CAAGP,CAAU,CAAG,CAAlC,CAGA,MAAOO,CAAc,EAAI,KAAKhC,KAAL,CAAWW,MAApC,CAA4C,CACxC,GAAI,KAAKsB,wBAAL,CAA8B,KAAKC,aAAL,CAAmBF,CAAnB,CAA9B,CAAJ,CAAuE,CACnE,MAAOA,CAAAA,CACV,CACDA,CAAc,EACjB,CAED,MAAO,KACV,C,oEASqBP,C,CAAY,CAC9B,GAA0B,WAAtB,QAAOA,CAAAA,CAAX,CAAuC,CACnCA,CAAU,CAAG,KAAKM,oBAAL,EAChB,CACD,GAAII,CAAAA,CAAkB,CAAGV,CAAU,CAAG,CAAtC,CAGA,MAA6B,CAAtB,EAAAU,CAAP,CAAgC,CAC5B,GAAI,KAAKF,wBAAL,CAA8B,KAAKC,aAAL,CAAmBC,CAAnB,CAA9B,CAAJ,CAA2E,CACvE,MAAOA,CAAAA,CACV,CACDA,CAAkB,EACrB,CAED,MAAO,KACV,C,8CASUV,C,CAAY,CACnB,GAAIO,CAAAA,CAAc,CAAG,KAAKI,iBAAL,CAAuBX,CAAvB,CAArB,CAEA,MAA0B,KAAnB,GAAAO,CACV,C,gDASWP,C,CAAY,CACpB,GAAIU,CAAAA,CAAkB,CAAG,KAAKE,qBAAL,CAA2BZ,CAA3B,CAAzB,CAEA,MAA8B,KAAvB,GAAAU,CACV,C,0EASwBG,C,CAAY,CACjC,GAAI,CAACA,CAAL,CAAiB,CAEb,QACH,CAED,GAAI,KAAKC,qBAAL,CAA2BD,CAA3B,CAAJ,CAA4C,CAExC,QACH,CAED,GAAiC,WAA7B,QAAOA,CAAAA,CAAU,CAAChB,MAAlB,EAA4CgB,CAAU,CAAChB,MAA3D,CAAmE,CAE/D,QACH,CAED,GAAgC,WAA5B,QAAOgB,CAAAA,CAAU,CAACnB,KAAlB,EAA2CmB,CAAU,CAACnB,KAA1D,CAAiE,CAE7D,QACH,CAGD,QACH,C,oEASqBmB,C,CAAY,CAC9B,GAAI,CAACA,CAAL,CAAiB,CAEb,QACH,CAED,GAAIE,CAAAA,CAAM,CAAG,KAAKC,aAAL,CAAmBH,CAAnB,CAAb,CACA,GAAIE,CAAM,EAAIA,CAAM,CAAC7B,MAAjB,EAA2B6B,CAAM,CAACE,EAAP,CAAU,UAAV,CAA/B,CAAsD,CAElD,MAAO,CAAC,CAACF,CAAM,CAAC7B,MACnB,CAED,QACH,C,mCASM,CACH,MAAO,MAAKgC,QAAL,CAAc,KAAKP,iBAAL,EAAd,CACV,C,2CASU,CACP,MAAO,MAAKO,QAAL,CAAc,KAAKN,qBAAL,EAAd,CAA4C,CAAC,CAA7C,CACV,C,0CAWQZ,C,CAAYF,C,CAAW,CAC5B,GAAiB,CAAb,CAAAE,CAAJ,CAAoB,CAChB,MAAO,MAAKmB,OAAL,EACV,CAED,GAAIN,CAAAA,CAAU,CAAG,KAAKJ,aAAL,CAAmBT,CAAnB,CAAjB,CACA,GAAmB,IAAf,GAAAa,CAAJ,CAAyB,CACrB,MAAO,MAAKM,OAAL,EACV,CAED,MAAO,MAAKC,SAAL,CAAeP,CAAf,CAA2Bf,CAA3B,CACV,C,4CAESe,C,CAAYf,C,CAAW,CAC7B,GAAI,CAACe,CAAL,CAAiB,CACb,MAAO,MAAKM,OAAL,EACV,CAED,GAAgC,WAA5B,QAAON,CAAAA,CAAU,CAACnB,KAAlB,EAA2CmB,CAAU,CAACnB,KAAtD,EAA+D,CAACmB,CAAU,CAACQ,OAA/E,CAAwF,CACpFR,CAAU,CAACQ,OAAX,IACArD,MAAM,CAACsD,UAAP,CAAkB,KAAKF,SAAL,CAAeG,IAAf,CAAoB,IAApB,CAAlB,CAA6CV,CAAU,CAACnB,KAAxD,CAA+DmB,CAA/D,CAA2Ef,CAA3E,EAEA,MAAO,KACV,CALD,IAKO,IAAI,CAACe,CAAU,CAAChB,MAAZ,EAAsB,CAAC,KAAKiB,qBAAL,CAA2BD,CAA3B,CAA3B,CAAmE,CACtE,GAAIW,CAAAA,CAAE,CAAgB,CAAC,CAAd,EAAA1B,CAAS,CAAS,uBAAT,CAAmC,mBAArD,CACA,MAAO,MAAKoB,QAAL,CAAc,KAAKM,CAAL,EAASX,CAAU,CAACb,UAApB,CAAd,CAA+CF,CAA/C,CACV,CAED,KAAKzB,IAAL,GAEA,KAAKoD,iBAAL,CAAuB,cAAvB,CAAuCZ,CAAvC,EACA,KAAKa,UAAL,CAAgBb,CAAhB,EACA,KAAKY,iBAAL,CAAuB,aAAvB,CAAsCZ,CAAtC,EAEA,MAAO,KACV,C,oDASab,C,CAAY,CACtB,GAAmB,IAAf,GAAAA,CAAU,EAA0B,CAAb,CAAAA,CAAvB,EAAyCA,CAAU,EAAI,KAAKzB,KAAL,CAAWW,MAAtE,CAA8E,CAC1E,MAAO,KACV,CAGD,GAAI2B,CAAAA,CAAU,CAAG,KAAKc,mBAAL,CAAyB,KAAKpD,KAAL,CAAWyB,CAAX,CAAzB,CAAjB,CAGAa,CAAU,CAAGvB,UAAEC,MAAF,CAASsB,CAAT,CAAqB,CAACb,UAAU,CAAEA,CAAb,CAArB,CAAb,CAEA,MAAOa,CAAAA,CACV,C,gEASmBA,C,CAAY,CAE5B,GAAiC,WAA7B,QAAOA,CAAAA,CAAU,CAACe,MAAlB,EAAiF,WAArC,QAAOf,CAAAA,CAAU,CAACgB,cAAlE,CAAkG,CAC9FhB,CAAU,CAACgB,cAAX,CAA4BhB,CAAU,CAACe,MAC1C,CAED,GAAkC,WAA9B,QAAOf,CAAAA,CAAU,CAACrB,OAAlB,EAA0E,WAA7B,QAAOqB,CAAAA,CAAU,CAACE,MAAnE,CAA2F,CACvFF,CAAU,CAACE,MAAX,CAAoBF,CAAU,CAACrB,OAClC,CAED,GAAkC,WAA9B,QAAOqB,CAAAA,CAAU,CAACiB,OAAlB,EAAwE,WAA3B,QAAOjB,CAAAA,CAAU,CAACkB,IAAnE,CAAyF,CACrFlB,CAAU,CAACkB,IAAX,CAAkBlB,CAAU,CAACiB,OAChC,CAEDjB,CAAU,CAAGvB,UAAEC,MAAF,CAAS,EAAT,CAAa,KAAKH,YAAlB,CAAgCyB,CAAhC,CAAb,CAEAA,CAAU,CAAGvB,UAAEC,MAAF,CAAS,EAAT,CAAa,CACtByC,QAAQ,CAAEnB,CAAU,CAACE,MADC,CAEtBkB,WAAW,CAAE,OAFS,CAAb,CAGVpB,CAHU,CAAb,CAKA,GAAIA,CAAU,CAACmB,QAAf,CAAyB,CACrBnB,CAAU,CAACmB,QAAX,CAAsB,cAAEnB,CAAU,CAACmB,QAAb,EAAuBE,KAAvB,EACzB,CAED,MAAOrB,CAAAA,CACV,C,oDAWaA,C,CAAY,CACtB,GAAIA,CAAU,CAACE,MAAf,CAAuB,CACnB,MAAO,cAAEF,CAAU,CAACE,MAAb,CACV,CAED,MAAO,KACV,C,4DAUiBtC,C,CAAW0D,C,CAAM,CAC/B,GAA6C,WAAzC,QAAO,MAAK1E,aAAL,CAAmBgB,CAAnB,CAAX,CAA0D,CACtD,MAAO,KACV,CAED,KAAKhB,aAAL,CAAmBgB,CAAnB,EAA8BC,OAA9B,CAAsC,SAAS0D,CAAT,CAAoB,CACtDA,CAAS,CAACC,IAAV,CAAe,IAAf,CAAqBF,CAArB,CACH,CAFD,CAEG,IAFH,EAIA,MAAO,KACV,C,wDAQe1D,C,CAAWE,C,CAAS,CAChC,GAA6C,WAAzC,QAAO,MAAKlB,aAAL,CAAmBgB,CAAnB,CAAX,CAA0D,CACtD,KAAKhB,aAAL,CAAmBgB,CAAnB,EAAgC,EACnC,CAED,KAAKhB,aAAL,CAAmBgB,CAAnB,EAA8B6D,IAA9B,CAAmC3D,CAAnC,EAEA,MAAO,KACV,C,kEAUoBkC,C,CAAY,CAC7B,KAAK0B,SAAL,CAAeD,IAAf,CAEA,CACIE,IAAI,CAAE,KAAKC,eADf,CAEIC,IAAI,CAAE,CAAC,OAAD,CAAU,sBAAV,CAAgCpD,UAAEqD,KAAF,CAAQ,KAAKC,IAAb,CAAmB,IAAnB,CAAhC,CAFV,CAFA,CAKG,CACCJ,IAAI,CAAE,KAAKC,eADZ,CAECC,IAAI,CAAE,CAAC,OAAD,CAAU,0BAAV,CAAoCpD,UAAEqD,KAAF,CAAQ,KAAKE,QAAb,CAAuB,IAAvB,CAApC,CAFP,CALH,CAWA,CACIL,IAAI,CAAE,KAAKC,eADf,CAEIC,IAAI,CAAE,CAAC,OAAD,CAAU,qBAAV,CAA+BpD,UAAEqD,KAAF,CAAQ,KAAKxB,OAAb,CAAsB,IAAtB,CAA/B,CAFV,CAXA,CAiBA,CACIqB,IAAI,CAAE,cAAE,+BAAF,CADV,CAEIE,IAAI,CAAE,CAAC,OAAD,CAAUpD,UAAEqD,KAAF,CAAQ,KAAKtE,IAAb,CAAmB,IAAnB,CAAV,CAFV,CAjBA,CAuBA,CACImE,IAAI,CAAE,cAAE,MAAF,CADV,CAEIE,IAAI,CAAE,CAAC,SAAD,CAAYpD,UAAEqD,KAAF,CAAQ,KAAKG,aAAb,CAA4B,IAA5B,CAAZ,CAFV,CAvBA,EA4BA,GAAIjC,CAAU,CAAClB,WAAf,CAA4B,CACxB,GAAIoD,CAAAA,CAAU,CAAG,KAAK/B,aAAL,CAAmBH,CAAnB,CAAjB,CACA,KAAK0B,SAAL,CAAeD,IAAf,CAAoB,CAChBE,IAAI,CAAEO,CADU,CAEhBL,IAAI,CAAE,CAAC,OAAD,CAAUpD,UAAEqD,KAAF,CAAQ,SAASvE,CAAT,CAAY,CAChC,GAAmE,CAA/D,iBAAEA,CAAC,CAAC2C,MAAJ,EAAYiC,OAAZ,CAAoB,gCAApB,EAAoD9D,MAAxD,CAAsE,CAElElB,MAAM,CAACsD,UAAP,CAAkBhC,UAAEqD,KAAF,CAAQ,KAAKC,IAAb,CAAmB,IAAnB,CAAlB,CAA4C,GAA5C,CACH,CACJ,CALe,CAKb,IALa,CAAV,CAFU,CAApB,CASH,CAED,KAAKL,SAAL,CAAe7D,OAAf,CAAuB,SAAUuE,CAAV,CAAoB,CACvCA,CAAQ,CAACT,IAAT,CAAcU,EAAd,CAAiBrF,KAAjB,CAAuBoF,CAAQ,CAACT,IAAhC,CAAsCS,CAAQ,CAACP,IAA/C,CACH,CAFD,EAIA,MAAO,KACV,C,+DASoB,CAEjB,GAAI,KAAKH,SAAT,CAAoB,CAChB,KAAKA,SAAL,CAAe7D,OAAf,CAAuB,SAASuE,CAAT,CAAmB,CACtCA,CAAQ,CAACT,IAAT,CAAcW,GAAd,CAAkBtF,KAAlB,CAAwBoF,CAAQ,CAACT,IAAjC,CAAuCS,CAAQ,CAACP,IAAhD,CACH,CAFD,CAGH,CACD,KAAKH,SAAL,CAAiB,EAAjB,CAEA,MAAO,KACV,C,8CAUU1B,C,CAAY,CAEnB,KAAKuC,iBAAL,CAAyBvC,CAAzB,CACA,KAAKwC,oBAAL,CAA0BxC,CAAU,CAACb,UAArC,EAGA,GAAIlB,CAAAA,CAAQ,CAAG,cAAE,KAAKwE,kBAAL,EAAF,CAAf,CAGAxE,CAAQ,CAACyE,IAAT,CAAc,8BAAd,EACKC,IADL,CACU3C,CAAU,CAAC4C,KADrB,EAIA3E,CAAQ,CAACyE,IAAT,CAAc,6BAAd,EACKC,IADL,CACU3C,CAAU,CAACkB,IADrB,EAIA,GAAI,KAAK2B,WAAL,CAAiB7C,CAAU,CAACb,UAA5B,CAAJ,CAA6C,CACzClB,CAAQ,CAACyE,IAAT,CAAc,0BAAd,EAAwCI,IAAxC,CAA6C,UAA7C,IACH,CAFD,IAEO,CACH7E,CAAQ,CAACyE,IAAT,CAAc,0BAAd,EAAwCI,IAAxC,CAA6C,UAA7C,IACH,CAGD,GAAI,KAAKC,UAAL,CAAgB/C,CAAU,CAACb,UAA3B,CAAJ,CAA4C,CACxClB,CAAQ,CAACyE,IAAT,CAAc,sBAAd,EAAoCI,IAApC,CAAyC,UAAzC,IACH,CAFD,IAEO,CACH7E,CAAQ,CAACyE,IAAT,CAAc,sBAAd,EAAoCI,IAApC,CAAyC,UAAzC,IACH,CAED7E,CAAQ,CAACyE,IAAT,CAAc,0BAAd,EAAwCM,IAAxC,CAA6C,MAA7C,CAAqD,QAArD,EACA/E,CAAQ,CAACyE,IAAT,CAAc,sBAAd,EAAoCM,IAApC,CAAyC,MAAzC,CAAiD,QAAjD,EACA/E,CAAQ,CAACyE,IAAT,CAAc,qBAAd,EAAmCM,IAAnC,CAAwC,MAAxC,CAAgD,QAAhD,EAGAhD,CAAU,CAAC/B,QAAX,CAAsBA,CAAtB,CAGA,KAAKgF,aAAL,CAAmBjD,CAAnB,EAIA,KAAKkD,oBAAL,CAA0BlD,CAA1B,EAEA,MAAO,KACV,C,+DAQoB,CACjB,MAAO,cAAE,KAAK9B,eAAP,EAAwBiF,KAAxB,EACV,C,oDAUanD,C,CAAY,IAElB4B,CAAAA,CAAe,CAAG,cAAE,4CAAF,EACjBe,IADiB,CACZ3C,CAAU,CAAC/B,QADC,EAEjBT,IAFiB,EAFA,CAOlB4F,CAAe,CAAG,cAAE,YAAF,EACjBC,IADiB,OAPA,CAUtB,GAAI,KAAKpD,qBAAL,CAA2BD,CAA3B,CAAJ,CAA4C,CACxC,GAAIkC,CAAAA,CAAU,CAAG,KAAK/B,aAAL,CAAmBH,CAAnB,CAAjB,CAEAkC,CAAU,CAACZ,IAAX,CAAgB,WAAhB,CAA6B,QAA7B,EAEA,GAAIgC,CAAAA,CAAM,CAAG,KAAKC,eAAL,CAAqBrB,CAArB,CAAb,CACA,GAAIoB,CAAJ,CAAY,CACRtD,CAAU,CAACsD,MAAX,CAAoBA,CAAM,CAAG,CAChC,CAED,GAAItD,CAAU,CAACsD,MAAf,CAAuB,CACnB1B,CAAe,CAAC4B,GAAhB,CAAoB,QAApB,CAA8BxD,CAAU,CAACsD,MAAX,CAAoB,CAAlD,CACH,CAGD,KAAKG,gBAAL,CAAsBzD,CAAtB,EAEA,cAAE0D,QAAQ,CAACxC,IAAX,EAAiByC,MAAjB,CAAwB/B,CAAxB,EACA,KAAKA,eAAL,CAAuBA,CAAvB,CAIA,KAAKA,eAAL,CAAqB4B,GAArB,CAAyB,CACrBI,GAAG,CAAE,CADgB,CAErBC,IAAI,CAAE,CAFe,CAAzB,EAKAT,CAAe,CACVU,OADL,CACa,CACLC,SAAS,CAAE,KAAKC,kBAAL,CAAwBhE,CAAxB,CADN,CADb,EAGOiE,OAHP,GAGiBC,IAHjB,CAGsB,UAAW,CACrB,KAAKC,YAAL,CAAkBnE,CAAlB,EACA,KAAKoE,UAAL,CAAgBpE,CAAhB,CAEH,CAJa,CAIZU,IAJY,CAIP,IAJO,CAHtB,EAQS2D,KART,CAQe,UAAW,CAEjB,CAVT,CAYH,CAvCD,IAuCO,IAAIrE,CAAU,CAAChB,MAAf,CAAuB,CAC1BgB,CAAU,CAACsE,QAAX,IAGAtE,CAAU,CAACmB,QAAX,CAAsB,cAAE,MAAF,EAAUE,KAAV,EAAtB,CACArB,CAAU,CAACoB,WAAX,CAAyB,QAAzB,CAGA,KAAKqC,gBAAL,CAAsBzD,CAAtB,EAGA4B,CAAe,CAAC2C,QAAhB,CAAyB,QAAzB,EAGA,cAAEb,QAAQ,CAACxC,IAAX,EAAiByC,MAAjB,CAAwB/B,CAAxB,EACA,KAAKA,eAAL,CAAuBA,CAAvB,CAEA,KAAKA,eAAL,CAAqB4C,MAArB,CAA4B,KAAKC,2BAAL,EAA5B,EACA,KAAK7C,eAAL,CAAqB4B,GAArB,CAAyB,UAAzB,CAAqC,OAArC,EAEA,KAAKkB,iBAAL,CAAyB,GAAIC,UAAJ,CACrB,cAAE,MAAF,CADqB,CAErB,KAAK/C,eAAL,CAAqB,CAArB,CAFqB,CAEI,CACrBgD,eAAe,GADM,CAErBhG,SAAS,CAAEoB,CAAU,CAACpB,SAAX,CAAuB,QAFb,CAGrBiG,YAAY,CAAE,uBAHO,CAKrBC,SAAS,CAAE,CACPtH,IAAI,CAAE,CACFuH,OAAO,GADL,CADC,CAIPC,UAAU,CAAE,CACRC,MAAM,CAAE,IADA,CAERF,OAAO,GAFC,CAJL,CALU,CAFJ,CAAzB,CAmBA,KAAKX,UAAL,CAAgBpE,CAAhB,CACH,CAED,MAAO,KACV,C,8CAUUA,C,CAAY,CAEnB,KAAK4B,eAAL,CAAqBsD,MAArB,CAA4B,EAA5B,CAAgCzG,UAAEqD,KAAF,CAAQ,UAAW,CAE3C,KAAKqD,YAAL,CAAkBnF,CAAlB,EAGA,KAAK4B,eAAL,CAAqBwD,KAArB,GACAjI,MAAM,CAACsD,UAAP,CAAkBhC,UAAEqD,KAAF,CAAQ,UAAW,CAIjC,GAAI,KAAKF,eAAT,CAA0B,CACtB,KAAKA,eAAL,CAAqBwD,KAArB,EACH,CACJ,CAPiB,CAOf,IAPe,CAAlB,CAOU,GAPV,CASH,CAf2B,CAezB,IAfyB,CAAhC,EAiBA,MAAO,KACV,C,kDAUYpF,C,CAAY,CAMrB,GAAIqF,CAAAA,CAAM,CAAG,aAAe,KAAK/H,QAApB,CAA+B,GAA/B,CAAqC0C,CAAU,CAACb,UAA7D,CACA,KAAKyC,eAAL,CAAqBoB,IAArB,CAA0B,IAA1B,CAAgCqC,CAAhC,EAEA,GAAIC,CAAAA,CAAU,CAAG,KAAK1D,eAAL,CAAqBc,IAArB,CAA0B,6BAA1B,EAAuDrB,KAAvD,EAAjB,CACAiE,CAAU,CAACtC,IAAX,CAAgB,IAAhB,CAAsBqC,CAAM,CAAG,OAA/B,EACAC,CAAU,CAACtC,IAAX,CAAgB,MAAhB,CAAwB,UAAxB,EAEA,GAAIuC,CAAAA,CAAY,CAAG,KAAK3D,eAAL,CAAqBc,IAArB,CAA0B,8BAA1B,EAAwDrB,KAAxD,EAAnB,CACAkE,CAAY,CAACvC,IAAb,CAAkB,IAAlB,CAAwBqC,CAAM,CAAG,QAAjC,EACAE,CAAY,CAACvC,IAAb,CAAkB,iBAAlB,CAAqCqC,CAAM,CAAG,OAA9C,EAGA,KAAKzD,eAAL,CAAqBoB,IAArB,CAA0B,MAA1B,CAAkC,QAAlC,EACA,KAAKpB,eAAL,CAAqBoB,IAArB,CAA0B,UAA1B,CAAsC,CAAtC,EACA,KAAKpB,eAAL,CAAqBoB,IAArB,CAA0B,iBAA1B,CAA6CqC,CAAM,CAAG,QAAtD,EACA,KAAKzD,eAAL,CAAqBoB,IAArB,CAA0B,kBAA1B,CAA8CqC,CAAM,CAAG,OAAvD,EAGA,GAAInF,CAAAA,CAAM,CAAG,KAAKC,aAAL,CAAmBH,CAAnB,CAAb,CACA,GAAIE,CAAJ,CAAY,CACR,GAAI,CAACA,CAAM,CAAC8C,IAAP,CAAY,UAAZ,CAAL,CAA8B,CAC1B9C,CAAM,CAAC8C,IAAP,CAAY,UAAZ,CAAwB,CAAxB,CACH,CAED9C,CAAM,CACDoB,IADL,CACU,sBADV,CACkCpB,CAAM,CAAC8C,IAAP,CAAY,kBAAZ,CADlC,EAEKA,IAFL,CAEU,kBAFV,CAE8BqC,CAAM,CAAG,OAFvC,CAIH,CAED,KAAKG,iBAAL,CAAuBxF,CAAvB,EAEA,MAAO,KACV,C,oDAQazC,C,CAAG,CACb,GAAIkI,CAAAA,CAAgB,CAAG,iEAAvB,CACAA,CAAgB,EAAI,4CAApB,CACA,OAAQlI,CAAC,CAACmI,OAAV,EACI,IAAK,GAAL,CACI,KAAKpF,OAAL,GACA,MAGJ,IAAK,EAAL,CAEI,CAAC,UAAW,CACR,GAAI,CAAC,KAAKiC,iBAAL,CAAuBoD,WAA5B,CAAyC,CAErC,MACH,CAJO,GAOJC,CAAAA,CAAa,CAAG,cAAElC,QAAQ,CAACkC,aAAX,CAPZ,CAQJC,CAAU,CAAG,KAAK1F,aAAL,CAAmB,KAAKoC,iBAAxB,CART,CASJuD,CAAa,CAAG,cAAEL,CAAF,CATZ,CAUJM,CAAe,CAAG,cAAE,oCAAF,CAVd,CAWJC,CAXI,CAaR,GAAIH,CAAJ,CAAgB,CACZC,CAAa,CAAGA,CAAa,CAACG,MAAd,CAAqB,SAASC,CAAT,CAAgBvH,CAAhB,CAAyB,CAC1D,MAAsB,KAAf,GAAAkH,CAAU,GACTA,CAAU,CAACM,GAAX,CAAexH,CAAf,EAAwBN,MAAxB,EACG0H,CAAe,CAACI,GAAhB,CAAoBxH,CAApB,EAA6BN,MADhC,EAEGwH,CAAU,CAACzF,EAAX,CAAczB,CAAd,CAFH,EAGGoH,CAAe,CAAC3F,EAAhB,CAAmBzB,CAAnB,CAJM,CAKpB,CANe,CAOnB,CAGDmH,CAAa,CAACM,IAAd,CAAmB,SAASF,CAAT,CAAgBvH,CAAhB,CAAyB,CACxC,GAAIiH,CAAa,CAACxF,EAAd,CAAiBzB,CAAjB,CAAJ,CAA+B,CAC3BqH,CAAY,CAAGE,CAAf,CACA,QACH,CAED,QACH,CAPD,EAxBQ,GAiCJG,CAAAA,CAjCI,CAkCJC,CAlCI,CAmCJC,CAnCI,CAoCR,GAAoB,IAAK,EAArB,EAAAP,CAAJ,CAA4B,CACxB,GAAI/G,CAAAA,CAAS,CAAG,CAAhB,CACA,GAAI1B,CAAC,CAACiJ,QAAN,CAAgB,CACZvH,CAAS,CAAG,CAAC,CAChB,CACDoH,CAAS,CAAGL,CAAZ,CACA,EAAG,CACCK,CAAS,EAAIpH,CAAb,CACAqH,CAAQ,CAAG,cAAER,CAAa,CAACO,CAAD,CAAf,CACd,CAHD,MAGSC,CAAQ,CAACjI,MAAT,EAAmBiI,CAAQ,CAAClG,EAAT,CAAY,WAAZ,CAAnB,EAA+CkG,CAAQ,CAAClG,EAAT,CAAY,SAAZ,CAHxD,EAIA,GAAIkG,CAAQ,CAACjI,MAAb,CAAqB,CAEjBkI,CAAa,CAAGD,CAAQ,CAACG,OAAT,CAAiBZ,CAAjB,EAA6BxH,MAA7C,CACAkI,CAAa,CAAGA,CAAa,EAAID,CAAQ,CAACG,OAAT,CAAiB,KAAK7E,eAAtB,EAAuCvD,MAC3E,CAJD,IAIO,CAEHkI,CAAa,GAChB,CACJ,CAED,GAAIA,CAAJ,CAAmB,CACfD,CAAQ,CAAClB,KAAT,EACH,CAFD,IAEO,CACH,GAAI7H,CAAC,CAACiJ,QAAN,CAAgB,CAEZ,KAAK5E,eAAL,CAAqBc,IAArB,CAA0B+C,CAA1B,EAA4CiB,IAA5C,GAAmDtB,KAAnD,EACH,CAHD,IAGO,CACH,GAAI,KAAK7C,iBAAL,CAAuB+B,QAA3B,CAAqC,CAEjC,KAAK1C,eAAL,CAAqBwD,KAArB,EACH,CAHD,IAGO,CAEHS,CAAU,CAACT,KAAX,EACH,CACJ,CACJ,CACD7H,CAAC,CAACoJ,cAAF,EACH,CAzED,EAyEGnF,IAzEH,CAyEQ,IAzER,EA0EA,MAlFR,CAoFH,C,4CAUSoF,C,CAAS,CACf,GAAI,KAAK1J,OAAL,EAAmC,WAAnB,QAAO0J,CAAAA,CAA3B,CAAoD,CAChD,GAAIC,CAAAA,CAAiB,CAAG,KAAK3J,OAAL,CAAa4J,OAAb,CAAqB,KAAKzJ,UAA1B,CAAxB,CACA,GAAIwJ,CAAJ,CAAuB,CACnB,GAAIE,CAAAA,CAAc,CAAG7H,QAAQ,CAAC2H,CAAD,CAAoB,EAApB,CAA7B,CACA,GAAIE,CAAc,EAAI,KAAKrJ,KAAL,CAAWW,MAAjC,CAAyC,CACrCuI,CAAO,CAAGG,CACb,CACJ,CACJ,CAED,GAAuB,WAAnB,QAAOH,CAAAA,CAAX,CAAoC,CAChCA,CAAO,CAAG,KAAKnH,oBAAL,EACb,CAED,KAAKmB,iBAAL,CAAuB,aAAvB,CAAsCgG,CAAtC,EACA,KAAKvG,QAAL,CAAcuG,CAAd,EACA,KAAKhG,iBAAL,CAAuB,YAAvB,CAAqCgG,CAArC,EAEA,MAAO,KACV,C,iDASa,CACV,MAAO,MAAKI,SAAL,CAAe,CAAf,CACV,C,yCASS,CACN,KAAKpG,iBAAL,CAAuB,WAAvB,EAEA,GAAI,KAAK2B,iBAAT,CAA4B,CACxB,GAAI0E,CAAAA,CAAc,CAAG,KAAK9G,aAAL,CAAmB,KAAKoC,iBAAxB,CAArB,CACA,GAAI0E,CAAJ,CAAoB,CAChB,GAAI,CAACA,CAAc,CAACjE,IAAf,CAAoB,UAApB,CAAL,CAAsC,CAClCiE,CAAc,CAACjE,IAAf,CAAoB,UAApB,CAAgC,IAAhC,CACH,CACDiE,CAAc,CAAC7B,KAAf,EACH,CACJ,CAED,KAAK5H,IAAL,KAEA,KAAKoD,iBAAL,CAAuB,UAAvB,EAEA,MAAO,KACV,C,kCAUIsG,C,CAAY,CACb,KAAKtG,iBAAL,CAAuB,YAAvB,EAEA,GAAI,KAAKgB,eAAL,EAAwB,KAAKA,eAAL,CAAqBvD,MAAjD,CAAyD,CACrD,KAAKuD,eAAL,CAAqBpE,IAArB,GACA,GAAI,KAAKkH,iBAAT,CAA4B,CACxB,KAAKA,iBAAL,CAAuByC,OAAvB,EACH,CACJ,CAGD,GAAI,KAAK5E,iBAAT,CAA4B,CACxB,GAAIrC,CAAAA,CAAM,CAAG,KAAKC,aAAL,CAAmB,KAAKoC,iBAAxB,CAAb,CACA,GAAIrC,CAAJ,CAAY,CACR,GAAIA,CAAM,CAACoB,IAAP,CAAY,qBAAZ,CAAJ,CAAwC,CACpCpB,CAAM,CAAC8C,IAAP,CAAY,iBAAZ,CAA+B9C,CAAM,CAACoB,IAAP,CAAY,qBAAZ,CAA/B,CACH,CAED,GAAIpB,CAAM,CAACoB,IAAP,CAAY,sBAAZ,CAAJ,CAAyC,CACrCpB,CAAM,CAAC8C,IAAP,CAAY,kBAAZ,CAAgC9C,CAAM,CAACoB,IAAP,CAAY,sBAAZ,CAAhC,CACH,CAED,GAAIpB,CAAM,CAACoB,IAAP,CAAY,mBAAZ,CAAJ,CAAsC,CAClCpB,CAAM,CAAC8C,IAAP,CAAY,UAAZ,CAAwB9C,CAAM,CAACoB,IAAP,CAAY,UAAZ,CAAxB,CACH,CACJ,CAGD,KAAKiB,iBAAL,CAAyB,IAC5B,CAED,GAAI6E,CAAAA,CAAQ,CAAG,CAAf,CACA,GAAIF,CAAJ,CAAgB,CACZE,CAAQ,CAAG,GACd,CAGD,cAAE,sCAAF,EAAwCC,MAAxC,GACA,cAAE,oCAAF,EAAsCC,UAAtC,CAAiD,gBAAjD,EACA,cAAE,+BAAF,EAAiCC,OAAjC,CAAyCH,CAAzC,CAAmD,UAAW,CAC1D,cAAE,IAAF,EAAQC,MAAR,EACH,CAFD,EAKA,GAAI,KAAKzF,eAAL,EAAwB,KAAKA,eAAL,CAAqBvD,MAAjD,CAAyD,CACrD,GAAIgH,CAAAA,CAAM,CAAG,KAAKzD,eAAL,CAAqBoB,IAArB,CAA0B,IAA1B,CAAb,CACA,GAAIqC,CAAJ,CAAY,CACR,GAAImC,CAAAA,CAAkB,CAAG,uBAAwBnC,CAAxB,CAAiC,UAA1D,CACA,cAAEmC,CAAF,EAAsBF,UAAtB,CAAiC,UAAjC,EACA,cAAEE,CAAF,EAAsBF,UAAtB,CAAiC,kBAAjC,CACH,CACJ,CAGD,KAAK7J,kBAAL,GAEA,KAAKgK,iBAAL,GAEA,KAAK7G,iBAAL,CAAuB,WAAvB,EAEA,KAAKgB,eAAL,CAAuB,IAAvB,CACA,KAAK8C,iBAAL,CAAyB,IAAzB,CACA,MAAO,KACV,C,mCASM,CAEH,GAAIkC,CAAAA,CAAO,CAAG,KAAKnH,oBAAL,EAAd,CAEA,MAAO,MAAKY,QAAL,CAAcuG,CAAd,CACV,C,2DAQkB,CACf,MAAO,cAAE,KAAKhF,eAAP,CACV,C,8DASkB5B,C,CAAY,IACvB+D,CAAAA,CAAS,CAAG,cAAE5G,MAAF,EAAU4G,SAAV,EADW,CAEvB2D,CAAc,CAAG,cAAEvK,MAAF,EAAUwK,MAAV,EAFM,CAGvBzF,CAAU,CAAG,KAAK/B,aAAL,CAAmBH,CAAnB,CAHU,CAK3B,GAA6B,KAAzB,GAAAA,CAAU,CAACpB,SAAf,CAAoC,CAEhCmF,CAAS,CAAG7B,CAAU,CAACsC,MAAX,GAAoBZ,GAApB,CAA2B8D,CAAc,CAAG,CAC3D,CAHD,IAGO,IAA6B,QAAzB,GAAA1H,CAAU,CAACpB,SAAf,CAAuC,CAE1CmF,CAAS,CAAG7B,CAAU,CAACsC,MAAX,GAAoBZ,GAApB,CAA0B1B,CAAU,CAACyF,MAAX,EAA1B,CAAiDD,CAAc,CAAG,CACjF,CAHM,IAGA,IAAIxF,CAAU,CAACyF,MAAX,IAAyC,EAAjB,CAAAD,CAA5B,CAAmD,CAEtD3D,CAAS,CAAG7B,CAAU,CAACsC,MAAX,GAAoBZ,GAApB,CAA2B,CAAC8D,CAAc,CAAGxF,CAAU,CAACyF,MAAX,EAAlB,EAAyC,CACnF,CAHM,IAGA,CAGH5D,CAAS,CAAG7B,CAAU,CAACsC,MAAX,GAAoBZ,GAApB,CAA4C,EAAjB,CAAA8D,CAC1C,CAGD3D,CAAS,CAAG6D,IAAI,CAACC,GAAL,CAAS,CAAT,CAAY9D,CAAZ,CAAZ,CAGAA,CAAS,CAAG6D,IAAI,CAACE,GAAL,CAAS,cAAEpE,QAAF,EAAYiE,MAAZ,GAAuBD,CAAhC,CAAgD3D,CAAhD,CAAZ,CAEA,MAAO6D,CAAAA,IAAI,CAACG,IAAL,CAAUhE,CAAV,CACV,C,iFAQ6B,IACtB2D,CAAAA,CAAc,CAAG,cAAEvK,MAAF,EAAUwK,MAAV,EADK,CAEtBK,CAAU,CAAG,KAAKpG,eAAL,CAAqB+F,MAArB,EAFS,CAItBM,CAAa,CAAG,cAAE9K,MAAF,EAAU+K,KAAV,EAJM,CAKtBC,CAAS,CAAG,KAAKvG,eAAL,CAAqBsG,KAArB,EALU,CAO1B,MAAO,CACHtE,GAAG,CAAEgE,IAAI,CAACG,IAAL,CAAU,CAACL,CAAc,CAAGM,CAAlB,EAAgC,CAA1C,CADF,CAEHnE,IAAI,CAAE+D,IAAI,CAACG,IAAL,CAAU,CAACE,CAAa,CAAGE,CAAjB,EAA8B,CAAxC,CAFH,CAIV,C,kDAUYnI,C,CAAY,CACrB,GAAIiB,CAAAA,CAAO,CAAG,KAAKW,eAAnB,CACA,GAAI,CAACX,CAAD,EAAY,CAACA,CAAO,CAAC5C,MAAzB,CAAiC,CAE7B,MAAO,KACV,CAED,GAAI+J,CAAAA,CAAJ,CACA,OAAQpI,CAAU,CAACpB,SAAnB,EACI,IAAK,MAAL,CACIwJ,CAAY,CAAG,CAAC,MAAD,CAAS,OAAT,CAAkB,KAAlB,CAAyB,QAAzB,CAAf,CACA,MACJ,IAAK,OAAL,CACIA,CAAY,CAAG,CAAC,OAAD,CAAU,MAAV,CAAkB,KAAlB,CAAyB,QAAzB,CAAf,CACA,MACJ,IAAK,KAAL,CACIA,CAAY,CAAG,CAAC,KAAD,CAAQ,QAAR,CAAkB,OAAlB,CAA2B,MAA3B,CAAf,CACA,MACJ,IAAK,QAAL,CACIA,CAAY,CAAG,CAAC,QAAD,CAAW,KAAX,CAAkB,OAAlB,CAA2B,MAA3B,CAAf,CACA,MACJ,QACIA,CAAY,CAAG,MAAf,CACA,MAfR,CARqB,GA0BjBlI,CAAAA,CAAM,CAAG,KAAKC,aAAL,CAAmBH,CAAnB,CA1BQ,CA2BjBtD,CAAM,CAAG,CACTkC,SAAS,CAAEoB,CAAU,CAACpB,SAAX,CAAuB,QADzB,CAETgG,eAAe,GAFN,CAGTE,SAAS,CAAE,CACPuD,IAAI,CAAE,CACFC,SAAS,CAAEF,CADT,CADC,CAIPG,KAAK,CAAE,CACH5J,OAAO,CAAE,uBADN,CAJA,CAHF,CAWT6J,QAAQ,CAAE,kBAASlH,CAAT,CAAe,CACrBmH,CAAwB,CAACnH,CAAD,CAC3B,CAbQ,CAcToH,QAAQ,CAAE,kBAASpH,CAAT,CAAe,CACrBmH,CAAwB,CAACnH,CAAD,CAC3B,CAhBQ,CA3BQ,CA8CjBmH,CAAwB,CAAG,SAASnH,CAAT,CAAe,IACtC1C,CAAAA,CAAS,CAAG0C,CAAI,CAAC1C,SAAL,CAAe+J,KAAf,CAAqB,GAArB,EAA0B,CAA1B,CAD0B,CAEpCC,CAAU,CAA4C,CAAC,CAA1C,IAAC,MAAD,CAAS,OAAT,EAAkBC,OAAlB,CAA0BjK,CAA1B,CAFuB,CAGpCiG,CAAY,CAAGvD,CAAI,CAACwH,QAAL,CAAcC,MAAd,CAAqBC,aAArB,CAAmC,uBAAnC,CAHqB,CAIpCC,CAAW,CAAG,cAAE3H,CAAI,CAACwH,QAAL,CAAcC,MAAd,CAAqBC,aAArB,CAAmC,gCAAnC,CAAF,CAJsB,CAK1C,GAAIJ,CAAJ,CAAgB,IACRM,CAAAA,CAAW,CAAGC,UAAU,CAAChM,MAAM,CAACiM,gBAAP,CAAwBvE,CAAxB,EAAsC8C,MAAvC,CADhB,CAER0B,CAAW,CAAGF,UAAU,CAAChM,MAAM,CAACiM,gBAAP,CAAwBvE,CAAxB,EAAsCjB,GAAvC,CAFhB,CAGR0F,CAAY,CAAGH,UAAU,CAAChM,MAAM,CAACiM,gBAAP,CAAwB9H,CAAI,CAACwH,QAAL,CAAcC,MAAtC,EAA8CpB,MAA/C,CAHjB,CAIR4B,CAAY,CAAGJ,UAAU,CAAChM,MAAM,CAACiM,gBAAP,CAAwB9H,CAAI,CAACwH,QAAL,CAAcC,MAAtC,EAA8CnF,GAA/C,CAJjB,CAKR4F,CAAiB,CAAGL,UAAU,CAACF,CAAW,CAACzF,GAAZ,CAAgB,gBAAhB,CAAD,CALtB,CAMRiG,CAAuB,CAAwD,CAArD,CAAAN,UAAU,CAACF,CAAW,CAACzF,GAAZ,CAAgB,qBAAhB,CAAD,CAN5B,CAORkG,CAAQ,CAAGL,CAAW,CAAIH,CAAW,CAAG,CAPhC,CAQRS,CAAM,CAAGL,CAAY,CAAGC,CAAf,CAA8BC,CAA9B,CAAkDC,CARnD,CASRG,CAAM,CAAGL,CAAY,CAAGC,CAAf,CAAmCC,CATpC,CAUZ,GAAIC,CAAQ,EAAIC,CAAZ,EAAsBD,CAAQ,EAAIE,CAAtC,CAA8C,CAC1C,GAAIC,CAAAA,CAAW,CAAG,CAAlB,CACA,GAAIH,CAAQ,CAAIJ,CAAY,CAAG,CAA/B,CAAmC,CAC/BO,CAAW,CAAGF,CAAM,CAAGT,CAC1B,CAFD,IAEO,CACHW,CAAW,CAAGD,CAAM,CAAGV,CAC1B,CACD,cAAErE,CAAF,EAAgBrB,GAAhB,CAAoB,KAApB,CAA2BqG,CAA3B,CACH,CACJ,CAnBD,IAmBO,IACCC,CAAAA,CAAU,CAAGX,UAAU,CAAChM,MAAM,CAACiM,gBAAP,CAAwBvE,CAAxB,EAAsCqD,KAAvC,CADxB,CAECmB,CAAW,CAAGF,UAAU,CAAChM,MAAM,CAACiM,gBAAP,CAAwBvE,CAAxB,EAAsChB,IAAvC,CAFzB,CAGCkG,CAAW,CAAGZ,UAAU,CAAChM,MAAM,CAACiM,gBAAP,CAAwB9H,CAAI,CAACwH,QAAL,CAAcC,MAAtC,EAA8Cb,KAA/C,CAHzB,CAICqB,CAAY,CAAGJ,UAAU,CAAChM,MAAM,CAACiM,gBAAP,CAAwB9H,CAAI,CAACwH,QAAL,CAAcC,MAAtC,EAA8ClF,IAA/C,CAJ1B,CAKC2F,CAAiB,CAAGL,UAAU,CAACF,CAAW,CAACzF,GAAZ,CAAgB,gBAAhB,CAAD,CAL/B,CAMCiG,CAAuB,CAAwD,CAArD,CAAAN,UAAU,CAACF,CAAW,CAACzF,GAAZ,CAAgB,qBAAhB,CAAD,CANrC,CAOCkG,CAAQ,CAAGL,CAAW,CAAIS,CAAU,CAAG,CAPxC,CAQCH,CAAM,CAAGI,CAAW,CAAGR,CAAd,CAA6BC,CAA7B,CAAiDC,CAR3D,CASCG,CAAM,CAAGL,CAAY,CAAGC,CAAf,CAAmCC,CAT7C,CAUH,GAAIC,CAAQ,EAAIC,CAAZ,EAAsBD,CAAQ,EAAIE,CAAtC,CAA8C,CAC1C,GAAIC,CAAAA,CAAW,CAAG,CAAlB,CACA,GAAIH,CAAQ,CAAIK,CAAW,CAAG,CAA9B,CAAkC,CAC9BF,CAAW,CAAGF,CAAM,CAAGG,CAC1B,CAFD,IAEO,CACHD,CAAW,CAAGD,CAAM,CAAGE,CAC1B,CACD,cAAEjF,CAAF,EAAgBrB,GAAhB,CAAoB,MAApB,CAA4BqG,CAA5B,CACH,CACJ,CACJ,CA1FoB,CA4FjBG,CAAU,CAAG,cAAE,sCAAF,CA5FI,CA6FrB,GAAIA,CAAU,CAAC3L,MAAf,CAAuB,CACnB6B,CAAM,CAAG8J,CACZ,CACD,KAAKtF,iBAAL,CAAyB,GAAIC,UAAJ,CAAWzE,CAAX,CAAmBe,CAAO,CAAC,CAAD,CAA1B,CAA+BvE,CAA/B,CAAzB,CAEA,MAAO,KACV,C,0DAUgBsD,C,CAAY,CACzB,GAAIA,CAAU,CAACiK,QAAf,CAAyB,CACrB,KAAK1H,iBAAL,CAAuBoD,WAAvB,IACA,GAAIsE,CAAAA,CAAQ,CAAG,cAAE,yCAAF,CAAf,CAEA,GAAIjK,CAAU,CAACsD,MAAf,CAAuB,CACnB,GAA+B,QAA3B,GAAAtD,CAAU,CAACoB,WAAf,CAAyC,CACrCpB,CAAU,CAACmB,QAAX,CAAoBwC,MAApB,CAA2BsG,CAA3B,CACH,CAFD,IAEO,CACHA,CAAQ,CAACC,WAAT,CAAqBlK,CAAU,CAACmB,QAAhC,CACH,CACJ,CAND,IAMO,CACH,cAAE,MAAF,EAAUwC,MAAV,CAAiBsG,CAAjB,CACH,CAED,GAAI,KAAKhK,qBAAL,CAA2BD,CAA3B,CAAJ,CAA4C,IAGpCgK,CAAAA,CAAU,CAAG,cAAE,gDAAF,CAHuB,CAKpC9H,CAAU,CAAG,KAAK/B,aAAL,CAAmBH,CAAnB,CALuB,CAOpCmK,CAAM,CAAG,EAP2B,CASpCC,CAAS,CAAGlI,CATwB,CAUxC,GAAIiI,CAAJ,CAAY,CACRC,CAAS,CAAG,cAAE,MAAF,CACf,CAEDJ,CAAU,CAACxG,GAAX,CAAe,CACX0E,KAAK,CAAEhG,CAAU,CAACmI,UAAX,GAA0BF,CAA1B,CAAmCA,CAD/B,CAEXxC,MAAM,CAAEzF,CAAU,CAACoI,WAAX,GAA2BH,CAA3B,CAAoCA,CAFjC,CAGXtG,IAAI,CAAE3B,CAAU,CAACsC,MAAX,GAAoBX,IAApB,CAA2BsG,CAHtB,CAIXvG,GAAG,CAAE1B,CAAU,CAACsC,MAAX,GAAoBZ,GAApB,CAA0BuG,CAJpB,CAKXI,eAAe,CAAE,KAAKC,kCAAL,CAAwCJ,CAAxC,CALN,CAAf,EAQA,GAAIlI,CAAU,CAACsC,MAAX,GAAoBX,IAApB,CAA2BsG,CAA/B,CAAuC,CACnCH,CAAU,CAACxG,GAAX,CAAe,CACX0E,KAAK,CAAEhG,CAAU,CAACmI,UAAX,GAA0BnI,CAAU,CAACsC,MAAX,GAAoBX,IAA9C,CAAqDsG,CADjD,CAEXtG,IAAI,CAAE3B,CAAU,CAACsC,MAAX,GAAoBX,IAFf,CAAf,CAIH,CAED,GAAI3B,CAAU,CAACsC,MAAX,GAAoBZ,GAApB,CAA0BuG,CAA9B,CAAsC,CAClCH,CAAU,CAACxG,GAAX,CAAe,CACXmE,MAAM,CAAEzF,CAAU,CAACoI,WAAX,GAA2BpI,CAAU,CAACsC,MAAX,GAAoBZ,GAA/C,CAAqDuG,CADlD,CAEXvG,GAAG,CAAE1B,CAAU,CAACsC,MAAX,GAAoBZ,GAFd,CAAf,CAIH,CAED,GAAI6G,CAAAA,CAAY,CAAGvI,CAAU,CAACsB,GAAX,CAAe,cAAf,CAAnB,CACA,GAAIiH,CAAY,EAAIA,CAAY,GAAK,cAAE,MAAF,EAAUjH,GAAV,CAAc,cAAd,CAArC,CAAoE,CAChEwG,CAAU,CAACxG,GAAX,CAAe,cAAf,CAA+BiH,CAA/B,CACH,CAED,GAAIC,CAAAA,CAAc,CAAG,KAAKC,iBAAL,CAAuBzI,CAAvB,CAArB,CACA,GAAuB,OAAnB,GAAAwI,CAAJ,CAAgC,CAC5BV,CAAU,CAACxG,GAAX,CAAe,KAAf,CAAsB,CAAtB,CACH,CAFD,IAEO,IAAuB,UAAnB,GAAAkH,CAAJ,CAAmC,CACtCV,CAAU,CAACxG,GAAX,CAAe,UAAf,CAA2B,OAA3B,CACH,CAED,GAAIoH,CAAAA,CAAK,CAAGZ,CAAU,CAAC7G,KAAX,EAAZ,CACAyH,CAAK,CAACpH,GAAN,CAAU,CACN+G,eAAe,CAAEN,CAAQ,CAACzG,GAAT,CAAa,iBAAb,CADX,CAENqH,OAAO,CAAEZ,CAAQ,CAACzG,GAAT,CAAa,SAAb,CAFH,CAAV,EAIAoH,CAAK,CAAC5H,IAAN,CAAW,gBAAX,CAA6B,uBAA7B,EAEA,GAAIhD,CAAU,CAACsD,MAAf,CAAuB,CACnB,GAA+B,QAA3B,GAAAtD,CAAU,CAACoB,WAAf,CAAyC,CACrCpB,CAAU,CAACmB,QAAX,CAAoBwC,MAApB,CAA2BqG,CAA3B,CACH,CAFD,IAEO,CACHY,CAAK,CAACV,WAAN,CAAkBlK,CAAU,CAACmB,QAA7B,EACA6I,CAAU,CAACE,WAAX,CAAuBlK,CAAU,CAACmB,QAAlC,CACH,CACJ,CAPD,IAOO,CACH,cAAE,MAAF,EAAUwC,MAAV,CAAiBiH,CAAjB,EACA,cAAE,MAAF,EAAUjH,MAAV,CAAiBqG,CAAjB,CACH,CAID9H,CAAU,CAACc,IAAX,CAAgB,gBAAhB,CAAkC,eAAlC,EAEA,GAAIhD,CAAU,CAACsD,MAAf,CAAuB,CACnB2G,CAAQ,CAACzG,GAAT,CAAa,QAAb,CAAuBxD,CAAU,CAACsD,MAAlC,EACA0G,CAAU,CAACxG,GAAX,CAAe,QAAf,CAAyBxD,CAAU,CAACsD,MAAX,CAAoB,CAA7C,EACApB,CAAU,CAACsB,GAAX,CAAe,QAAf,CAAyBxD,CAAU,CAACsD,MAAX,CAAoB,CAA7C,CACH,CAEDsH,CAAK,CAACrD,OAAN,CAAc,MAAd,CAAsB,UAAW,CAC7B,cAAE,IAAF,EAAQF,MAAR,EACH,CAFD,CAGH,CACJ,CACD,MAAO,KACV,C,wDASeyD,C,CAAM,CAClBA,CAAI,CAAG,cAAEA,CAAF,CAAP,CACA,MAAOA,CAAI,CAACzM,MAAL,EAAeyM,CAAI,CAAC,CAAD,CAAJ,GAAYpH,QAAlC,CAA4C,CAIxC,GAAIqH,CAAAA,CAAQ,CAAGD,CAAI,CAACtH,GAAL,CAAS,UAAT,CAAf,CACA,GAAiB,UAAb,GAAAuH,CAAQ,EAAgC,UAAb,GAAAA,CAA3B,EAAmE,OAAb,GAAAA,CAA1D,CAAgF,CAK5E,GAAIC,CAAAA,CAAK,CAAG9L,QAAQ,CAAC4L,CAAI,CAACtH,GAAL,CAAS,QAAT,CAAD,CAAqB,EAArB,CAApB,CACA,GAAI,CAACyH,KAAK,CAACD,CAAD,CAAN,EAA2B,CAAV,GAAAA,CAArB,CAAkC,CAC9B,MAAOA,CAAAA,CACV,CACJ,CACDF,CAAI,CAAGA,CAAI,CAACI,MAAL,EACV,CAED,MAAO,EACV,C,8FASkCJ,C,CAAM,CAErC,GAAIK,CAAAA,CAAQ,CAAG,cAAE,OAAF,EAAW3N,IAAX,EAAf,CACA,cAAE,MAAF,EAAUmG,MAAV,CAAiBwH,CAAjB,EACA,GAAIC,CAAAA,CAAa,CAAGD,CAAQ,CAAC3H,GAAT,CAAa,iBAAb,CAApB,CACA2H,CAAQ,CAAC9D,MAAT,GAEAyD,CAAI,CAAG,cAAEA,CAAF,CAAP,CACA,MAAOA,CAAI,CAACzM,MAAL,EAAeyM,CAAI,CAAC,CAAD,CAAJ,GAAYpH,QAAlC,CAA4C,CACxC,GAAI2H,CAAAA,CAAK,CAAGP,CAAI,CAACtH,GAAL,CAAS,iBAAT,CAAZ,CACA,GAAI6H,CAAK,GAAKD,CAAd,CAA6B,CACzB,MAAOC,CAAAA,CACV,CACDP,CAAI,CAAGA,CAAI,CAACI,MAAL,EACV,CAED,MAAO,KACV,C,4DASiBJ,C,CAAM,CACpBA,CAAI,CAAG,cAAEA,CAAF,CAAP,CACA,MAAOA,CAAI,CAACzM,MAAL,EAAeyM,CAAI,CAAC,CAAD,CAAJ,GAAYpH,QAAlC,CAA4C,CACxC,GAAIqH,CAAAA,CAAQ,CAAGD,CAAI,CAACtH,GAAL,CAAS,UAAT,CAAf,CACA,GAAiB,QAAb,GAAAuH,CAAJ,CAA2B,CACvB,MAAOA,CAAAA,CACV,CACDD,CAAI,CAAGA,CAAI,CAACI,MAAL,EACV,CAED,MAAO,KACV,C,6DASmB,IAEZI,CAAAA,CAAQ,CAAG,aAFC,CAGZC,CAAY,CAAG,SAASC,CAAT,CAAgB,CAC/B,GAAIC,CAAAA,CAAa,CAAGD,CAAK,CAAClK,IAAN,CAAW,WAAX,CAApB,CACA,GAAImK,CAAJ,CAAmB,CACf,OAAQA,CAAR,EACI,IAAK,WAAL,CACA,IAAK,QAAL,CACI,OAHR,CAKH,CAED,GAAIC,CAAAA,CAAM,CAAGF,CAAK,CAACxI,IAAN,CAAWsI,CAAX,CAAb,CACA,GAAI,CAACI,CAAL,CAAa,CACTF,CAAK,CAACxI,IAAN,uBACAwI,CAAK,CAACxI,IAAN,CAAWsI,CAAX,IACH,CACJ,CAlBe,CAoBhB,KAAK1J,eAAL,CAAqB+J,QAArB,GAAgCvF,IAAhC,CAAqC,SAASF,CAAT,CAAgBvE,CAAhB,CAAsB,CACvD4J,CAAY,CAAC,cAAE5J,CAAF,CAAD,CACf,CAFD,EAGA,KAAKC,eAAL,CAAqBgK,YAArB,CAAkC,MAAlC,EAA0CD,QAA1C,GAAqDvF,IAArD,CAA0D,SAASF,CAAT,CAAgBvE,CAAhB,CAAsB,CAC5E4J,CAAY,CAAC,cAAE5J,CAAF,CAAD,CACf,CAFD,CAGH,C,6DASmB,IAGZkK,CAAAA,CAAY,CAAG,SAASL,CAAT,CAAgB,CAC/B,GAAIE,CAAAA,CAAM,CAAGF,CAAK,CAACxI,IAAN,mBAAb,CACA,GAAsB,WAAlB,QAAO0I,CAAAA,CAAX,CAAmC,CAC/BF,CAAK,CAAClE,UAAN,oBACAkE,CAAK,CAAClE,UAAN,CALO,aAKP,CACH,CACJ,CATe,CAWhB,mCAA2BlB,IAA3B,CAAgC,SAASF,CAAT,CAAgBvE,CAAhB,CAAsB,CAClDkK,CAAY,CAAC,cAAElK,CAAF,CAAD,CACf,CAFD,CAGH,C","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 * Manage user tours in Moodle.\n *\n * @copyright 2018 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport Popper from 'core/popper';\n\n/**\n * A Tour.\n *\n * @class Tour\n */\nexport default class Tour {\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 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 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 {Integer} 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 {Integer} 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 {Integer} stepNumber The current step number\n * @return {Integer} 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 {Integer} stepNumber The current step number\n * @return {Integer} 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 {Integer} 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 the step the first step number?\n *\n * @method isFirstStep\n * @param {Integer} stepNumber Step number to test\n * @return {Boolean} Whether the step is the first step\n */\n isFirstStep(stepNumber) {\n let previousStepNumber = this.getPreviousStepNumber(stepNumber);\n\n return previousStepNumber === 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 * 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 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 * 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 {Integer} stepNumber The step number to display\n * @param {Integer} direction Next or previous step\n * @chainable\n * @return {Object} this.\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 if (typeof stepConfig.delay !== 'undefined' && stepConfig.delay && !stepConfig.delayed) {\n stepConfig.delayed = true;\n window.setTimeout(this._gotoStep.bind(this), stepConfig.delay, stepConfig, direction);\n\n return this;\n } else if (!stepConfig.orphan && !this.isStepActuallyVisible(stepConfig)) {\n let fn = direction == -1 ? 'getPreviousStepNumber' : 'getNextStepNumber';\n return this.gotoStep(this[fn](stepConfig.stepNumber), direction);\n }\n\n this.hide();\n\n this.fireEventHandlers('beforeRender', stepConfig);\n this.renderStep(stepConfig);\n this.fireEventHandlers('afterRender', stepConfig);\n\n return this;\n }\n\n /**\n * Fetch the normalised step configuration for the specified step number.\n *\n * @method getStepConfig\n * @param {Integer} 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 to handle\n * @param {Object} data Any data to pass to the event\n * @chainable\n * @return {Object} this.\n */\n fireEventHandlers(eventName, data) {\n if (typeof this.eventHandlers[eventName] === 'undefined') {\n return this;\n }\n\n this.eventHandlers[eventName].forEach(function(thisEvent) {\n thisEvent.call(this, data);\n }, this);\n\n return this;\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/Previous buttons.\n {\n node: this.currentStepNode,\n args: ['click', '[data-role=\"next\"]', $.proxy(this.next, this)]\n }, {\n node: this.currentStepNode,\n args: ['click', '[data-role=\"previous\"]', $.proxy(this.previous, 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 // Is this the first step?\n if (this.isFirstStep(stepConfig.stepNumber)) {\n template.find('[data-role=\"previous\"]').prop('disabled', true);\n } else {\n template.find('[data-role=\"previous\"]').prop('disabled', false);\n }\n\n // Is this the final step?\n if (this.isLastStep(stepConfig.stepNumber)) {\n template.find('[data-role=\"next\"]').prop('disabled', true);\n } else {\n template.find('[data-role=\"next\"]').prop('disabled', false);\n }\n\n template.find('[data-role=\"previous\"]').attr('role', 'button');\n template.find('[data-role=\"next\"]').attr('role', 'button');\n template.find('[data-role=\"end\"]').attr('role', 'button');\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\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 let zIndex = this.calculateZIndex(targetNode);\n if (zIndex) {\n stepConfig.zIndex = zIndex + 1;\n }\n\n if (stepConfig.zIndex) {\n currentStepNode.css('zIndex', stepConfig.zIndex + 1);\n }\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 animationTarget\n .animate({\n scrollTop: this.calculateScrollTop(stepConfig),\n }).promise().then(function() {\n this.positionStep(stepConfig);\n this.revealStep(stepConfig);\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.offset(this.calculateStepPositionInPage());\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 }\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 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 }, 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 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 {Integer} startAt Which step number to start at. If not specified, starts at the last point.\n * @chainable\n * @return {Object} this.\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 this.fireEventHandlers('beforeStart', startAt);\n this.gotoStep(startAt);\n this.fireEventHandlers('afterStart', startAt);\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 */\n endTour() {\n this.fireEventHandlers('beforeEnd');\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.focus();\n }\n }\n\n this.hide(true);\n\n this.fireEventHandlers('afterEnd');\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 */\n hide(transition) {\n this.fireEventHandlers('beforeHide');\n\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 }\n }\n\n // Clear the step configuration.\n this.currentStepConfig = null;\n }\n\n let fadeTime = 0;\n if (transition) {\n fadeTime = 400;\n }\n\n // Remove the backdrop features.\n $('[data-flexitour=\"step-background\"]').remove();\n $('[data-flexitour=\"step-backdrop\"]').removeAttr('data-flexitour');\n $('[data-flexitour=\"backdrop\"]').fadeOut(fadeTime, function() {\n $(this).remove();\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.fireEventHandlers('afterHide');\n\n this.currentStepNode = null;\n this.currentStepPopper = null;\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 * 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 scrollTop = $(window).scrollTop();\n let viewportHeight = $(window).height();\n let targetNode = this.getStepTarget(stepConfig);\n\n 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() - (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 * @method calculateScrollTop\n * @return {Number}\n */\n calculateStepPositionInPage() {\n let viewportHeight = $(window).height();\n let stepHeight = this.currentStepNode.height();\n\n let viewportWidth = $(window).width();\n let stepWidth = this.currentStepNode.width();\n\n return {\n top: Math.ceil((viewportHeight - stepHeight) / 2),\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 if (!content || !content.length) {\n // Unable to find the step node.\n return this;\n }\n\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 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 },\n onCreate: function(data) {\n recalculateArrowPosition(data);\n },\n onUpdate: function(data) {\n recalculateArrowPosition(data);\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 let background = $('[data-flexitour=\"step-background\"]');\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 * 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 let backdrop = $('
');\n\n if (stepConfig.zIndex) {\n if (stepConfig.attachPoint === 'append') {\n stepConfig.attachTo.append(backdrop);\n } else {\n backdrop.insertAfter(stepConfig.attachTo);\n }\n } else {\n $('body').append(backdrop);\n }\n\n if (this.isStepActuallyVisible(stepConfig)) {\n // The step has a visible target.\n // Punch a hole through the backdrop.\n let background = $('
');\n\n let targetNode = this.getStepTarget(stepConfig);\n\n let buffer = 10;\n\n let colorNode = targetNode;\n if (buffer) {\n colorNode = $('body');\n }\n\n background.css({\n width: targetNode.outerWidth() + buffer + buffer,\n height: targetNode.outerHeight() + buffer + buffer,\n left: targetNode.offset().left - buffer,\n top: targetNode.offset().top - buffer,\n backgroundColor: this.calculateInherittedBackgroundColor(colorNode),\n });\n\n if (targetNode.offset().left < buffer) {\n background.css({\n width: targetNode.outerWidth() + targetNode.offset().left + buffer,\n left: targetNode.offset().left,\n });\n }\n\n if (targetNode.offset().top < buffer) {\n background.css({\n height: targetNode.outerHeight() + targetNode.offset().top + buffer,\n top: targetNode.offset().top,\n });\n }\n\n let targetRadius = targetNode.css('borderRadius');\n if (targetRadius && targetRadius !== $('body').css('borderRadius')) {\n background.css('borderRadius', targetRadius);\n }\n\n let targetPosition = this.calculatePosition(targetNode);\n if (targetPosition === 'fixed') {\n background.css('top', 0);\n } else if (targetPosition === 'absolute') {\n background.css('position', 'fixed');\n }\n\n let fader = background.clone();\n fader.css({\n backgroundColor: backdrop.css('backgroundColor'),\n opacity: backdrop.css('opacity'),\n });\n fader.attr('data-flexitour', 'step-background-fader');\n\n if (stepConfig.zIndex) {\n if (stepConfig.attachPoint === 'append') {\n stepConfig.attachTo.append(background);\n } else {\n fader.insertAfter(stepConfig.attachTo);\n background.insertAfter(stepConfig.attachTo);\n }\n } else {\n $('body').append(fader);\n $('body').append(background);\n }\n\n // Add the backdrop data to the actual target.\n // This is the part which actually does the work.\n targetNode.attr('data-flexitour', 'step-backdrop');\n\n if (stepConfig.zIndex) {\n backdrop.css('zIndex', stepConfig.zIndex);\n background.css('zIndex', stepConfig.zIndex + 1);\n targetNode.css('zIndex', stepConfig.zIndex + 2);\n }\n\n fader.fadeOut('2000', function() {\n $(this).remove();\n });\n }\n }\n return this;\n }\n\n /**\n * Calculate the inheritted z-index.\n *\n * @method calculateZIndex\n * @param {jQuery} elem The element to calculate z-index for\n * @return {Number} Calculated z-index\n */\n calculateZIndex(elem) {\n elem = $(elem);\n while (elem.length && elem[0] !== document) {\n // Ignore z-index if position is set to a value where z-index is ignored by the browser\n // This makes behavior of this function consistent across browsers\n // WebKit always returns auto if the element is positioned.\n let position = elem.css(\"position\");\n if (position === \"absolute\" || position === \"relative\" || position === \"fixed\") {\n // IE returns 0 when zIndex is not specified\n // other browsers return a string\n // we ignore the case of nested elements with an explicit value of 0\n //
\n let value = parseInt(elem.css(\"zIndex\"), 10);\n if (!isNaN(value) && value !== 0) {\n return value;\n }\n }\n elem = elem.parent();\n }\n\n return 0;\n }\n\n /**\n * Calculate the inheritted background colour.\n *\n * @method calculateInherittedBackgroundColor\n * @param {jQuery} elem The element to calculate colour for\n * @return {String} Calculated background colour\n */\n calculateInherittedBackgroundColor(elem) {\n // Use a fake node to compare each element against.\n let fakeNode = $('
').hide();\n $('body').append(fakeNode);\n let fakeElemColor = fakeNode.css('backgroundColor');\n fakeNode.remove();\n\n elem = $(elem);\n while (elem.length && elem[0] !== document) {\n let color = elem.css('backgroundColor');\n if (color !== fakeElemColor) {\n return color;\n }\n elem = elem.parent();\n }\n\n return null;\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 child.attr(attrName, true);\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 attrName = 'aria-hidden';\n let showFunction = function(child) {\n let hidden = child.attr(stateHolder);\n if (typeof hidden !== 'undefined') {\n child.removeAttr(stateHolder);\n child.removeAttr(attrName);\n }\n };\n\n $('[' + stateHolder + ']').each(function(index, node) {\n showFunction($(node));\n });\n }\n}\n"],"file":"tour.min.js"} \ No newline at end of file diff --git a/admin/tool/usertours/amd/readme_moodle.txt b/admin/tool/usertours/amd/readme_moodle.txt deleted file mode 100644 index 1fb69a323ab..00000000000 --- a/admin/tool/usertours/amd/readme_moodle.txt +++ /dev/null @@ -1,10 +0,0 @@ -Description of External library imports into Moodle - -Flexitour Instructions ----------------------- -1. Clone https://github.com/andrewnicols/flexitour into an unrelated directory -2. Copy /build/tour.js to amd/src/tour.js -3. Open the amd/src/tour.js file and find the AMD module define. -4. Change the "popper" inclusion to "core/popper" -5. Update thirdpartylibs.xml -6. Run `grunt amd` diff --git a/admin/tool/usertours/amd/src/tour.js b/admin/tool/usertours/amd/src/tour.js index 65e48a70bdf..0f9ad947c62 100644 --- a/admin/tool/usertours/amd/src/tour.js +++ b/admin/tool/usertours/amd/src/tour.js @@ -1,1563 +1,1534 @@ -// jshint ignore: start -(function (root, factory) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module unless amdModuleId is set - define(["jquery","core/popper"], function (a0,b1) { - return (root['Tour'] = factory(a0,b1)); - }); - } else if (typeof module === 'object' && module.exports) { - // Node. Does not work with strict CommonJS, but - // only CommonJS-like environments that support module.exports, - // like Node. - module.exports = factory(require("jquery"),require("popper.js")); - } else { - root['Tour'] = factory(root["$"],root["Popper"]); - } -}(this, function ($, Popper) { +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . -"use strict"; +/** + * Manage user tours in Moodle. + * + * @copyright 2018 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import $ from 'jquery'; +import Popper from 'core/popper'; /** * A Tour. * - * @class Tour - * @param {object} config The configuration object. + * @class Tour */ - -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; - -function Tour(config) { - this.init(config); -} - -/** - * The name of the tour. - * - * @property {String} tourName - */ -Tour.prototype.tourName; - -/** - * The name of the tour storage key. - * - * @property {String} storageKey - */ -Tour.prototype.storageKey; - -/** - * The session storage object - * - * @property {Storage} storage - */ -Tour.prototype.storage; - -/** - * The original configuration as passed into the constructor. - * - * @property {Object} originalConfiguration - */ -Tour.prototype.originalConfiguration; - -/** - * The list of step listeners. - * - * @property {Array} listeners - */ -Tour.prototype.listeners; - -/** - * The list of event handlers. - * - * @property {Object} eventHandlers - */ -Tour.prototype.eventHandlers; - -/** - * The list of steps. - * - * @property {Object[]} steps - */ -Tour.prototype.steps; - -/** - * The current step node. - * - * @property {jQuery} currentStepNode - */ -Tour.prototype.currentStepNode; - -/** - * The current step number. - * - * @property {Number} currentStepNumber - */ -Tour.prototype.currentStepNumber; - -/** - * The popper for the current step. - * - * @property {Popper} currentStepPopper - */ -Tour.prototype.currentStepPopper; - -/** - * The config for the current step. - * - * @property {Object} currentStepConfig - */ -Tour.prototype.currentStepConfig; - -/** - * The template content. - * - * @property {String} templateContent - */ -Tour.prototype.templateContent; - -/** - * Initialise the tour. - * - * @method init - * @param {Object} config The configuration object. - * @chainable - */ -Tour.prototype.init = function (config) { - // Unset all handlers. - this.eventHandlers = {}; - - // Reset the current tour states. - this.reset(); - - // Store the initial configuration. - this.originalConfiguration = config || {}; - - // Apply configuration. - this.configure.apply(this, arguments); - - try { - this.storage = window.sessionStorage; - this.storageKey = 'tourstate_' + this.tourName; - } catch (e) { - this.storage = false; - this.storageKey = ''; +export default class Tour { + /** + * @param {object} config The configuration object. + */ + constructor(config) { + this.init(config); } - return this; -}; + /** + * Initialise the tour. + * + * @method init + * @param {Object} config The configuration object. + * @chainable + * @return {Object} this. + */ + init(config) { + // Unset all handlers. + this.eventHandlers = {}; -/** - * Reset the current tour state. - * - * @method reset - * @chainable - */ -Tour.prototype.reset = function () { - // Hide the current step. - this.hide(); + // Reset the current tour states. + this.reset(); - // Unset all handlers. - this.eventHandlers = []; + // Store the initial configuration. + this.originalConfiguration = config || {}; - // Unset all listeners. - this.resetStepListeners(); + // Apply configuration. + this.configure.apply(this, arguments); - // Unset the original configuration. - this.originalConfiguration = {}; - - // Reset the current step number and list of steps. - this.steps = []; - - // Reset the current step number. - this.currentStepNumber = 0; - - return this; -}; - -/** - * Prepare tour configuration. - * - * @method configure - * @chainable - */ -Tour.prototype.configure = function (config) { - var _this = this; - - if ((typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object') { - // Tour name. - if (typeof config.tourName !== 'undefined') { - this.tourName = config.tourName; - } - - // Set up eventHandlers. - if (config.eventHandlers) { - (function () { - var eventName = void 0; - for (eventName in config.eventHandlers) { - config.eventHandlers[eventName].forEach(function (handler) { - this.addEventHandler(eventName, handler); - }, _this); - } - })(); - } - - // Reset the step configuration. - this.resetStepDefaults(true); - - // Configure the steps. - if (_typeof(config.steps) === 'object') { - this.steps = config.steps; - } - - if (typeof config.template !== 'undefined') { - this.templateContent = config.template; - } - } - - // Check that we have enough to start the tour. - this.checkMinimumRequirements(); - - return this; -}; - -/** - * Check that the configuration meets the minimum requirements. - * - * @method checkMinimumRequirements - * @chainable - */ -Tour.prototype.checkMinimumRequirements = function () { - // Need a tourName. - if (!this.tourName) { - throw new Error("Tour Name required"); - } - - // Need a minimum of one step. - if (!this.steps || !this.steps.length) { - throw new Error("Steps must be specified"); - } -}; - -/** - * Reset step default configuration. - * - * @method resetStepDefaults - * @param {Boolean} loadOriginalConfiguration Whether to load the original configuration supplied with the Tour. - * @chainable - */ -Tour.prototype.resetStepDefaults = function (loadOriginalConfiguration) { - if (typeof loadOriginalConfiguration === 'undefined') { - loadOriginalConfiguration = true; - } - - this.stepDefaults = {}; - if (!loadOriginalConfiguration || typeof this.originalConfiguration.stepDefaults === 'undefined') { - this.setStepDefaults({}); - } else { - this.setStepDefaults(this.originalConfiguration.stepDefaults); - } - - return this; -}; - -/** - * Set the step defaults. - * - * @method setStepDefaults - * @param {Object} stepDefaults The step defaults to apply to all steps - * @chainable - */ -Tour.prototype.setStepDefaults = function (stepDefaults) { - if (!this.stepDefaults) { - this.stepDefaults = {}; - } - $.extend(this.stepDefaults, { - element: '', - placement: 'top', - delay: 0, - moveOnClick: false, - moveAfterTime: 0, - orphan: false, - direction: 1 - }, stepDefaults); - - return this; -}; - -/** - * Retrieve the current step number. - * - * @method getCurrentStepNumber - * @return {Integer} The current step number - */ -Tour.prototype.getCurrentStepNumber = function () { - return parseInt(this.currentStepNumber, 10); -}; - -/** - * Store the current step number. - * - * @method setCurrentStepNumber - * @param {Integer} stepNumber The current step number - * @chainable - */ -Tour.prototype.setCurrentStepNumber = function (stepNumber) { - this.currentStepNumber = stepNumber; - if (this.storage) { try { - this.storage.setItem(this.storageKey, stepNumber); + this.storage = window.sessionStorage; + this.storageKey = 'tourstate_' + this.tourName; } catch (e) { - if (e.code === DOMException.QUOTA_EXCEEDED_ERR) { - this.storage.removeItem(this.storageKey); + this.storage = false; + this.storageKey = ''; + } + + return this; + } + + /** + * Reset the current tour state. + * + * @method reset + * @chainable + * @return {Object} this. + */ + reset() { + // Hide the current step. + this.hide(); + + // Unset all handlers. + this.eventHandlers = []; + + // Unset all listeners. + this.resetStepListeners(); + + // Unset the original configuration. + this.originalConfiguration = {}; + + // Reset the current step number and list of steps. + this.steps = []; + + // Reset the current step number. + this.currentStepNumber = 0; + + return this; + } + + /** + * Prepare tour configuration. + * + * @method configure + * @param {Object} config The configuration object. + * @chainable + * @return {Object} this. + */ + configure(config) { + if (typeof config === 'object') { + // Tour name. + if (typeof config.tourName !== 'undefined') { + this.tourName = config.tourName; + } + + // Set up eventHandlers. + if (config.eventHandlers) { + for (let eventName in config.eventHandlers) { + config.eventHandlers[eventName].forEach(function(handler) { + this.addEventHandler(eventName, handler); + }, this); + } + } + + // Reset the step configuration. + this.resetStepDefaults(true); + + // Configure the steps. + if (typeof config.steps === 'object') { + this.steps = config.steps; + } + + if (typeof config.template !== 'undefined') { + this.templateContent = config.template; + } + } + + // Check that we have enough to start the tour. + this.checkMinimumRequirements(); + + return this; + } + + /** + * Check that the configuration meets the minimum requirements. + * + * @method checkMinimumRequirements + */ + checkMinimumRequirements() { + // Need a tourName. + if (!this.tourName) { + throw new Error("Tour Name required"); + } + + // Need a minimum of one step. + if (!this.steps || !this.steps.length) { + throw new Error("Steps must be specified"); + } + } + + /** + * Reset step default configuration. + * + * @method resetStepDefaults + * @param {Boolean} loadOriginalConfiguration Whether to load the original configuration supplied with the Tour. + * @chainable + * @return {Object} this. + */ + resetStepDefaults(loadOriginalConfiguration) { + if (typeof loadOriginalConfiguration === 'undefined') { + loadOriginalConfiguration = true; + } + + this.stepDefaults = {}; + if (!loadOriginalConfiguration || typeof this.originalConfiguration.stepDefaults === 'undefined') { + this.setStepDefaults({}); + } else { + this.setStepDefaults(this.originalConfiguration.stepDefaults); + } + + return this; + } + + /** + * Set the step defaults. + * + * @method setStepDefaults + * @param {Object} stepDefaults The step defaults to apply to all steps + * @chainable + * @return {Object} this. + */ + setStepDefaults(stepDefaults) { + if (!this.stepDefaults) { + this.stepDefaults = {}; + } + $.extend( + this.stepDefaults, + { + element: '', + placement: 'top', + delay: 0, + moveOnClick: false, + moveAfterTime: 0, + orphan: false, + direction: 1, + }, + stepDefaults + ); + + return this; + } + + /** + * Retrieve the current step number. + * + * @method getCurrentStepNumber + * @return {Integer} The current step number + */ + getCurrentStepNumber() { + return parseInt(this.currentStepNumber, 10); + } + + /** + * Store the current step number. + * + * @method setCurrentStepNumber + * @param {Integer} stepNumber The current step number + * @chainable + */ + setCurrentStepNumber(stepNumber) { + this.currentStepNumber = stepNumber; + if (this.storage) { + try { + this.storage.setItem(this.storageKey, stepNumber); + } catch (e) { + if (e.code === DOMException.QUOTA_EXCEEDED_ERR) { + this.storage.removeItem(this.storageKey); + } } } } -}; -/** - * Get the next step number after the currently displayed step. - * - * @method getNextStepNumber - * @return {Integer} The next step number to display - */ -Tour.prototype.getNextStepNumber = function (stepNumber) { - if (typeof stepNumber === 'undefined') { - stepNumber = this.getCurrentStepNumber(); - } - var nextStepNumber = stepNumber + 1; - - // Keep checking the remaining steps. - while (nextStepNumber <= this.steps.length) { - if (this.isStepPotentiallyVisible(this.getStepConfig(nextStepNumber))) { - return nextStepNumber; + /** + * Get the next step number after the currently displayed step. + * + * @method getNextStepNumber + * @param {Integer} stepNumber The current step number + * @return {Integer} The next step number to display + */ + getNextStepNumber(stepNumber) { + if (typeof stepNumber === 'undefined') { + stepNumber = this.getCurrentStepNumber(); } - nextStepNumber++; - } + let nextStepNumber = stepNumber + 1; - return null; -}; - -/** - * Get the previous step number before the currently displayed step. - * - * @method getPreviousStepNumber - * @return {Integer} The previous step number to display - */ -Tour.prototype.getPreviousStepNumber = function (stepNumber) { - if (typeof stepNumber === 'undefined') { - stepNumber = this.getCurrentStepNumber(); - } - var previousStepNumber = stepNumber - 1; - - // Keep checking the remaining steps. - while (previousStepNumber >= 0) { - if (this.isStepPotentiallyVisible(this.getStepConfig(previousStepNumber))) { - return previousStepNumber; + // Keep checking the remaining steps. + while (nextStepNumber <= this.steps.length) { + if (this.isStepPotentiallyVisible(this.getStepConfig(nextStepNumber))) { + return nextStepNumber; + } + nextStepNumber++; } - previousStepNumber--; - } - return null; -}; - -/** - * Is the step the final step number? - * - * @method isLastStep - * @param {Integer} stepNumber Step number to test - * @return {Boolean} Whether the step is the final step - */ -Tour.prototype.isLastStep = function (stepNumber) { - var nextStepNumber = this.getNextStepNumber(stepNumber); - - return nextStepNumber === null; -}; - -/** - * Is the step the first step number? - * - * @method isFirstStep - * @param {Integer} stepNumber Step number to test - * @return {Boolean} Whether the step is the first step - */ -Tour.prototype.isFirstStep = function (stepNumber) { - var previousStepNumber = this.getPreviousStepNumber(stepNumber); - - return previousStepNumber === null; -}; - -/** - * Is this step potentially visible? - * - * @method isStepPotentiallyVisible - * @param {Integer} stepNumber Step number to test - * @return {Boolean} Whether the step is the potentially visible - */ -Tour.prototype.isStepPotentiallyVisible = function (stepConfig) { - if (!stepConfig) { - // Without step config, there can be no step. - return false; - } - - if (this.isStepActuallyVisible(stepConfig)) { - // If it is actually visible, it is already potentially visible. - return true; - } - - if (typeof stepConfig.orphan !== 'undefined' && stepConfig.orphan) { - // Orphan steps have no target. They are always visible. - return true; - } - - if (typeof stepConfig.delay !== 'undefined' && stepConfig.delay) { - // Only return true if the activated has not been used yet. - return true; - } - - // Not theoretically, or actually visible. - return false; -}; - -/** - * Is this step actually visible? - * - * @method isStepActuallyVisible - * @param {Integer} stepNumber Step number to test - * @return {Boolean} Whether the step is actually visible - */ -Tour.prototype.isStepActuallyVisible = function (stepConfig) { - if (!stepConfig) { - // Without step config, there can be no step. - return false; - } - - var target = this.getStepTarget(stepConfig); - if (target && target.length && target.is(':visible')) { - // Without a target, there can be no step. - return !!target.length; - } - - return false; -}; - -/** - * Go to the next step in the tour. - * - * @method next - * @chainable - */ -Tour.prototype.next = function () { - return this.gotoStep(this.getNextStepNumber()); -}; - -/** - * Go to the previous step in the tour. - * - * @method previous - * @chainable - */ -Tour.prototype.previous = function () { - return this.gotoStep(this.getPreviousStepNumber(), -1); -}; - -/** - * Go to the specified step in the tour. - * - * @method gotoStep - * @param {Integer} stepNumber The step number to display - * @chainable - */ -Tour.prototype.gotoStep = function (stepNumber, direction) { - if (stepNumber < 0) { - return this.endTour(); - } - - var stepConfig = this.getStepConfig(stepNumber); - if (stepConfig === null) { - return this.endTour(); - } - - return this._gotoStep(stepConfig, direction); -}; - -Tour.prototype._gotoStep = function (stepConfig, direction) { - if (!stepConfig) { - return this.endTour(); - } - - if (typeof stepConfig.delay !== 'undefined' && stepConfig.delay && !stepConfig.delayed) { - stepConfig.delayed = true; - window.setTimeout(this._gotoStep.bind(this), stepConfig.delay, stepConfig, direction); - - return this; - } else if (!stepConfig.orphan && !this.isStepActuallyVisible(stepConfig)) { - var fn = direction == -1 ? 'getPreviousStepNumber' : 'getNextStepNumber'; - return this.gotoStep(this[fn](stepConfig.stepNumber), direction); - } - - this.hide(); - - this.fireEventHandlers('beforeRender', stepConfig); - this.renderStep(stepConfig); - this.fireEventHandlers('afterRender', stepConfig); - - return this; -}; - -/** - * Fetch the normalised step configuration for the specified step number. - * - * @method getStepConfig - * @param {Integer} stepNumber The step number to fetch configuration for - * @return {Object} The step configuration - */ -Tour.prototype.getStepConfig = function (stepNumber) { - if (stepNumber === null || stepNumber < 0 || stepNumber >= this.steps.length) { return null; } - // Normalise the step configuration. - var stepConfig = this.normalizeStepConfig(this.steps[stepNumber]); + /** + * Get the previous step number before the currently displayed step. + * + * @method getPreviousStepNumber + * @param {Integer} stepNumber The current step number + * @return {Integer} The previous step number to display + */ + getPreviousStepNumber(stepNumber) { + if (typeof stepNumber === 'undefined') { + stepNumber = this.getCurrentStepNumber(); + } + let previousStepNumber = stepNumber - 1; - // Add the stepNumber to the stepConfig. - stepConfig = $.extend(stepConfig, { stepNumber: stepNumber }); - - return stepConfig; -}; - -/** - * Normalise the supplied step configuration. - * - * @method normalizeStepConfig - * @param {Object} stepConfig The step configuration to normalise - * @return {Object} The normalised step configuration - */ -Tour.prototype.normalizeStepConfig = function (stepConfig) { - - if (typeof stepConfig.reflex !== 'undefined' && typeof stepConfig.moveAfterClick === 'undefined') { - stepConfig.moveAfterClick = stepConfig.reflex; - } - - if (typeof stepConfig.element !== 'undefined' && typeof stepConfig.target === 'undefined') { - stepConfig.target = stepConfig.element; - } - - if (typeof stepConfig.content !== 'undefined' && typeof stepConfig.body === 'undefined') { - stepConfig.body = stepConfig.content; - } - - stepConfig = $.extend({}, this.stepDefaults, stepConfig); - - stepConfig = $.extend({}, { - attachTo: stepConfig.target, - attachPoint: 'after' - }, stepConfig); - - if (stepConfig.attachTo) { - stepConfig.attachTo = $(stepConfig.attachTo).first(); - } - - return stepConfig; -}; - -/** - * Fetch the actual step target from the selector. - * - * This should not be called until after any delay has completed. - * - * @method getStepTarget - * @param {Object} stepConfig The step configuration - * @return {$} - */ -Tour.prototype.getStepTarget = function (stepConfig) { - if (stepConfig.target) { - return $(stepConfig.target); - } - - return null; -}; - -/** - * Fire any event handlers for the specified event. - * - * @param {String} eventName The name of the event to handle - * @param {Object} data Any data to pass to the event - * @chainable - */ -Tour.prototype.fireEventHandlers = function (eventName, data) { - if (typeof this.eventHandlers[eventName] === 'undefined') { - return this; - } - - this.eventHandlers[eventName].forEach(function (thisEvent) { - thisEvent.call(this, data); - }, this); - - return this; -}; - -/** - * @method addEventHandler - * @param string eventName The name of the event to listen for - * @param function handler The event handler to call - */ -Tour.prototype.addEventHandler = function (eventName, handler) { - if (typeof this.eventHandlers[eventName] === 'undefined') { - this.eventHandlers[eventName] = []; - } - - this.eventHandlers[eventName].push(handler); - - return this; -}; - -/** - * Process listeners for the step being shown. - * - * @method processStepListeners - * @param {object} stepConfig The configuration for the step - * @chainable - */ -Tour.prototype.processStepListeners = function (stepConfig) { - this.listeners.push( - // Next/Previous buttons. - { - node: this.currentStepNode, - args: ['click', '[data-role="next"]', $.proxy(this.next, this)] - }, { - node: this.currentStepNode, - args: ['click', '[data-role="previous"]', $.proxy(this.previous, this)] - }, - - // Close and end tour buttons. - { - node: this.currentStepNode, - args: ['click', '[data-role="end"]', $.proxy(this.endTour, this)] - }, - - // Click backdrop and hide tour. - { - node: $('[data-flexitour="backdrop"]'), - args: ['click', $.proxy(this.hide, this)] - }, - - // Keypresses. - { - node: $('body'), - args: ['keydown', $.proxy(this.handleKeyDown, this)] - }); - - if (stepConfig.moveOnClick) { - var targetNode = this.getStepTarget(stepConfig); - this.listeners.push({ - node: targetNode, - args: ['click', $.proxy(function (e) { - if ($(e.target).parents('[data-flexitour="container"]').length === 0) { - // Ignore clicks when they are in the flexitour. - window.setTimeout($.proxy(this.next, this), 500); - } - }, this)] - }); - } - - this.listeners.forEach(function (listener) { - listener.node.on.apply(listener.node, listener.args); - }); - - return this; -}; - -/** - * Reset step listeners. - * - * @method resetStepListeners - * @chainable - */ -Tour.prototype.resetStepListeners = function () { - // Stop listening to all external handlers. - if (this.listeners) { - this.listeners.forEach(function (listener) { - listener.node.off.apply(listener.node, listener.args); - }); - } - this.listeners = []; - - return this; -}; - -/** - * The standard step renderer. - * - * @method renderStep - * @param {Object} stepConfig The step configuration of the step - * @chainable - */ -Tour.prototype.renderStep = function (stepConfig) { - // Store the current step configuration for later. - this.currentStepConfig = stepConfig; - this.setCurrentStepNumber(stepConfig.stepNumber); - - // Fetch the template and convert it to a $ object. - var template = $(this.getTemplateContent()); - - // Title. - template.find('[data-placeholder="title"]').html(stepConfig.title); - - // Body. - template.find('[data-placeholder="body"]').html(stepConfig.body); - - // Is this the first step? - if (this.isFirstStep(stepConfig.stepNumber)) { - template.find('[data-role="previous"]').prop('disabled', true); - } else { - template.find('[data-role="previous"]').prop('disabled', false); - } - - // Is this the final step? - if (this.isLastStep(stepConfig.stepNumber)) { - template.find('[data-role="next"]').prop('disabled', true); - } else { - template.find('[data-role="next"]').prop('disabled', false); - } - - template.find('[data-role="previous"]').attr('role', 'button'); - template.find('[data-role="next"]').attr('role', 'button'); - template.find('[data-role="end"]').attr('role', 'button'); - - // Replace the template with the updated version. - stepConfig.template = template; - - // Add to the page. - this.addStepToPage(stepConfig); - - // Process step listeners after adding to the page. - // This uses the currentNode. - this.processStepListeners(stepConfig); - - return this; -}; - -/** - * Getter for the template content. - * - * @method getTemplateContent - * @return {$} - */ -Tour.prototype.getTemplateContent = function () { - return $(this.templateContent).clone(); -}; - -/** - * Helper to add a step to the page. - * - * @method addStepToPage - * @param {Object} stepConfig The step configuration of the step - * @chainable - */ -Tour.prototype.addStepToPage = function (stepConfig) { - var stepContent = stepConfig.template; - - // Create the stepNode from the template data. - var currentStepNode = $('').html(stepConfig.template).hide(); - - // The scroll animation occurs on the body or html. - var animationTarget = $('body, html').stop(true, true); - - if (this.isStepActuallyVisible(stepConfig)) { - var targetNode = this.getStepTarget(stepConfig); - - targetNode.data('flexitour', 'target'); - - var zIndex = this.calculateZIndex(targetNode); - if (zIndex) { - stepConfig.zIndex = zIndex + 1; + // Keep checking the remaining steps. + while (previousStepNumber >= 0) { + if (this.isStepPotentiallyVisible(this.getStepConfig(previousStepNumber))) { + return previousStepNumber; + } + previousStepNumber--; } - if (stepConfig.zIndex) { - currentStepNode.css('zIndex', stepConfig.zIndex + 1); - } - - // Add the backdrop. - this.positionBackdrop(stepConfig); - - $(document.body).append(currentStepNode); - this.currentStepNode = currentStepNode; - - // Ensure that the step node is positioned. - // Some situations mean that the value is not properly calculated without this step. - this.currentStepNode.css({ - top: 0, - left: 0 - }); - - animationTarget.animate({ - scrollTop: this.calculateScrollTop(stepConfig) - }).promise().then(function () { - this.positionStep(stepConfig); - this.revealStep(stepConfig); - }.bind(this)); - } else if (stepConfig.orphan) { - stepConfig.isOrphan = true; - - // This will be appended to the body instead. - stepConfig.attachTo = $('body').first(); - stepConfig.attachPoint = 'append'; - - // Add the backdrop. - this.positionBackdrop(stepConfig); - - // This is an orphaned step. - currentStepNode.addClass('orphan'); - - // It lives in the body. - $(document.body).append(currentStepNode); - this.currentStepNode = currentStepNode; - - this.currentStepNode.offset(this.calculateStepPositionInPage()); - this.currentStepNode.css('position', 'fixed'); - - this.currentStepPopper = new Popper($('body'), this.currentStepNode[0], { - removeOnDestroy: true, - placement: stepConfig.placement + '-start', - arrowElement: '[data-role="arrow"]', - // Empty the modifiers. We've already placed the step and don't want it moved. - modifiers: { - hide: { - enabled: false - }, - applyStyle: { - onLoad: null, - enabled: false - } - } - }); - - this.revealStep(stepConfig); + return null; } - return this; -}; + /** + * Is the step the final step number? + * + * @method isLastStep + * @param {Integer} stepNumber Step number to test + * @return {Boolean} Whether the step is the final step + */ + isLastStep(stepNumber) { + let nextStepNumber = this.getNextStepNumber(stepNumber); -Tour.prototype.revealStep = function (stepConfig) { - // Fade the step in. - this.currentStepNode.fadeIn('', $.proxy(function () { - // Announce via ARIA. - this.announceStep(stepConfig); - - // Focus on the current step Node. - this.currentStepNode.focus(); - window.setTimeout($.proxy(function () { - // After a brief delay, focus again. - // There seems to be an issue with Jaws where it only reads the dialogue title initially. - // This second focus helps it to read the full dialogue. - if (this.currentStepNode) { - this.currentStepNode.focus(); - } - }, this), 100); - }, this)); - - return this; -}; - -/** - * Helper to announce the step on the page. - * - * @method announceStep - * @param {Object} stepConfig The step configuration of the step - * @chainable - */ -Tour.prototype.announceStep = function (stepConfig) { - // Setup the step Dialogue as per: - // * https://www.w3.org/TR/wai-aria-practices/#dialog_nonmodal - // * https://www.w3.org/TR/wai-aria-practices/#dialog_modal - - // Generate an ID for the current step node. - var stepId = 'tour-step-' + this.tourName + '-' + stepConfig.stepNumber; - this.currentStepNode.attr('id', stepId); - - var bodyRegion = this.currentStepNode.find('[data-placeholder="body"]').first(); - bodyRegion.attr('id', stepId + '-body'); - bodyRegion.attr('role', 'document'); - - var headerRegion = this.currentStepNode.find('[data-placeholder="title"]').first(); - headerRegion.attr('id', stepId + '-title'); - headerRegion.attr('aria-labelledby', stepId + '-body'); - - // Generally, a modal dialog has a role of dialog. - this.currentStepNode.attr('role', 'dialog'); - this.currentStepNode.attr('tabindex', 0); - this.currentStepNode.attr('aria-labelledby', stepId + '-title'); - this.currentStepNode.attr('aria-describedby', stepId + '-body'); - - // Configure ARIA attributes on the target. - var target = this.getStepTarget(stepConfig); - if (target) { - if (!target.attr('tabindex')) { - target.attr('tabindex', 0); - } - - target.data('original-describedby', target.attr('aria-describedby')).attr('aria-describedby', stepId + '-body'); + return nextStepNumber === null; } - this.accessibilityShow(stepConfig); + /** + * Is the step the first step number? + * + * @method isFirstStep + * @param {Integer} stepNumber Step number to test + * @return {Boolean} Whether the step is the first step + */ + isFirstStep(stepNumber) { + let previousStepNumber = this.getPreviousStepNumber(stepNumber); - return this; -}; - -/** - * Handle key down events. - * - * @method handleKeyDown - * @param {EventFacade} e - */ -Tour.prototype.handleKeyDown = function (e) { - var tabbableSelector = 'a[href], link[href], [draggable=true], [contenteditable=true], :input:enabled, [tabindex], button:enabled'; - switch (e.keyCode) { - case 27: - this.endTour(); - break; - - // 9 == Tab - trap focus for items with a backdrop. - case 9: - // Tab must be handled on key up only in this instance. - (function () { - if (!this.currentStepConfig.hasBackdrop) { - // Trapping tab focus is only handled for those steps with a backdrop. - return; - } - - // Find all tabbable locations. - var activeElement = $(document.activeElement); - var stepTarget = this.getStepTarget(this.currentStepConfig); - var tabbableNodes = $(tabbableSelector); - var dialogContainer = $('span[data-flexitour="container"]'); - var currentIndex = void 0; - // Filter out element which is not belong to target section or dialogue. - if (stepTarget) { - tabbableNodes = tabbableNodes.filter(function (index, element) { - return stepTarget != null && (stepTarget.has(element).length || dialogContainer.has(element).length || stepTarget.is(element) || dialogContainer.is(element)); - }); - } - - // Find index of focusing element. - tabbableNodes.each(function (index, element) { - if (activeElement.is(element)) { - currentIndex = index; - return false; - } - }); - - var nextIndex = void 0; - var nextNode = void 0; - var focusRelevant = void 0; - if (currentIndex != void 0) { - var direction = 1; - if (e.shiftKey) { - direction = -1; - } - nextIndex = currentIndex; - do { - nextIndex += direction; - nextNode = $(tabbableNodes[nextIndex]); - } while (nextNode.length && nextNode.is(':disabled') || nextNode.is(':hidden')); - if (nextNode.length) { - // A new f - focusRelevant = nextNode.closest(stepTarget).length; - focusRelevant = focusRelevant || nextNode.closest(this.currentStepNode).length; - } else { - // Unable to find the target somehow. - focusRelevant = false; - } - } - - if (focusRelevant) { - nextNode.focus(); - } else { - if (e.shiftKey) { - // Focus on the last tabbable node in the step. - this.currentStepNode.find(tabbableSelector).last().focus(); - } else { - if (this.currentStepConfig.isOrphan) { - // Focus on the step - there is no target. - this.currentStepNode.focus(); - } else { - // Focus on the step target. - stepTarget.focus(); - } - } - } - e.preventDefault(); - }).call(this); - break; - } -}; - -/** - * Start the current tour. - * - * @method startTour - * @param {Integer} startAt Which step number to start at. If not specified, starts at the last point. - * @chainable - */ -Tour.prototype.startTour = function (startAt) { - if (this.storage && typeof startAt === 'undefined') { - var storageStartValue = this.storage.getItem(this.storageKey); - if (storageStartValue) { - var storageStartAt = parseInt(storageStartValue, 10); - if (storageStartAt <= this.steps.length) { - startAt = storageStartAt; - } - } + return previousStepNumber === null; } - if (typeof startAt === 'undefined') { - startAt = this.getCurrentStepNumber(); - } - - this.fireEventHandlers('beforeStart', startAt); - this.gotoStep(startAt); - this.fireEventHandlers('afterStart', startAt); - - return this; -}; - -/** - * Restart the tour from the beginning, resetting the completionlag. - * - * @method restartTour - * @chainable - */ -Tour.prototype.restartTour = function () { - return this.startTour(0); -}; - -/** - * End the current tour. - * - * @method endTour - * @chainable - */ -Tour.prototype.endTour = function () { - this.fireEventHandlers('beforeEnd'); - - if (this.currentStepConfig) { - var previousTarget = this.getStepTarget(this.currentStepConfig); - if (previousTarget) { - if (!previousTarget.attr('tabindex')) { - previousTarget.attr('tabindex', '-1'); - } - previousTarget.focus(); - } - } - - this.hide(true); - - this.fireEventHandlers('afterEnd'); - - return this; -}; - -/** - * Hide any currently visible steps. - * - * @method hide - * @chainable - */ -Tour.prototype.hide = function (transition) { - this.fireEventHandlers('beforeHide'); - - if (this.currentStepNode && this.currentStepNode.length) { - this.currentStepNode.hide(); - if (this.currentStepPopper) { - this.currentStepPopper.destroy(); - } - } - - // Restore original target configuration. - if (this.currentStepConfig) { - var target = this.getStepTarget(this.currentStepConfig); - if (target) { - if (target.data('original-labelledby')) { - target.attr('aria-labelledby', target.data('original-labelledby')); - } - - if (target.data('original-describedby')) { - target.attr('aria-describedby', target.data('original-describedby')); - } - - if (target.data('original-tabindex')) { - target.attr('tabindex', target.data('tabindex')); - } - } - - // Clear the step configuration. - this.currentStepConfig = null; - } - - var fadeTime = 0; - if (transition) { - fadeTime = 400; - } - - // Remove the backdrop features. - $('[data-flexitour="step-background"]').remove(); - $('[data-flexitour="step-backdrop"]').removeAttr('data-flexitour'); - $('[data-flexitour="backdrop"]').fadeOut(fadeTime, function () { - $(this).remove(); - }); - - // Remove aria-describedby and tabindex attributes. - if (this.currentStepNode && this.currentStepNode.length) { - var stepId = this.currentStepNode.attr('id'); - if (stepId) { - var currentStepElement = '[aria-describedby="' + stepId + '-body"]'; - $(currentStepElement).removeAttr('tabindex'); - $(currentStepElement).removeAttr('aria-describedby'); - } - } - - // Reset the listeners. - this.resetStepListeners(); - - this.accessibilityHide(); - - this.fireEventHandlers('afterHide'); - - this.currentStepNode = null; - this.currentStepPopper = null; - return this; -}; - -/** - * Show the current steps. - * - * @method show - * @chainable - */ -Tour.prototype.show = function () { - // Show the current step. - var startAt = this.getCurrentStepNumber(); - - return this.gotoStep(startAt); -}; - -/** - * Return the current step node. - * - * @method getStepContainer - * @return {jQuery} - */ -Tour.prototype.getStepContainer = function () { - return $(this.currentStepNode); -}; - -/** - * Calculate scrollTop. - * - * @method calculateScrollTop - * @param {Object} stepConfig The step configuration of the step - * @return {Number} - */ -Tour.prototype.calculateScrollTop = function (stepConfig) { - var scrollTop = $(window).scrollTop(); - var viewportHeight = $(window).height(); - var targetNode = this.getStepTarget(stepConfig); - - if (stepConfig.placement === 'top') { - // If the placement is top, center scroll at the top of the target. - scrollTop = targetNode.offset().top - viewportHeight / 2; - } else if (stepConfig.placement === 'bottom') { - // If the placement is bottom, center scroll at the bottom of the target. - scrollTop = targetNode.offset().top + targetNode.height() - viewportHeight / 2; - } else if (targetNode.height() <= viewportHeight * 0.8) { - // If the placement is left/right, and the target fits in the viewport, centre screen on the target - scrollTop = targetNode.offset().top - (viewportHeight - targetNode.height()) / 2; - } else { - // If the placement is left/right, and the target is bigger than the viewport, set scrollTop to target.top + buffer - // and change step attachmentTarget to top+. - scrollTop = targetNode.offset().top - viewportHeight * 0.2; - } - - // Never scroll over the top. - scrollTop = Math.max(0, scrollTop); - - // Never scroll beyond the bottom. - scrollTop = Math.min($(document).height() - viewportHeight, scrollTop); - - return Math.ceil(scrollTop); -}; - -/** - * Calculate dialogue position for page middle. - * - * @method calculateScrollTop - * @return {Number} - */ -Tour.prototype.calculateStepPositionInPage = function () { - var viewportHeight = $(window).height(); - var stepHeight = this.currentStepNode.height(); - - var viewportWidth = $(window).width(); - var stepWidth = this.currentStepNode.width(); - - return { - top: Math.ceil((viewportHeight - stepHeight) / 2), - left: Math.ceil((viewportWidth - stepWidth) / 2) - }; -}; - -/** - * Position the step on the page. - * - * @method positionStep - * @param {Object} stepConfig The step configuration of the step - * @chainable - */ -Tour.prototype.positionStep = function (stepConfig) { - var content = this.currentStepNode; - if (!content || !content.length) { - // Unable to find the step node. - return this; - } - - var flipBehavior = void 0; - switch (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'; - break; - } - - var target = this.getStepTarget(stepConfig); - var config = { - placement: stepConfig.placement + '-start', - removeOnDestroy: true, - modifiers: { - flip: { - behaviour: flipBehavior - }, - arrow: { - element: '[data-role="arrow"]' - } - }, - onCreate: function onCreate(data) { - recalculateArrowPosition(data); - }, - onUpdate: function onUpdate(data) { - recalculateArrowPosition(data); - } - }; - - var recalculateArrowPosition = function recalculateArrowPosition(data) { - var placement = data.placement.split('-')[0]; - var isVertical = ['left', 'right'].indexOf(placement) !== -1; - var arrowElement = data.instance.popper.querySelector('[data-role="arrow"]'); - var stepElement = $(data.instance.popper.querySelector('[data-role="flexitour-step"]')); - if (isVertical) { - var arrowHeight = parseFloat(window.getComputedStyle(arrowElement).height); - var arrowOffset = parseFloat(window.getComputedStyle(arrowElement).top); - var popperHeight = parseFloat(window.getComputedStyle(data.instance.popper).height); - var popperOffset = parseFloat(window.getComputedStyle(data.instance.popper).top); - var popperBorderWidth = parseFloat(stepElement.css('borderTopWidth')); - var popperBorderRadiusWidth = parseFloat(stepElement.css('borderTopLeftRadius')) * 2; - var arrowPos = arrowOffset + arrowHeight / 2; - var maxPos = popperHeight + popperOffset - popperBorderWidth - popperBorderRadiusWidth; - var minPos = popperOffset + popperBorderWidth + popperBorderRadiusWidth; - if (arrowPos >= maxPos || arrowPos <= minPos) { - var newArrowPos = 0; - if (arrowPos > popperHeight / 2) { - newArrowPos = maxPos - arrowHeight; - } else { - newArrowPos = minPos + arrowHeight; - } - $(arrowElement).css('top', newArrowPos); - } - } else { - var arrowWidth = parseFloat(window.getComputedStyle(arrowElement).width); - var _arrowOffset = parseFloat(window.getComputedStyle(arrowElement).left); - var popperWidth = parseFloat(window.getComputedStyle(data.instance.popper).width); - var _popperOffset = parseFloat(window.getComputedStyle(data.instance.popper).left); - var _popperBorderWidth = parseFloat(stepElement.css('borderTopWidth')); - var _popperBorderRadiusWidth = parseFloat(stepElement.css('borderTopLeftRadius')) * 2; - var _arrowPos = _arrowOffset + arrowWidth / 2; - var _maxPos = popperWidth + _popperOffset - _popperBorderWidth - _popperBorderRadiusWidth; - var _minPos = _popperOffset + _popperBorderWidth + _popperBorderRadiusWidth; - if (_arrowPos >= _maxPos || _arrowPos <= _minPos) { - var _newArrowPos = 0; - if (_arrowPos > popperWidth / 2) { - _newArrowPos = _maxPos - arrowWidth; - } else { - _newArrowPos = _minPos + arrowWidth; - } - $(arrowElement).css('left', _newArrowPos); - } - } - }; - - var background = $('[data-flexitour="step-background"]'); - if (background.length) { - target = background; - } - this.currentStepPopper = new Popper(target, content[0], config); - - return this; -}; - -/** - * Add the backdrop. - * - * @method positionBackdrop - * @param {Object} stepConfig The step configuration of the step - * @chainable - */ -Tour.prototype.positionBackdrop = function (stepConfig) { - if (stepConfig.backdrop) { - this.currentStepConfig.hasBackdrop = true; - var backdrop = $('
'); - - if (stepConfig.zIndex) { - if (stepConfig.attachPoint === 'append') { - stepConfig.attachTo.append(backdrop); - } else { - backdrop.insertAfter(stepConfig.attachTo); - } - } else { - $('body').append(backdrop); + /** + * Is this step potentially visible? + * + * @method isStepPotentiallyVisible + * @param {Object} stepConfig The step configuration to normalise + * @return {Boolean} Whether the step is the potentially visible + */ + isStepPotentiallyVisible(stepConfig) { + if (!stepConfig) { + // Without step config, there can be no step. + return false; } if (this.isStepActuallyVisible(stepConfig)) { - // The step has a visible target. - // Punch a hole through the backdrop. - var background = $('
'); + // If it is actually visible, it is already potentially visible. + return true; + } + if (typeof stepConfig.orphan !== 'undefined' && stepConfig.orphan) { + // Orphan steps have no target. They are always visible. + return true; + } + + if (typeof stepConfig.delay !== 'undefined' && stepConfig.delay) { + // Only return true if the activated has not been used yet. + return true; + } + + // Not theoretically, or actually visible. + return false; + } + + /** + * Is this step actually visible? + * + * @method isStepActuallyVisible + * @param {Object} stepConfig The step configuration to normalise + * @return {Boolean} Whether the step is actually visible + */ + isStepActuallyVisible(stepConfig) { + if (!stepConfig) { + // Without step config, there can be no step. + return false; + } + + let target = this.getStepTarget(stepConfig); + if (target && target.length && target.is(':visible')) { + // Without a target, there can be no step. + return !!target.length; + } + + return false; + } + + /** + * Go to the next step in the tour. + * + * @method next + * @chainable + * @return {Object} this. + */ + next() { + return this.gotoStep(this.getNextStepNumber()); + } + + /** + * Go to the previous step in the tour. + * + * @method previous + * @chainable + * @return {Object} this. + */ + previous() { + return this.gotoStep(this.getPreviousStepNumber(), -1); + } + + /** + * Go to the specified step in the tour. + * + * @method gotoStep + * @param {Integer} stepNumber The step number to display + * @param {Integer} direction Next or previous step + * @chainable + * @return {Object} this. + */ + gotoStep(stepNumber, direction) { + if (stepNumber < 0) { + return this.endTour(); + } + + let stepConfig = this.getStepConfig(stepNumber); + if (stepConfig === null) { + return this.endTour(); + } + + return this._gotoStep(stepConfig, direction); + } + + _gotoStep(stepConfig, direction) { + if (!stepConfig) { + return this.endTour(); + } + + if (typeof stepConfig.delay !== 'undefined' && stepConfig.delay && !stepConfig.delayed) { + stepConfig.delayed = true; + window.setTimeout(this._gotoStep.bind(this), stepConfig.delay, stepConfig, direction); + + return this; + } else if (!stepConfig.orphan && !this.isStepActuallyVisible(stepConfig)) { + let fn = direction == -1 ? 'getPreviousStepNumber' : 'getNextStepNumber'; + return this.gotoStep(this[fn](stepConfig.stepNumber), direction); + } + + this.hide(); + + this.fireEventHandlers('beforeRender', stepConfig); + this.renderStep(stepConfig); + this.fireEventHandlers('afterRender', stepConfig); + + return this; + } + + /** + * Fetch the normalised step configuration for the specified step number. + * + * @method getStepConfig + * @param {Integer} stepNumber The step number to fetch configuration for + * @return {Object} The step configuration + */ + getStepConfig(stepNumber) { + if (stepNumber === null || stepNumber < 0 || stepNumber >= this.steps.length) { + return null; + } + + // Normalise the step configuration. + let stepConfig = this.normalizeStepConfig(this.steps[stepNumber]); + + // Add the stepNumber to the stepConfig. + stepConfig = $.extend(stepConfig, {stepNumber: stepNumber}); + + return stepConfig; + } + + /** + * Normalise the supplied step configuration. + * + * @method normalizeStepConfig + * @param {Object} stepConfig The step configuration to normalise + * @return {Object} The normalised step configuration + */ + normalizeStepConfig(stepConfig) { + + if (typeof stepConfig.reflex !== 'undefined' && typeof stepConfig.moveAfterClick === 'undefined') { + stepConfig.moveAfterClick = stepConfig.reflex; + } + + if (typeof stepConfig.element !== 'undefined' && typeof stepConfig.target === 'undefined') { + stepConfig.target = stepConfig.element; + } + + if (typeof stepConfig.content !== 'undefined' && typeof stepConfig.body === 'undefined') { + stepConfig.body = stepConfig.content; + } + + stepConfig = $.extend({}, this.stepDefaults, stepConfig); + + stepConfig = $.extend({}, { + attachTo: stepConfig.target, + attachPoint: 'after', + }, stepConfig); + + if (stepConfig.attachTo) { + stepConfig.attachTo = $(stepConfig.attachTo).first(); + } + + return stepConfig; + } + + /** + * Fetch the actual step target from the selector. + * + * This should not be called until after any delay has completed. + * + * @method getStepTarget + * @param {Object} stepConfig The step configuration + * @return {$} + */ + getStepTarget(stepConfig) { + if (stepConfig.target) { + return $(stepConfig.target); + } + + return null; + } + + /** + * Fire any event handlers for the specified event. + * + * @param {String} eventName The name of the event to handle + * @param {Object} data Any data to pass to the event + * @chainable + * @return {Object} this. + */ + fireEventHandlers(eventName, data) { + if (typeof this.eventHandlers[eventName] === 'undefined') { + return this; + } + + this.eventHandlers[eventName].forEach(function(thisEvent) { + thisEvent.call(this, data); + }, this); + + return this; + } + + /** + * @method addEventHandler + * @param {string} eventName The name of the event to listen for + * @param {function} handler The event handler to call + * @return {Object} this. + */ + addEventHandler(eventName, handler) { + if (typeof this.eventHandlers[eventName] === 'undefined') { + this.eventHandlers[eventName] = []; + } + + this.eventHandlers[eventName].push(handler); + + return this; + } + + /** + * Process listeners for the step being shown. + * + * @method processStepListeners + * @param {object} stepConfig The configuration for the step + * @chainable + * @return {Object} this. + */ + processStepListeners(stepConfig) { + this.listeners.push( + // Next/Previous buttons. + { + node: this.currentStepNode, + args: ['click', '[data-role="next"]', $.proxy(this.next, this)] + }, { + node: this.currentStepNode, + args: ['click', '[data-role="previous"]', $.proxy(this.previous, this)] + }, + + // Close and end tour buttons. + { + node: this.currentStepNode, + args: ['click', '[data-role="end"]', $.proxy(this.endTour, this)] + }, + + // Click backdrop and hide tour. + { + node: $('[data-flexitour="backdrop"]'), + args: ['click', $.proxy(this.hide, this)] + }, + + // Keypresses. + { + node: $('body'), + args: ['keydown', $.proxy(this.handleKeyDown, this)] + }); + + if (stepConfig.moveOnClick) { var targetNode = this.getStepTarget(stepConfig); + this.listeners.push({ + node: targetNode, + args: ['click', $.proxy(function(e) { + if ($(e.target).parents('[data-flexitour="container"]').length === 0) { + // Ignore clicks when they are in the flexitour. + window.setTimeout($.proxy(this.next, this), 500); + } + }, this)] + }); + } - var buffer = 10; + this.listeners.forEach(function (listener) { + listener.node.on.apply(listener.node, listener.args); + }); - var colorNode = targetNode; - if (buffer) { - colorNode = $('body'); + return this; + } + + /** + * Reset step listeners. + * + * @method resetStepListeners + * @chainable + * @return {Object} this. + */ + resetStepListeners() { + // Stop listening to all external handlers. + if (this.listeners) { + this.listeners.forEach(function(listener) { + listener.node.off.apply(listener.node, listener.args); + }); + } + this.listeners = []; + + return this; + } + + /** + * The standard step renderer. + * + * @method renderStep + * @param {Object} stepConfig The step configuration of the step + * @chainable + * @return {Object} this. + */ + renderStep(stepConfig) { + // Store the current step configuration for later. + this.currentStepConfig = stepConfig; + this.setCurrentStepNumber(stepConfig.stepNumber); + + // Fetch the template and convert it to a $ object. + let template = $(this.getTemplateContent()); + + // Title. + template.find('[data-placeholder="title"]') + .html(stepConfig.title); + + // Body. + template.find('[data-placeholder="body"]') + .html(stepConfig.body); + + // Is this the first step? + if (this.isFirstStep(stepConfig.stepNumber)) { + template.find('[data-role="previous"]').prop('disabled', true); + } else { + template.find('[data-role="previous"]').prop('disabled', false); + } + + // Is this the final step? + if (this.isLastStep(stepConfig.stepNumber)) { + template.find('[data-role="next"]').prop('disabled', true); + } else { + template.find('[data-role="next"]').prop('disabled', false); + } + + template.find('[data-role="previous"]').attr('role', 'button'); + template.find('[data-role="next"]').attr('role', 'button'); + template.find('[data-role="end"]').attr('role', 'button'); + + // Replace the template with the updated version. + stepConfig.template = template; + + // Add to the page. + this.addStepToPage(stepConfig); + + // Process step listeners after adding to the page. + // This uses the currentNode. + this.processStepListeners(stepConfig); + + return this; + } + + /** + * Getter for the template content. + * + * @method getTemplateContent + * @return {$} + */ + getTemplateContent() { + return $(this.templateContent).clone(); + } + + /** + * Helper to add a step to the page. + * + * @method addStepToPage + * @param {Object} stepConfig The step configuration of the step + * @chainable + * @return {Object} this. + */ + addStepToPage(stepConfig) { + // Create the stepNode from the template data. + let currentStepNode = $('') + .html(stepConfig.template) + .hide(); + + // The scroll animation occurs on the body or html. + let animationTarget = $('body, html') + .stop(true, true); + + if (this.isStepActuallyVisible(stepConfig)) { + let targetNode = this.getStepTarget(stepConfig); + + targetNode.data('flexitour', 'target'); + + let zIndex = this.calculateZIndex(targetNode); + if (zIndex) { + stepConfig.zIndex = zIndex + 1; } - background.css({ - width: targetNode.outerWidth() + buffer + buffer, - height: targetNode.outerHeight() + buffer + buffer, - left: targetNode.offset().left - buffer, - top: targetNode.offset().top - buffer, - backgroundColor: this.calculateInherittedBackgroundColor(colorNode) + if (stepConfig.zIndex) { + currentStepNode.css('zIndex', stepConfig.zIndex + 1); + } + + // Add the backdrop. + this.positionBackdrop(stepConfig); + + $(document.body).append(currentStepNode); + this.currentStepNode = currentStepNode; + + // Ensure that the step node is positioned. + // Some situations mean that the value is not properly calculated without this step. + this.currentStepNode.css({ + top: 0, + left: 0, }); - if (targetNode.offset().left < buffer) { - background.css({ - width: targetNode.outerWidth() + targetNode.offset().left + buffer, - left: targetNode.offset().left - }); + animationTarget + .animate({ + scrollTop: this.calculateScrollTop(stepConfig), + }).promise().then(function() { + this.positionStep(stepConfig); + this.revealStep(stepConfig); + return; + }.bind(this)) + .catch(function() { + // Silently fail. + }); + + } else if (stepConfig.orphan) { + stepConfig.isOrphan = true; + + // This will be appended to the body instead. + stepConfig.attachTo = $('body').first(); + stepConfig.attachPoint = 'append'; + + // Add the backdrop. + this.positionBackdrop(stepConfig); + + // This is an orphaned step. + currentStepNode.addClass('orphan'); + + // It lives in the body. + $(document.body).append(currentStepNode); + this.currentStepNode = currentStepNode; + + this.currentStepNode.offset(this.calculateStepPositionInPage()); + this.currentStepNode.css('position', 'fixed'); + + this.currentStepPopper = new Popper( + $('body'), + this.currentStepNode[0], { + removeOnDestroy: true, + placement: stepConfig.placement + '-start', + arrowElement: '[data-role="arrow"]', + // Empty the modifiers. We've already placed the step and don't want it moved. + modifiers: { + hide: { + enabled: false, + }, + applyStyle: { + onLoad: null, + enabled: false, + }, + } + } + ); + + this.revealStep(stepConfig); + } + + return this; + } + + /** + * Make the given step visible. + * + * @method revealStep + * @param {Object} stepConfig The step configuration of the step + * @chainable + * @return {Object} this. + */ + revealStep(stepConfig) { + // Fade the step in. + this.currentStepNode.fadeIn('', $.proxy(function() { + // Announce via ARIA. + this.announceStep(stepConfig); + + // Focus on the current step Node. + this.currentStepNode.focus(); + window.setTimeout($.proxy(function() { + // After a brief delay, focus again. + // There seems to be an issue with Jaws where it only reads the dialogue title initially. + // This second focus helps it to read the full dialogue. + if (this.currentStepNode) { + this.currentStepNode.focus(); + } + }, this), 100); + + }, this)); + + return this; + } + + /** + * Helper to announce the step on the page. + * + * @method announceStep + * @param {Object} stepConfig The step configuration of the step + * @chainable + * @return {Object} this. + */ + announceStep(stepConfig) { + // Setup the step Dialogue as per: + // * https://www.w3.org/TR/wai-aria-practices/#dialog_nonmodal + // * https://www.w3.org/TR/wai-aria-practices/#dialog_modal + + // Generate an ID for the current step node. + 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'); + + // Generally, a modal dialog has a role of dialog. + this.currentStepNode.attr('role', 'dialog'); + this.currentStepNode.attr('tabindex', 0); + this.currentStepNode.attr('aria-labelledby', stepId + '-title'); + this.currentStepNode.attr('aria-describedby', stepId + '-body'); + + // Configure ARIA attributes on the target. + let target = this.getStepTarget(stepConfig); + if (target) { + if (!target.attr('tabindex')) { + target.attr('tabindex', 0); } - if (targetNode.offset().top < buffer) { - background.css({ - height: targetNode.outerHeight() + targetNode.offset().top + buffer, - top: targetNode.offset().top - }); + target + .data('original-describedby', target.attr('aria-describedby')) + .attr('aria-describedby', stepId + '-body') + ; + } + + this.accessibilityShow(stepConfig); + + return this; + } + + /** + * Handle key down events. + * + * @method handleKeyDown + * @param {EventFacade} e + */ + handleKeyDown(e) { + let tabbableSelector = 'a[href], link[href], [draggable=true], [contenteditable=true], '; + tabbableSelector += ':input:enabled, [tabindex], button:enabled'; + switch (e.keyCode) { + case 27: + this.endTour(); + break; + + // 9 == Tab - trap focus for items with a backdrop. + case 9: + // Tab must be handled on key up only in this instance. + (function() { + if (!this.currentStepConfig.hasBackdrop) { + // Trapping tab focus is only handled for those steps with a backdrop. + return; + } + + // Find all tabbable locations. + let activeElement = $(document.activeElement); + let stepTarget = this.getStepTarget(this.currentStepConfig); + let tabbableNodes = $(tabbableSelector); + let dialogContainer = $('span[data-flexitour="container"]'); + let currentIndex; + // Filter out element which is not belong to target section or dialogue. + if (stepTarget) { + tabbableNodes = tabbableNodes.filter(function(index, element) { + return stepTarget !== null + && (stepTarget.has(element).length + || dialogContainer.has(element).length + || stepTarget.is(element) + || dialogContainer.is(element)); + }); + } + + // Find index of focusing element. + tabbableNodes.each(function(index, element) { + if (activeElement.is(element)) { + currentIndex = index; + return false; + } + // Keep looping. + return true; + }); + + let nextIndex; + let nextNode; + let focusRelevant; + if (currentIndex != void 0) { + let direction = 1; + if (e.shiftKey) { + direction = -1; + } + nextIndex = currentIndex; + do { + nextIndex += direction; + nextNode = $(tabbableNodes[nextIndex]); + } while (nextNode.length && nextNode.is(':disabled') || nextNode.is(':hidden')); + if (nextNode.length) { + // A new f + focusRelevant = nextNode.closest(stepTarget).length; + focusRelevant = focusRelevant || nextNode.closest(this.currentStepNode).length; + } else { + // Unable to find the target somehow. + focusRelevant = false; + } + } + + if (focusRelevant) { + nextNode.focus(); + } else { + if (e.shiftKey) { + // Focus on the last tabbable node in the step. + this.currentStepNode.find(tabbableSelector).last().focus(); + } else { + if (this.currentStepConfig.isOrphan) { + // Focus on the step - there is no target. + this.currentStepNode.focus(); + } else { + // Focus on the step target. + stepTarget.focus(); + } + } + } + e.preventDefault(); + }).call(this); + break; + } + } + + /** + * Start the current tour. + * + * @method startTour + * @param {Integer} startAt Which step number to start at. If not specified, starts at the last point. + * @chainable + * @return {Object} this. + */ + startTour(startAt) { + if (this.storage && typeof startAt === 'undefined') { + let storageStartValue = this.storage.getItem(this.storageKey); + if (storageStartValue) { + let storageStartAt = parseInt(storageStartValue, 10); + if (storageStartAt <= this.steps.length) { + startAt = storageStartAt; + } + } + } + + if (typeof startAt === 'undefined') { + startAt = this.getCurrentStepNumber(); + } + + this.fireEventHandlers('beforeStart', startAt); + this.gotoStep(startAt); + this.fireEventHandlers('afterStart', startAt); + + return this; + } + + /** + * Restart the tour from the beginning, resetting the completionlag. + * + * @method restartTour + * @chainable + * @return {Object} this. + */ + restartTour() { + return this.startTour(0); + } + + /** + * End the current tour. + * + * @method endTour + * @chainable + * @return {Object} this. + */ + endTour() { + this.fireEventHandlers('beforeEnd'); + + if (this.currentStepConfig) { + let previousTarget = this.getStepTarget(this.currentStepConfig); + if (previousTarget) { + if (!previousTarget.attr('tabindex')) { + previousTarget.attr('tabindex', '-1'); + } + previousTarget.focus(); + } + } + + this.hide(true); + + this.fireEventHandlers('afterEnd'); + + return this; + } + + /** + * Hide any currently visible steps. + * + * @method hide + * @param {Bool} transition Animate the visibility change + * @chainable + * @return {Object} this. + */ + hide(transition) { + this.fireEventHandlers('beforeHide'); + + if (this.currentStepNode && this.currentStepNode.length) { + this.currentStepNode.hide(); + if (this.currentStepPopper) { + this.currentStepPopper.destroy(); + } + } + + // Restore original target configuration. + if (this.currentStepConfig) { + let target = this.getStepTarget(this.currentStepConfig); + if (target) { + if (target.data('original-labelledby')) { + target.attr('aria-labelledby', target.data('original-labelledby')); + } + + if (target.data('original-describedby')) { + target.attr('aria-describedby', target.data('original-describedby')); + } + + if (target.data('original-tabindex')) { + target.attr('tabindex', target.data('tabindex')); + } } - var targetRadius = targetNode.css('borderRadius'); - if (targetRadius && targetRadius !== $('body').css('borderRadius')) { - background.css('borderRadius', targetRadius); - } + // Clear the step configuration. + this.currentStepConfig = null; + } - var targetPosition = this.calculatePosition(targetNode); - if (targetPosition === 'fixed') { - background.css('top', 0); - } else if (targetPosition === 'absolute') { - background.css('position', 'fixed'); - } + let fadeTime = 0; + if (transition) { + fadeTime = 400; + } - var fader = background.clone(); - fader.css({ - backgroundColor: backdrop.css('backgroundColor'), - opacity: backdrop.css('opacity') - }); - fader.attr('data-flexitour', 'step-background-fader'); + // Remove the backdrop features. + $('[data-flexitour="step-background"]').remove(); + $('[data-flexitour="step-backdrop"]').removeAttr('data-flexitour'); + $('[data-flexitour="backdrop"]').fadeOut(fadeTime, function() { + $(this).remove(); + }); + + // Remove aria-describedby and tabindex attributes. + if (this.currentStepNode && this.currentStepNode.length) { + let stepId = this.currentStepNode.attr('id'); + if (stepId) { + let currentStepElement = '[aria-describedby="' + stepId + '-body"]'; + $(currentStepElement).removeAttr('tabindex'); + $(currentStepElement).removeAttr('aria-describedby'); + } + } + + // Reset the listeners. + this.resetStepListeners(); + + this.accessibilityHide(); + + this.fireEventHandlers('afterHide'); + + this.currentStepNode = null; + this.currentStepPopper = null; + return this; + } + + /** + * Show the current steps. + * + * @method show + * @chainable + * @return {Object} this. + */ + show() { + // Show the current step. + let startAt = this.getCurrentStepNumber(); + + return this.gotoStep(startAt); + } + + /** + * Return the current step node. + * + * @method getStepContainer + * @return {jQuery} + */ + getStepContainer() { + return $(this.currentStepNode); + } + + /** + * Calculate scrollTop. + * + * @method calculateScrollTop + * @param {Object} stepConfig The step configuration of the step + * @return {Number} + */ + calculateScrollTop(stepConfig) { + let scrollTop = $(window).scrollTop(); + let viewportHeight = $(window).height(); + let targetNode = this.getStepTarget(stepConfig); + + if (stepConfig.placement === 'top') { + // If the placement is top, center scroll at the top of the target. + scrollTop = targetNode.offset().top - (viewportHeight / 2); + } else if (stepConfig.placement === 'bottom') { + // If the placement is bottom, center scroll at the bottom of the target. + scrollTop = targetNode.offset().top + targetNode.height() - (viewportHeight / 2); + } else if (targetNode.height() <= (viewportHeight * 0.8)) { + // If the placement is left/right, and the target fits in the viewport, centre screen on the target + scrollTop = targetNode.offset().top - ((viewportHeight - targetNode.height()) / 2); + } else { + // If the placement is left/right, and the target is bigger than the viewport, set scrollTop to target.top + buffer + // and change step attachmentTarget to top+. + scrollTop = targetNode.offset().top - (viewportHeight * 0.2); + } + + // Never scroll over the top. + scrollTop = Math.max(0, scrollTop); + + // Never scroll beyond the bottom. + scrollTop = Math.min($(document).height() - viewportHeight, scrollTop); + + return Math.ceil(scrollTop); + } + + /** + * Calculate dialogue position for page middle. + * + * @method calculateScrollTop + * @return {Number} + */ + calculateStepPositionInPage() { + let viewportHeight = $(window).height(); + let stepHeight = this.currentStepNode.height(); + + let viewportWidth = $(window).width(); + let stepWidth = this.currentStepNode.width(); + + return { + top: Math.ceil((viewportHeight - stepHeight) / 2), + left: Math.ceil((viewportWidth - stepWidth) / 2) + }; + } + + /** + * Position the step on the page. + * + * @method positionStep + * @param {Object} stepConfig The step configuration of the step + * @chainable + * @return {Object} this. + */ + positionStep(stepConfig) { + let content = this.currentStepNode; + if (!content || !content.length) { + // Unable to find the step node. + return this; + } + + let flipBehavior; + switch (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'; + break; + } + + let target = this.getStepTarget(stepConfig); + var config = { + placement: stepConfig.placement + '-start', + removeOnDestroy: true, + modifiers: { + flip: { + behaviour: flipBehavior, + }, + arrow: { + element: '[data-role="arrow"]', + }, + }, + onCreate: function(data) { + recalculateArrowPosition(data); + }, + onUpdate: function(data) { + recalculateArrowPosition(data); + }, + }; + + let recalculateArrowPosition = function(data) { + let placement = data.placement.split('-')[0]; + const isVertical = ['left', 'right'].indexOf(placement) !== -1; + const arrowElement = data.instance.popper.querySelector('[data-role="arrow"]'); + const stepElement = $(data.instance.popper.querySelector('[data-role="flexitour-step"]')); + if (isVertical) { + let arrowHeight = parseFloat(window.getComputedStyle(arrowElement).height); + let arrowOffset = parseFloat(window.getComputedStyle(arrowElement).top); + let popperHeight = parseFloat(window.getComputedStyle(data.instance.popper).height); + let popperOffset = parseFloat(window.getComputedStyle(data.instance.popper).top); + let popperBorderWidth = parseFloat(stepElement.css('borderTopWidth')); + let popperBorderRadiusWidth = parseFloat(stepElement.css('borderTopLeftRadius')) * 2; + let arrowPos = arrowOffset + (arrowHeight / 2); + let maxPos = popperHeight + popperOffset - popperBorderWidth - popperBorderRadiusWidth; + let minPos = popperOffset + popperBorderWidth + popperBorderRadiusWidth; + if (arrowPos >= maxPos || arrowPos <= minPos) { + let newArrowPos = 0; + if (arrowPos > (popperHeight / 2)) { + newArrowPos = maxPos - arrowHeight; + } else { + newArrowPos = minPos + arrowHeight; + } + $(arrowElement).css('top', newArrowPos); + } + } else { + let arrowWidth = parseFloat(window.getComputedStyle(arrowElement).width); + let arrowOffset = parseFloat(window.getComputedStyle(arrowElement).left); + let popperWidth = parseFloat(window.getComputedStyle(data.instance.popper).width); + let popperOffset = parseFloat(window.getComputedStyle(data.instance.popper).left); + let popperBorderWidth = parseFloat(stepElement.css('borderTopWidth')); + let popperBorderRadiusWidth = parseFloat(stepElement.css('borderTopLeftRadius')) * 2; + let arrowPos = arrowOffset + (arrowWidth / 2); + let maxPos = popperWidth + popperOffset - popperBorderWidth - popperBorderRadiusWidth; + let minPos = popperOffset + popperBorderWidth + popperBorderRadiusWidth; + if (arrowPos >= maxPos || arrowPos <= minPos) { + let newArrowPos = 0; + if (arrowPos > (popperWidth / 2)) { + newArrowPos = maxPos - arrowWidth; + } else { + newArrowPos = minPos + arrowWidth; + } + $(arrowElement).css('left', newArrowPos); + } + } + }; + + let background = $('[data-flexitour="step-background"]'); + if (background.length) { + target = background; + } + this.currentStepPopper = new Popper(target, content[0], config); + + return this; + } + + /** + * Add the backdrop. + * + * @method positionBackdrop + * @param {Object} stepConfig The step configuration of the step + * @chainable + * @return {Object} this. + */ + positionBackdrop(stepConfig) { + if (stepConfig.backdrop) { + this.currentStepConfig.hasBackdrop = true; + let backdrop = $('
'); if (stepConfig.zIndex) { if (stepConfig.attachPoint === 'append') { - stepConfig.attachTo.append(background); + stepConfig.attachTo.append(backdrop); } else { - fader.insertAfter(stepConfig.attachTo); - background.insertAfter(stepConfig.attachTo); + backdrop.insertAfter(stepConfig.attachTo); } } else { - $('body').append(fader); - $('body').append(background); + $('body').append(backdrop); } - // Add the backdrop data to the actual target. - // This is the part which actually does the work. - targetNode.attr('data-flexitour', 'step-backdrop'); + if (this.isStepActuallyVisible(stepConfig)) { + // The step has a visible target. + // Punch a hole through the backdrop. + let background = $('
'); - if (stepConfig.zIndex) { - backdrop.css('zIndex', stepConfig.zIndex); - background.css('zIndex', stepConfig.zIndex + 1); - targetNode.css('zIndex', stepConfig.zIndex + 2); - } + let targetNode = this.getStepTarget(stepConfig); - fader.fadeOut('2000', function () { - $(this).remove(); - }); - } - } - return this; -}; + let buffer = 10; -/** - * Calculate the inheritted z-index. - * - * @method calculateZIndex - * @param {jQuery} elem The element to calculate z-index for - * @return {Number} Calculated z-index - */ -Tour.prototype.calculateZIndex = function (elem) { - elem = $(elem); - while (elem.length && elem[0] !== document) { - // Ignore z-index if position is set to a value where z-index is ignored by the browser - // This makes behavior of this function consistent across browsers - // WebKit always returns auto if the element is positioned. - var position = elem.css("position"); - if (position === "absolute" || position === "relative" || position === "fixed") { - // IE returns 0 when zIndex is not specified - // other browsers return a string - // we ignore the case of nested elements with an explicit value of 0 - //
- var value = parseInt(elem.css("zIndex"), 10); - if (!isNaN(value) && value !== 0) { - return value; + let colorNode = targetNode; + if (buffer) { + colorNode = $('body'); + } + + background.css({ + width: targetNode.outerWidth() + buffer + buffer, + height: targetNode.outerHeight() + buffer + buffer, + left: targetNode.offset().left - buffer, + top: targetNode.offset().top - buffer, + backgroundColor: this.calculateInherittedBackgroundColor(colorNode), + }); + + if (targetNode.offset().left < buffer) { + background.css({ + width: targetNode.outerWidth() + targetNode.offset().left + buffer, + left: targetNode.offset().left, + }); + } + + if (targetNode.offset().top < buffer) { + background.css({ + height: targetNode.outerHeight() + targetNode.offset().top + buffer, + top: targetNode.offset().top, + }); + } + + let targetRadius = targetNode.css('borderRadius'); + if (targetRadius && targetRadius !== $('body').css('borderRadius')) { + background.css('borderRadius', targetRadius); + } + + let targetPosition = this.calculatePosition(targetNode); + if (targetPosition === 'fixed') { + background.css('top', 0); + } else if (targetPosition === 'absolute') { + background.css('position', 'fixed'); + } + + let fader = background.clone(); + fader.css({ + backgroundColor: backdrop.css('backgroundColor'), + opacity: backdrop.css('opacity'), + }); + fader.attr('data-flexitour', 'step-background-fader'); + + if (stepConfig.zIndex) { + if (stepConfig.attachPoint === 'append') { + stepConfig.attachTo.append(background); + } else { + fader.insertAfter(stepConfig.attachTo); + background.insertAfter(stepConfig.attachTo); + } + } else { + $('body').append(fader); + $('body').append(background); + } + + // Add the backdrop data to the actual target. + // This is the part which actually does the work. + targetNode.attr('data-flexitour', 'step-backdrop'); + + if (stepConfig.zIndex) { + backdrop.css('zIndex', stepConfig.zIndex); + background.css('zIndex', stepConfig.zIndex + 1); + targetNode.css('zIndex', stepConfig.zIndex + 2); + } + + fader.fadeOut('2000', function() { + $(this).remove(); + }); } } - elem = elem.parent(); + return this; } - return 0; -}; - -/** - * Calculate the inheritted background colour. - * - * @method calculateInherittedBackgroundColor - * @param {jQuery} elem The element to calculate colour for - * @return {String} Calculated background colour - */ -Tour.prototype.calculateInherittedBackgroundColor = function (elem) { - // Use a fake node to compare each element against. - var fakeNode = $('
').hide(); - $('body').append(fakeNode); - var fakeElemColor = fakeNode.css('backgroundColor'); - fakeNode.remove(); - - elem = $(elem); - while (elem.length && elem[0] !== document) { - var color = elem.css('backgroundColor'); - if (color !== fakeElemColor) { - return color; - } - elem = elem.parent(); - } - - return null; -}; - -/** - * Calculate the inheritted position. - * - * @method calculatePosition - * @param {jQuery} elem The element to calculate position for - * @return {String} Calculated position - */ -Tour.prototype.calculatePosition = function (elem) { - elem = $(elem); - while (elem.length && elem[0] !== document) { - var position = elem.css('position'); - if (position !== 'static') { - return position; - } - elem = elem.parent(); - } - - return null; -}; - -/** - * Perform accessibility changes for step shown. - * - * This will add aria-hidden="true" to all siblings and parent siblings. - * - * @method accessibilityShow - */ -Tour.prototype.accessibilityShow = function () { - var stateHolder = 'data-has-hidden'; - var attrName = 'aria-hidden'; - var hideFunction = function hideFunction(child) { - var flexitourRole = child.data('flexitour'); - if (flexitourRole) { - switch (flexitourRole) { - case 'container': - case 'target': - return; + /** + * Calculate the inheritted z-index. + * + * @method calculateZIndex + * @param {jQuery} elem The element to calculate z-index for + * @return {Number} Calculated z-index + */ + calculateZIndex(elem) { + elem = $(elem); + while (elem.length && elem[0] !== document) { + // Ignore z-index if position is set to a value where z-index is ignored by the browser + // This makes behavior of this function consistent across browsers + // WebKit always returns auto if the element is positioned. + let position = elem.css("position"); + if (position === "absolute" || position === "relative" || position === "fixed") { + // IE returns 0 when zIndex is not specified + // other browsers return a string + // we ignore the case of nested elements with an explicit value of 0 + //
+ let value = parseInt(elem.css("zIndex"), 10); + if (!isNaN(value) && value !== 0) { + return value; + } } + elem = elem.parent(); } - var hidden = child.attr(attrName); - if (!hidden) { - child.attr(stateHolder, true); - child.attr(attrName, true); + return 0; + } + + /** + * Calculate the inheritted background colour. + * + * @method calculateInherittedBackgroundColor + * @param {jQuery} elem The element to calculate colour for + * @return {String} Calculated background colour + */ + calculateInherittedBackgroundColor(elem) { + // Use a fake node to compare each element against. + let fakeNode = $('
').hide(); + $('body').append(fakeNode); + let fakeElemColor = fakeNode.css('backgroundColor'); + fakeNode.remove(); + + elem = $(elem); + while (elem.length && elem[0] !== document) { + let color = elem.css('backgroundColor'); + if (color !== fakeElemColor) { + return color; + } + elem = elem.parent(); } - }; - this.currentStepNode.siblings().each(function (index, node) { - hideFunction($(node)); - }); - this.currentStepNode.parentsUntil('body').siblings().each(function (index, node) { - hideFunction($(node)); - }); -}; + return null; + } -/** - * Perform accessibility changes for step hidden. - * - * This will remove any newly added aria-hidden="true". - * - * @method accessibilityHide - */ -Tour.prototype.accessibilityHide = function () { - var stateHolder = 'data-has-hidden'; - var attrName = 'aria-hidden'; - var showFunction = function showFunction(child) { - var hidden = child.attr(stateHolder); - if (typeof hidden !== 'undefined') { - child.removeAttr(stateHolder); - child.removeAttr(attrName); + /** + * Calculate the inheritted position. + * + * @method calculatePosition + * @param {jQuery} elem The element to calculate position for + * @return {String} Calculated position + */ + calculatePosition(elem) { + elem = $(elem); + while (elem.length && elem[0] !== document) { + let position = elem.css('position'); + if (position !== 'static') { + return position; + } + elem = elem.parent(); } - }; - $('[' + stateHolder + ']').each(function (index, node) { - showFunction($(node)); - }); -}; + return null; + } -if ((typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object') { - module.exports = Tour; + /** + * Perform accessibility changes for step shown. + * + * This will add aria-hidden="true" to all siblings and parent siblings. + * + * @method accessibilityShow + */ + accessibilityShow() { + let stateHolder = 'data-has-hidden'; + let attrName = 'aria-hidden'; + let hideFunction = function(child) { + let flexitourRole = child.data('flexitour'); + if (flexitourRole) { + switch (flexitourRole) { + case 'container': + case 'target': + return; + } + } + + let hidden = child.attr(attrName); + if (!hidden) { + child.attr(stateHolder, true); + child.attr(attrName, true); + } + }; + + this.currentStepNode.siblings().each(function(index, node) { + hideFunction($(node)); + }); + this.currentStepNode.parentsUntil('body').siblings().each(function(index, node) { + hideFunction($(node)); + }); + } + + /** + * Perform accessibility changes for step hidden. + * + * This will remove any newly added aria-hidden="true". + * + * @method accessibilityHide + */ + accessibilityHide() { + let stateHolder = 'data-has-hidden'; + let attrName = 'aria-hidden'; + let showFunction = function(child) { + let hidden = child.attr(stateHolder); + if (typeof hidden !== 'undefined') { + child.removeAttr(stateHolder); + child.removeAttr(attrName); + } + }; + + $('[' + stateHolder + ']').each(function(index, node) { + showFunction($(node)); + }); + } } - -return Tour; - -})); diff --git a/admin/tool/usertours/thirdpartylibs.xml b/admin/tool/usertours/thirdpartylibs.xml deleted file mode 100644 index 8f1c4f5b389..00000000000 --- a/admin/tool/usertours/thirdpartylibs.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - amd/src/tour.js - Flexitour - GPLv3 - 0.12.3 - 3 - -