Proyectos de Subversion Moodle

Rev

Rev 11 | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |

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