PageSourceSearch

https://cdnall.icerikbulutu.com/Assets/js/intro/intro.js

js icerikbulutu.com collected 2026-09-24 17:19:02 UTC 95,487 bytes, 2,587 lines download raw bytes

1/*!
2 * Intro.js v3.0.1
3 * https://github.com/usablica/intro.js
4 *
5 * Copyright (C) 2017-2020 Afshin Mehrabani (@afshinmeh).
6 * https://raw.githubusercontent.com/usablica/intro.js/master/license.md
7 *
8 * Date: Sat, 17 Oct 2020 10:36:20 GMT
9 */
10
11(function (global, factory) {
12    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
13        typeof define === 'function' && define.amd ? define(factory) :
14            (global = global || self, global.introJs = factory());
15}(this, (function () {
16    'use strict';
17
18    function _typeof(obj) {
19        "@babel/helpers - typeof";
20
21        if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
22            _typeof = function (obj) {
23                return typeof obj;
24            };
25        } else {
26            _typeof = function (obj) {
27                return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
28            };
29        }
30
31        return _typeof(obj);
32    }
33
34    /**
35     * Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1
36     * via: http://stackoverflow.com/questions/171251/how-can-i-merge-properties-of-two-javascript-objects-dynamically
37     *
38     * @param obj1
39     * @param obj2
40     * @returns obj3 a new object based on obj1 and obj2
41     */
42    function mergeOptions(obj1, obj2) {
43        var obj3 = {};
44        var attrname;
45
46        for (attrname in obj1) {
47            obj3[attrname] = obj1[attrname];
48        }
49
50        for (attrname in obj2) {
51            obj3[attrname] = obj2[attrname];
52        }
53
54        return obj3;
55    }
56
57    /**
58     * Mark any object with an incrementing number
59     * used for keeping track of objects
60     *
61     * @param Object obj   Any object or DOM Element
62     * @param String key
63     * @return Object
64     */
65    var stamp = function () {
66        var keys = {};
67        return function stamp(obj) {
68            var key = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "introjs-stamp";
69            // each group increments from 0
70            keys[key] = keys[key] || 0; // stamp only once per object
71
72            if (obj[key] === undefined) {
73                // increment key for each new object
74                obj[key] = keys[key]++;
75            }
76
77            return obj[key];
78        };
79    }();
80
81    /**
82     * Iterates arrays
83     *
84     * @param {Array} arr
85     * @param {Function} forEachFnc
86     * @param {Function} completeFnc
87     * @return {Null}
88     */
89    function forEach(arr, forEachFnc, completeFnc) {
90        // in case arr is an empty query selector node list
91        if (arr) {
92            for (var i = 0, len = arr.length; i < len; i++) {
93                forEachFnc(arr[i], i);
94            }
95        }
96
97        if (typeof completeFnc === "function") {
98            completeFnc();
99        }
100    }
101
102    /**
103     * Remove a class from an element
104     *
105     * @api private
106     * @method _removeClass
107     * @param {Object} element
108     * @param {RegExp|String} classNameRegex can be regex or string
109     * @returns null
110     */
111    function removeClass(element, classNameRegex) {
112        if (element instanceof SVGElement) {
113            var pre = element.getAttribute("class") || "";
114            element.setAttribute("class", pre.replace(classNameRegex, "").replace(/^\s+|\s+$/g, ""));
115        } else {
116            element.className = element.className.replace(classNameRegex, "").replace(/^\s+|\s+$/g, "");
117        }
118    }
119
120    /**
121     * DOMEvent Handles all DOM events
122     *
123     * methods:
124     *
125     * on - add event handler
126     * off - remove event
127     */
128
129    var DOMEvent = function () {
130        function DOMEvent() {
131            var events_key = "introjs_event";
132            /**
133             * Gets a unique ID for an event listener
134             *
135             * @param obj Object
136             * @param type event type
137             * @param listener Function
138             * @param context Object
139             * @return String
140             */
141
142            this._id = function (obj, type, listener, context) {
143                return type + stamp(listener) + (context ? "_".concat(stamp(context)) : "");
144            };
145            /**
146             * Adds event listener
147             *
148             * @param obj Object obj
149             * @param type String
150             * @param listener Function
151             * @param context Object
152             * @param useCapture Boolean
153             * @return null
154             */
155
156
157            this.on = function (obj, type, listener, context, useCapture) {
158                var id = this._id.apply(this, arguments);
159
160                var handler = function handler(e) {
161                    return listener.call(context || obj, e || window.event);
162                };
163
164                if ("addEventListener" in obj) {
165                    obj.addEventListener(type, handler, useCapture);
166                } else if ("attachEvent" in obj) {
167                    obj.attachEvent("on".concat(type), handler);
168                }
169
170                obj[events_key] = obj[events_key] || {};
171                obj[events_key][id] = handler;
172            };
173            /**
174             * Removes event listener
175             *
176             * @param obj Object
177             * @param type String
178             * @param listener Function
179             * @param context Object
180             * @param useCapture Boolean
181             * @return null
182             */
183
184
185            this.off = function (obj, type, listener, context, useCapture) {
186                var id = this._id.apply(this, arguments);
187
188                var handler = obj[events_key] && obj[events_key][id];
189
190                if (!handler) {
191                    return;
192                }
193
194                if ("removeEventListener" in obj) {
195                    obj.removeEventListener(type, handler, useCapture);
196                } else if ("detachEvent" in obj) {
197                    obj.detachEvent("on".concat(type), handler);
198                }
199
200                obj[events_key][id] = null;
201            };
202        }
203
204        return new DOMEvent();
205    }();
206
207    /**
208     * Append a class to an element
209     *
210     * @api private
211     * @method _addClass
212     * @param {Object} element
213     * @param {String} className
214     * @returns null
215     */
216
217    function addClass(element, className) {
218        if (element instanceof SVGElement) {
219            // svg
220            var pre = element.getAttribute("class") || "";
221            element.setAttribute("class", "".concat(pre, " ").concat(className));
222        } else {
223            if (element.classList !== undefined) {
224                // check for modern classList property
225                var classes = className.split(" ");
226                forEach(classes, function (cls) {
227                    element.classList.add(cls);
228                });
229            } else if (!element.className.match(className)) {
230                // check if element doesn't already have className
231                element.className += " ".concat(className);
232            }
233        }
234    }
235
236    /**
237     * Get an element CSS property on the page
238     * Thanks to JavaScript Kit: http://www.javascriptkit.com/dhtmltutors/dhtmlcascade4.shtml
239     *
240     * @api private
241     * @method _getPropValue
242     * @param {Object} element
243     * @param {String} propName
244     * @returns string property value
245     */
246    function getPropValue(element, propName) {
247        var propValue = "";
248
249        if (element.currentStyle) {
250            //IE
251            propValue = element.currentStyle[propName];
252        } else if (document.defaultView && document.defaultView.getComputedStyle) {
253            //Others
254            propValue = document.defaultView.getComputedStyle(element, null).getPropertyValue(propName);
255        } //Prevent exception in IE
256
257
258        if (propValue && propValue.toLowerCase) {
259            return propValue.toLowerCase();
260        } else {
261            return propValue;
262        }
263    }
264
265    /**
266     * To set the show element
267     * This function set a relative (in most cases) position and changes the z-index
268     *
269     * @api private
270     * @method _setShowElement
271     * @param {Object} targetElement
272     */
273
274    function setShowElement(_ref) {
275        var element = _ref.element;
276        var parentElm;
276 // we need to add this show element class to the parent of SVG elements
277        // because the SVG elements can't have independent z-index
278
279        if (element instanceof SVGElement) {
280            parentElm = element.parentNode;
281
282            while (element.parentNode !== null) {
283                if (!parentElm.tagName || parentElm.tagName.toLowerCase() === "body") break;
284
285                if (parentElm.tagName.toLowerCase() === "svg") {
286                    addClass(parentElm, "introjs-showElement introjs-relativePosition");
287                }
288
289                parentElm = parentElm.parentNode;
290            }
291        }
292
293        addClass(element, "introjs-showElement");
294        var currentElementPosition = getPropValue(element, "position");
295
296        if (currentElementPosition !== "absolute" && currentElementPosition !== "relative" && currentElementPosition !== "fixed") {
297            //change to new intro item
298            addClass(element, "introjs-relativePosition");
299        }
300
301        parentElm = element.parentNode;
302
303        while (parentElm !== null) {
304            if (!parentElm.tagName || parentElm.tagName.toLowerCase() === "body") break; //fix The Stacking Context problem.
305            //More detail: https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context
306
307            var zIndex = getPropValue(parentElm, "z-index");
308            var opacity = parseFloat(getPropValue(parentElm, "opacity"));
309            var transform = getPropValue(parentElm, "transform") || getPropValue(parentElm, "-webkit-transform") || getPropValue(parentElm, "-moz-transform") || getPropValue(parentElm, "-ms-transform") || getPropValue(parentElm, "-o-transform");
310
311            if (/[0-9]+/.test(zIndex) || opacity < 1 || transform !== "none" && transform !== undefined) {
312                addClass(parentElm, "introjs-fixParent");
313            }
314
315            parentElm = parentElm.parentNode;
316        }
317    }
318
319    /**
320     * scroll a scrollable element to a child element
321     *
322     * @param Element parent
323     * @param Element element
324     * @return Null
325     */
326    function scrollParentToElement(parent, _ref) {
327        var offsetTop = _ref.offsetTop;
328        parent.scrollTop = offsetTop - parent.offsetTop;
329    }
330
331    /**
332     * Find the nearest scrollable parent
333     * copied from https://stackoverflow.com/questions/35939886/find-first-scrollable-parent
334     *
335     * @param Element element
336     * @return Element
337     */
338    function getScrollParent(element) {
339        var style = window.getComputedStyle(element);
340        var excludeStaticParent = style.position === "absolute";
341        var overflowRegex = /(auto|scroll)/;
342        if (style.position === "fixed") return document.body;
343
344        for (var parent = element; parent = parent.parentElement;) {
345            style = window.getComputedStyle(parent);
346
347            if (excludeStaticParent && style.position === "static") {
348                continue;
349            }
350
351            if (overflowRegex.test(style.overflow + style.overflowY + style.overflowX)) return parent;
352        }
353
354        return document.body;
355    }
356
357    /**
358     * Provides a cross-browser way to get the screen dimensions
359     * via: http://stackoverflow.com/questions/5864467/internet-explorer-innerheight
360     *
361     * @api private
362     * @method _getWinSize
363     * @returns {Object} width and height attributes
364     */
365    function getWinSize() {
366        if (window.innerWidth !== undefined) {
367            return {
368                width: window.innerWidth,
369                height: window.innerHeight
370            };
371        } else {
372            var D = document.documentElement;
373            return {
374                width: D.clientWidth,
375                height: D.clientHeight
376            };
377        }
378    }
379
380    /**
381     * Check to see if the element is in the viewport or not
382     * http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport
383     *
384     * @api private
385     * @method _elementInViewport
386     * @param {Object} el
387     */
388    function elementInViewport(el) {
389        var rect = el.getBoundingClientRect();
390        return rect.top >= 0 && rect.left >= 0 && rect.bottom + 80 <= window.innerHeight && // add 80 to get the text right
391            rect.right <= window.innerWidth;
392    }
393
394    /**
395     * To change the scroll of `window` after highlighting an element
396     *
397     * @api private
398     * @method _scrollTo
399     * @param {String} scrollTo
400     * @param {Object} targetElement
401     * @param {Object} tooltipLayer
402     */
403
404    function scrollTo(scrollTo, _ref, tooltipLayer) {
405        var element = _ref.element;
406        if (scrollTo === "off") return;
407        var rect;
408        if (!this._options.scrollToElement) return;
409
410        if (scrollTo === "tooltip") {
411            rect = tooltipLayer.getBoundingClientRect();
412        } else {
413            rect = element.getBoundingClientRect();
414        }
415
416        if (!elementInViewport(element)) {
417            var winHeight = getWinSize().height;
418            var top = rect.bottom - (rect.bottom - rect.top); // TODO (afshinm): do we need scroll padding now?
419            // I have changed the scroll option and now it scrolls the window to
420            // the center of the target element or tooltip.
421
422            if (top < 0 || element.clientHeight > winHeight) {
423                window.scrollBy(0, rect.top - (winHeight / 2 - rect.height / 2) - this._options.scrollPadding); // 30px padding from edge to look nice
424                //Scroll down
425            } else {
426                window.scrollBy(0, rect.top - (winHeight / 2 - rect.height / 2) + this._options.scrollPadding); // 30px padding from edge to look nice
427            }
428        }
429    }
430
431    /**
432     * Setting anchors to behave like buttons
433     *
434     * @api private
435     * @method _setAnchorAsButton
436     */
437    function setAnchorAsButton(anchor) {
438        anchor.setAttribute("role", "button");
439        anchor.tabIndex = 0;
440    }
441
442    /**
443     * Get an element position on the page
444     * Thanks to `meouw`: http://stackoverflow.com/a/442474/375966
445     *
446     * @api private
447     * @method _getOffset
448     * @param {Object} element
449     * @returns Element's position info
450     */
451    function getOffset(element) {
452        var body = document.body;
453        var docEl = document.documentElement;
454        var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop;
455        var scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft;
456        var x = element.getBoundingClientRect();
457        return {
458            top: x.top + scrollTop,
459            width: x.width,
460            height: x.height,
461            left: x.left + scrollLeft
462        };
463    }
464
465    /**
466     * Checks to see if target element (or parents) position is fixed or not
467     *
468     * @api private
469     * @method _isFixed
470     * @param {Object} element
471     * @returns Boolean
472     */
473
474    function isFixed(element) {
475        var p = element.parentNode;
476
477        if (!p || p.nodeName === "HTML") {
478            return false;
479        }
480
481        if (getPropValue(element, "position") === "fixed") {
482            return true;
483        }
484
485        return isFixed(p);
486    }
487
488    /**
489     * Update the position of the helper layer on the screen
490     *
491     * @api private
492     * @method _setHelperLayerPosition
493     * @param {Object} helperLayer
494     */
495
496    function setHelperLayerPosition(helperLayer) {
497        if (helperLayer) {
498            //prevent error when `this._currentStep` in undefined
499            if (!this._introItems[this._currentStep]) return;
500            var currentElement = this._introItems[this._currentStep];
501            var elementPosition = getOffset(currentElement.element);
502            var widthHeightPadding = this._options.helperElementPadding; // If the target element is fixed, the tooltip should be fixed as well.
503            // Otherwise, remove a fixed class that may be left over from the previous
504            // step.
505
506            if (isFixed(currentElement.element)) {
507                addClass(helperLayer, "introjs-fixedTooltip");
508            } else {
509                removeClass(helperLayer, "introjs-fixedTooltip");
510            }
511
512            if (currentElement.position === "floating") {
513                widthHeightPadding = 0;
514            } //set new position to helper layer
515
516
517            helperLayer.style.cssText = "width: ".concat(elementPosition.width + widthHeightPadding, "px; height:").concat(elementPosition.height + widthHeightPadding, "px; top:").concat(elementPosition.top - widthHeightPadding / 2, "px;left: ").concat(elementPosition.left - widthHeightPadding / 2, "px;");
518        }
519    }
520
521    /**
522     * Set tooltip left so it doesn't go off the right side of the window
523     *
524     * @return boolean true, if tooltipLayerStyleLeft is ok.  false, otherwise.
525     */
526    function checkRight(targetOffset, tooltipLayerStyleLeft, tooltipOffset, windowSize, tooltipLayer) {
527        if (targetOffset.left + tooltipLayerStyleLeft + tooltipOffset.width > windowSize.width) {
528            // off the right side of the window
529            tooltipLayer.left = "".concat(windowSize.width - tooltipOffset.width - targetOffset.left, "px");
530            return false;
531        }
532
533        tooltipLayer.left = "".concat(tooltipLayerStyleLeft, "px");
534        return true;
535    }
536
537    /**
538     * Set tooltip right so it doesn't go off the left side of the window
539     *
540     * @return boolean true, if tooltipLayerStyleRight is ok.  false, otherwise.
541     */
542    function checkLeft(targetOffset, tooltipLayerStyleRight, tooltipOffset, tooltipLayer) {
543        if (targetOffset.left + targetOffset.width - tooltipLayerStyleRight - tooltipOffset.width < 0) {
544            // off the left side of the window
545            tooltipLayer.style.left = "".concat(-targetOffset.left, "px");
546            return false;
547        }
548
549        tooltipLayer.style.right = "".concat(tooltipLayerStyleRight, "px");
550        return true;
551    }
552
553    /**
554     * Remove an entry from a string array if it's there, does nothing if it isn't there.
555     *
556     * @param {Array} stringArray
557     * @param {String} stringToRemove
558     */
559    function removeEntry(stringArray, stringToRemove) {
560        if (stringArray.includes(stringToRemove)) {
561            stringArray.splice(stringArray.indexOf(stringToRemove), 1);
562        }
563    }
564
565    /**
566     * auto-determine alignment
567     * @param {Integer}  offsetLeft
568     * @param {Integer}  tooltipWidth
569     * @param {Object}   windowSize
570     * @param {String}   desiredAlignment
571     * @return {String}  calculatedAlignment
572     */
573
574    function _determineAutoAlignment(offsetLeft, tooltipWidth, _ref, desiredAlignment) {
575        var width = _ref.width;
576        var halfTooltipWidth = tooltipWidth / 2;
577        var winWidth = Math.min(width, window.screen.width);
578        var possibleAlignments = ["-left-aligned", "-middle-aligned", "-right-aligned"];
579        var calculatedAlignment = ""; // valid left must be at least a tooltipWidth
580        // away from right side
581
582        if (winWidth - offsetLeft < tooltipWidth) {
583            removeEntry(possibleAlignments, "-left-aligned");
584        } // valid middle must be at least half
585        // width away from both sides
586
587
588        if (offsetLeft < halfTooltipWidth || winWidth - offsetLeft < halfTooltipWidth) {
589            removeEntry(possibleAlignments, "-middle-aligned");
590        } // valid right must be at least a tooltipWidth
591        // width away from left side
592
593
594        if (offsetLeft < tooltipWidth) {
595            removeEntry(possibleAlignments, "-right-aligned");
596        }
597
598        if (possibleAlignments.length) {
599            if (possibleAlignments.includes(desiredAlignment)) {
600                // the desired alignment is valid
601                calculatedAlignment = desiredAlignment;
602            } else {
603                // pick the first valid position, in order
604                calculatedAlignment = possibleAlignments[0];
605            }
606        } else {
607            // if screen width is too small
608            // for ANY alignment, middle is
609            // probably the best for visibility
610            calculatedAlignment = "-middle-aligned";
611        }
612
613        return calculatedAlignment;
614    }
615    /**
616     * Determines the position of the tooltip based on the position precedence and availability
617     * of screen space.
618     *
619     * @param {Object}    targetElement
620     * @param {Object}    tooltipLayer
621     * @param {String}    desiredTooltipPosition
622     * @return {String}   calculatedPosition
623     */
624
625
626    function _determineAutoPosition(targetElement, tooltipLayer, desiredTooltipPosition) {
627        // Take a clone of position precedence. These will be the available
628        var possiblePositions = this._options.positionPrecedence.slice();
629
630        var windowSize = getWinSize();
631        var tooltipHeight = getOffset(tooltipLayer).height + 10;
632        var tooltipWidth = getOffset(tooltipLayer).width + 20;
633        var targetElementRect = targetElement.getBoundingClientRect(); // If we check all the possible areas, and there are no valid places for the tooltip, the element
634        // must take up most of the screen real estate. Show the tooltip floating in the middle of the screen.
635
636        var calculatedPosition = "floating";
637        /*
638         * auto determine position
639         */
640        // Check for space below
641
642        if (targetElementRect.bottom + tooltipHeight > windowSize.height) {
643            removeEntry(possiblePositions, "bottom");
644        } // Check for space above
645
646
647        if (targetElementRect.top - tooltipHeight < 0) {
648            removeEntry(possiblePositions, "top");
649        } // Check for space to the right
650
651
652        if (targetElementRect.right + tooltipWidth > windowSize.width) {
653            removeEntry(possiblePositions, "right");
654        } // Check for space to the left
655
656
657        if (targetElementRect.left - tooltipWidth < 0) {
658            removeEntry(possiblePositions, "left");
659        } // @var {String}  ex: 'right-aligned'
660
661
662        var desiredAlignment = function (pos) {
663            var hyphenIndex = pos.indexOf("-");
664
665            if (hyphenIndex !== -1) {
666                // has alignment
667                return pos.substr(hyphenIndex);
668            }
669
670            return "";
671        }(desiredTooltipPosition || ""); // strip alignment from position
672
673
674        if (desiredTooltipPosition) {
675            // ex: "bottom-right-aligned"
676            // should return 'bottom'
677            desiredTooltipPosition = desiredTooltipPosition.split("-")[0];
678        }
679
680        if (possiblePositions.length) {
681            if (desiredTooltipPosition !== "auto" && possiblePositions.includes(desiredTooltipPosition)) {
682                // If the requested position is in the list, choose that
683                calculatedPosition = desiredTooltipPosition;
684            } else {
685                // Pick the first valid position, in order
686                calculatedPosition = possiblePositions[0];
687            }
688        } // only top and bottom positions have optional alignments
689
690
691        if (["top", "bottom"].includes(calculatedPosition)) {
692            calculatedPosition += _determineAutoAlignment(targetElementRect.left, tooltipWidth, windowSize, desiredAlignment);
693        }
694
695        return calculatedPosition;
696    }
697    /**
698     * Render tooltip box in the page
699     *
700     * @api private
701     * @method placeTooltip
702     * @param {HTMLElement} targetElement
703     * @param {HTMLElement} tooltipLayer
704     * @param {HTMLElement} arrowLayer
705     * @param {HTMLElement} helperNumberLayer
706     * @param {Boolean} hintMode
707     */
708
709
710    function placeTooltip(targetElement, tooltipLayer, arrowLayer, helperNumberLayer, hintMode) {
711        var tooltipCssClass = "";
712        var currentStepObj;
713        var tooltipOffset;
714        var targetOffset;
715        var windowSize;
716        var currentTooltipPosition;
717        hintMode = hintMode || false; //reset the old style
718
719        tooltipLayer.style.top = null;
720        tooltipLayer.style.right = null;
721        tooltipLayer.style.bottom = null;
722        tooltipLayer.style.left = null;
723        tooltipLayer.style.marginLeft = null;
724        tooltipLayer.style.marginTop = null;
725        arrowLayer.style.display = "inherit";
726
727        if (typeof helperNumberLayer !== "undefined" && helperNumberLayer !== null) {
728            helperNumberLayer.style.top = null;
729            helperNumberLayer.style.left = null;
730        } //prevent error when `this._currentStep` is undefined
731
732
733        if (!this._introItems[this._currentStep]) return; //if we have a custom css class for each step
734
735        currentStepObj = this._introItems[this._currentStep];
736
737        if (typeof currentStepObj.tooltipClass === "string") {
738            tooltipCssClass = currentStepObj.tooltipClass;
739        } else {
740            tooltipCssClass = this._options.tooltipClass;
741        }
742
743        tooltipLayer.className = "introjs-tooltip ".concat(tooltipCssClass).replace(/^\s+|\s+$/g, "");
744        tooltipLayer.setAttribute("role", "dialog");
745        currentTooltipPosition = this._introItems[this._currentStep].position; // Floating is always valid, no point in calculating
746
747        if (currentTooltipPosition !== "floating") {
748            currentTooltipPosition = _determineAutoPosition.call(this, targetElement, tooltipLayer, currentTooltipPosition);
749        }
750
751        var tooltipLayerStyleLeft;
752        targetOffset = getOffset(targetElement);
753        tooltipOffset = getOffset(tooltipLayer);
754        windowSize = getWinSize();
755        addClass(tooltipLayer, "introjs-".concat(currentTooltipPosition));
756
757        switch (currentTooltipPosition) {
758            case "top-right-aligned":
759                arrowLayer.className = "introjs-arrow bottom-right";
760                var tooltipLayerStyleRight = 0;
761                checkLeft(targetOffset, tooltipLayerStyleRight, tooltipOffset, tooltipLayer);
762                tooltipLayer.style.bottom = "".concat(targetOffset.height + 20, "px");
763                break;
764
765            case "top-middle-aligned":
766                arrowLayer.className = "introjs-arrow bottom-middle";
767                var tooltipLayerStyleLeftRight = targetOffset.width / 2 - tooltipOffset.width / 2; // a fix for middle aligned hints
768
769                if (hintMode) {
770                    tooltipLayerStyleLeftRight += 5;
771                }
772
773                if (checkLeft(targetOffset, tooltipLayerStyleLeftRight, tooltipOffset, tooltipLayer)) {
774                    tooltipLayer.style.right = null;
775                    checkRight(targetOffset, tooltipLayerStyleLeftRight, tooltipOffset, windowSize, tooltipLayer);
776                }
777
778                tooltipLayer.style.bottom = "".concat(targetOffset.height + 20, "px");
779                break;
780
781            case "top-left-aligned": // top-left-aligned is the same as the default top
782
783            case "top":
784                arrowLayer.className = "introjs-arrow bottom";
785                tooltipLayerStyleLeft = hintMode ? 0 : 15;
786                checkRight(targetOffset, tooltipLayerStyleLeft, tooltipOffset, windowSize, tooltipLayer);
787                tooltipLayer.style.bottom = "".concat(targetOffset.height + 20, "px");
788                break;
789
790            case "right":
791                tooltipLayer.style.left = "".concat(targetOffset.width + 20, "px");
792
793                if (targetOffset.top + tooltipOffset.height > windowSize.height) {
794                    // In this case, right would have fallen below the bottom of the screen.
795                    // Modify so that the bottom of the tooltip connects with the target
796                    arrowLayer.className = "introjs-arrow left-bottom";
797                    tooltipLayer.style.top = "-".concat(tooltipOffset.height - targetOffset.height - 20, "px");
798                } else {
799                    arrowLayer.className = "introjs-arrow left";
800                }
801
802                break;
803
804            case "left":
805                if (!hintMode && this._options.showStepNumbers === true) {
806                    tooltipLayer.style.top = "15px";
807                }
808
809                if (targetOffset.top + tooltipOffset.height > windowSize.height) {
810                    // In this case, left would have fallen below the bottom of the screen.
811                    // Modify so that the bottom of the tooltip connects with the target
812                    tooltipLayer.style.top = "-".concat(tooltipOffset.height - targetOffset.height - 20, "px");
813                    arrowLayer.className = "introjs-arrow right-bottom";
814                } else {
815                    arrowLayer.className = "introjs-arrow right";
816                }
817
818                tooltipLayer.style.right = "".concat(targetOffset.width + 20, "px");
819                break;
820
821            case "floating":
822                arrowLayer.style.display = "none"; //we have to adjust the top and left of layer manually for intro items without element
823
824                tooltipLayer.style.left = "50%";
825                tooltipLayer.style.top = "50%";
826                tooltipLayer.style.marginLeft = "-".concat(tooltipOffset.width / 2, "px");
827                tooltipLayer.style.marginTop = "-".concat(tooltipOffset.height / 2, "px");
828
829                if (typeof helperNumberLayer !== "undefined" && helperNumberLayer !== null) {
830                    helperNumberLayer.style.left = "-".concat(tooltipOffset.width / 2 + 18, "px");
831                    helperNumberLayer.style.top = "-".concat(tooltipOffset.height / 2 + 18, "px");
832                }
833
834                break;
835
836            case "bottom-right-aligned":
837                arrowLayer.className = "introjs-arrow top-right";
838                tooltipLayerStyleRight = 0;
839                checkLeft(targetOffset, tooltipLayerStyleRight, tooltipOffset, tooltipLayer);
840                tooltipLayer.style.top = "".concat(targetOffset.height + 20, "px");
841                break;
842
843            case "bottom-middle-aligned":
844                arrowLayer.className = "introjs-arrow top-middle";
845                tooltipLayerStyleLeftRight = targetOffset.width / 2 - tooltipOffset.width / 2; // a fix for middle aligned hints
846
847                if (hintMode) {
848                    tooltipLayerStyleLeftRight += 5;
849                }
850
851                if (checkLeft(targetOffset, tooltipLayerStyleLeftRight, tooltipOffset, tooltipLayer)) {
852                    tooltipLayer.style.right = null;
853                    checkRight(targetOffset, tooltipLayerStyleLeftRight, tooltipOffset, windowSize, tooltipLayer);
854                }
855
856                tooltipLayer.style.top = "".concat(targetOffset.height + 20, "px");
857                break;
858            // case 'bottom-left-aligned':
859            // Bottom-left-aligned is the same as the default bottom
860            // case 'bottom':
861            // Bottom going to follow the default behavior
862
863            default:
864                arrowLayer.className = "introjs-arrow top";
865                tooltipLayerStyleLeft = 0;
866                checkRight(targetOffset, tooltipLayerStyleLeft, tooltipOffset, windowSize, tooltipLayer);
867                tooltipLayer.style.top = "".concat(targetOffset.height + 20, "px");
868        }
869    }
870
871    /**
872     * To remove all show element(s)
873     *
874     * @api private
875     * @method _removeShowElement
876     */
877
878    function removeShowElement() {
879        var elms = document.querySelectorAll(".introjs-showElement");
880        forEach(elms, function (elm) {
881            removeClass(elm, /introjs-[a-zA-Z]+/g);
882        });
883    }
884
885    /**
886     * Gets the current progress percentage
887     *
888     * @api private
889     * @method _getProgress
890     * @returns current progress percentage
891     */
892
893    function _getProgress() {
894        // Steps are 0 indexed
895        var currentStep = parseInt(this._currentStep + 1, 10);
896        return currentStep / this._introItems.length * 100;
897    }
898    /**
899     * Add disableinteraction layer and adjust the size and position of the layer
900     *
901     * @api private
902     * @method _disableInteraction
903     */
904
905
906    function _disableInteraction() {
907        var disableInteractionLayer = document.querySelector(".introjs-disableInteraction");
908
909        if (disableInteractionLayer === null) {
910            disableInteractionLayer = document.createElement("div");
911            disableInteractionLayer.className = "introjs-disableInteraction";
912
913            this._targetElement.appendChild(disableInteractionLayer);
914        }
915
916        setHelperLayerPosition.call(this, disableInteractionLayer);
917    }
918    /**
919     * Show an element on the page
920     *
921     * @api private
922     * @method _showElement
923     * @param {Object} targetElement
924     */
925
926
927    function _showElement(targetElement) {
928        if (typeof this._introChangeCallback !== "undefined") {
929            this._introChangeCallback.call(this, targetElement.element);
930        }
931
932        var self = this;
933        var oldHelperLayer = document.querySelector(".introjs-helperLayer");
934        var oldReferenceLayer = document.querySelector(".introjs-tooltipReferenceLayer");
935        var highlightClass = "introjs-helperLayer";
936        var nextTooltipButton;
937        var prevTooltipButton;
938        var skipTooltipButton;
939        var scrollParent; //check for a current step highlight class
940
941        if (typeof targetElement.highlightClass === "string") {
942            highlightClass += " ".concat(targetElement.highlightClass);
943        } //check for options highlight class
944
945
946        if (typeof this._options.highlightClass === "string") {
947            highlightClass += " ".concat(this._options.highlightClass);
948        }
949
950        if (oldHelperLayer !== null) {
951            var oldHelperNumberLayer = oldReferenceLayer.querySelector(".introjs-helperNumberLayer");
952            var oldtooltipLayer = oldReferenceLayer.querySelector(".introjs-tooltiptext");
953            var oldArrowLayer = oldReferenceLayer.querySelector(".introjs-arrow");
954            var oldtooltipContainer = oldReferenceLayer.querySelector(".introjs-tooltip");
955            skipTooltipButton = oldReferenceLayer.querySelector(".introjs-skipbutton");
956            prevTooltipButton = oldReferenceLayer.querySelector(".introjs-prevbutton");
957            nextTooltipButton = oldReferenceLayer.querySelector(".introjs-nextbutton"); //update or reset the helper highlight class
958
959            oldHelperLayer.className = highlightClass; //hide the tooltip
960
961            oldtooltipContainer.style.opacity = 0;
962            oldtooltipContainer.style.display = "none";
963
964            if (oldHelperNumberLayer !== null) {
965                var lastIntroItem = this._introItems[targetElement.step - 2 >= 0 ? targetElement.step - 2 : 0];
966
967                if (lastIntroItem !== null && this._direction === "forward" && lastIntroItem.position === "floating" || this._direction === "backward" && targetElement.position === "floating") {
968                    oldHelperNumberLayer.style.opacity = 0;
969                }
970            } // scroll to element
971
972
973            scrollParent = getScrollParent(targetElement.element);
974
975            if (scrollParent !== document.body) {
976                // target is within a scrollable element
977                scrollParentToElement(scrollParent, targetElement.element);
978            } // set new position to helper layer
979
980
981            setHelperLayerPosition.call(self, oldHelperLayer);
982            setHelperLayerPosition.call(self, oldReferenceLayer); //remove `introjs-fixParent` class from the elements
983
984            var fixParents = document.querySelectorAll(".introjs-fixParent");
985            forEach(fixParents, function (parent) {
986                removeClass(parent, /introjs-fixParent/g);
987            }); //remove old classes if the element still exist
988
989            removeShowElement(); //we should wait until the CSS3 transition is competed (it's 0.3 sec) to prevent incorrect `height` and `width` calculation
990
991            if (self._lastShowElementTimer) {
992                window.clearTimeout(self._lastShowElementTimer);
993            }
994
995            self._lastShowElementTimer = window.setTimeout(function () {
996                //set current step to the label
997                if (oldHelperNumberLayer !== null) {
998                    oldHelperNumberLayer.innerHTML = targetElement.step;
999                } //set current tooltip text
1000
1001
1002                oldtooltipLayer.innerHTML = targetElement.intro; //set the tooltip position
1003
1004                oldtooltipContainer.style.display = "block";
1005                placeTooltip.call(self, targetElement.element, oldtooltipContainer, oldArrowLayer, oldHelperNumberLayer); //change active bullet
1006
1007                if (self._options.showBullets) {
1008                    oldReferenceLayer.querySelector(".introjs-bullets li > a.active").className = "";
1009                    oldReferenceLayer.querySelector(".introjs-bullets li > a[data-stepnumber=\"".concat(targetElement.step, "\"]")).className = "active";
1010                }
1011
1012                oldReferenceLayer.querySelector(".introjs-progress .introjs-progressbar").style.cssText = "width:".concat(_getProgress.call(self), "%;");
1013                oldReferenceLayer.querySelector(".introjs-progress .introjs-progressbar").setAttribute("aria-valuenow", _getProgress.call(self)); //show the tooltip
1014
1015                oldtooltipContainer.style.opacity = 1;
1016                if (oldHelperNumberLayer) oldHelperNumberLayer.style.opacity = 1; //reset button focus
1017
1018                if (typeof skipTooltipButton !== "undefined" && skipTooltipButton !== null && /introjs-donebutton/gi.test(skipTooltipButton.className)) {
1019                    // skip button is now "done" button
1020                    skipTooltipButton.focus();
1021                } else if (typeof nextTooltipButton !== "undefined" && nextTooltipButton !== null) {
1022                    //still in the tour, focus on next
1023                    nextTooltipButton.focus();
1024                } // change the scroll of the window, if needed
1025
1026
1027                scrollTo.call(self, targetElement.scrollTo, targetElement, oldtooltipLayer);
1028            }, 350); // end of old element if-else condition
1029        } else {
1030            var helperLayer = document.createElement("div");
1031            var referenceLayer = document.createElement("div");
1032            var arrowLayer = document.createElement("div");
1033            var tooltipLayer = document.createElement("div");
1034            var tooltipTextLayer = document.createElement("div");
1035            var bulletsLayer = document.createElement("div");
1036            var progressLayer = document.createElement("div");
1037            var buttonsLayer = document.createElement("div");
1038            helperLayer.className = highlightClass;
1039            referenceLayer.className = "introjs-tooltipReferenceLayer"; // scroll to element
1040
1041            scrollParent = getScrollParent(targetElement.element);
1042
1043            if (scrollParent !== document.body) {
1044                // target is within a scrollable element
1045                scrollParentToElement(scrollParent, targetElement.element);
1046            } //set new position to helper layer
1047
1048
1049            setHelperLayerPosition.call(self, helperLayer);
1050            setHelperLayerPosition.call(self, referenceLayer); //add helper layer to target element
1051
1052            this._targetElement.appendChild(helperLayer);
1053
1054            this._targetElement.appendChild(referenceLayer);
1055
1056            arrowLayer.className = "introjs-arrow";
1057            tooltipTextLayer.className = "introjs-tooltiptext";
1058            tooltipTextLayer.innerHTML = targetElement.intro;
1059            bulletsLayer.className = "introjs-bullets";
1060
1061            if (this._options.showBullets === false) {
1062                bulletsLayer.style.display = "none";
1063            }
1064
1065            var ulContainer = document.createElement("ul");
1066            ulContainer.setAttribute("role", "tablist");
1067
1068            var anchorClick = function anchorClick() {
1069                self.goToStep(this.getAttribute("data-stepnumber"));
1070            };
1071
1072            forEach(this._introItems, function (_ref, i) {
1073                var step = _ref.step;
1074                var innerLi = document.createElement("li");
1075                var anchorLink = document.createElement("a");
1076                innerLi.setAttribute("role", "presentation");
1077                anchorLink.setAttribute("role", "tab");
1078                anchorLink.onclick = anchorClick;
1079
1080                if (i === targetElement.step - 1) {
1081                    anchorLink.className = "active";
1082                }
1083
1084                setAnchorAsButton(anchorLink);
1085                anchorLink.innerHTML = "&nbsp;";
1086                anchorLink.setAttribute("data-stepnumber", step);
1087                innerLi.appendChild(anchorLink);
1088                ulContainer.appendChild(innerLi);
1089            });
1090            bulletsLayer.appendChild(ulContainer);
1091            progressLayer.className = "introjs-progress";
1092
1093            if (this._options.showProgress === false) {
1094                progressLayer.style.display = "none";
1095            }
1096
1097            var progressBar = document.createElement("div");
1098            progressBar.className = "introjs-progressbar";
1099            progressBar.setAttribute("role", "progress");
1100            progressBar.setAttribute("aria-valuemin", 0);
1101            progressBar.setAttribute("aria-valuemax", 100);
1102            progressBar.setAttribute("aria-valuenow", _getProgress.call(this));
1103            progressBar.style.cssText = "width:".concat(_getProgress.call(this), "%;");
1104            progressLayer.appendChild(progressBar);
1105            buttonsLayer.className = "introjs-tooltipbuttons";
1106
1107            if (this._options.showButtons === false) {
1108                buttonsLayer.style.display = "none";
1109            }
1110
1111            tooltipLayer.className = "introjs-tooltip";
1112            tooltipLayer.appendChild(tooltipTextLayer);
1113            tooltipLayer.appendChild(bulletsLayer);
1114            tooltipLayer.appendChild(progressLayer); //add helper layer number
1115
1116            var helperNumberLayer = document.createElement("span");
1117
1118            if (this._options.showStepNumbers === true) {
1119                helperNumberLayer.className = "introjs-helperNumberLayer";
1120                helperNumberLayer.innerHTML = targetElement.step;
1121                referenceLayer.appendChild(helperNumberLayer);
1122            }
1123
1124            tooltipLayer.appendChild(arrowLayer);
1125            referenceLayer.appendChild(tooltipLayer); //next button
1126
1127            nextTooltipButton = document.createElement("a");
1128
1129            nextTooltipButton.onclick = function () {
1130                if (self._introItems.length - 1 !== self._currentStep) {
1131                    nextStep.call(self);
1132                }
1133            };
1134
1135            setAnchorAsButton(nextTooltipButton);
1136            nextTooltipButton.innerHTML = this._options.nextLabel; //previous button
1137
1138            prevTooltipButton = document.createElement("a");
1139
1140            prevTooltipButton.onclick = function () {
1141                if (self._currentStep !== 0) {
1142                    previousStep.call(self);
1143                }
1144            };
1145
1146            setAnchorAsButton(prevTooltipButton);
1147            prevTooltipButton.innerHTML = this._options.prevLabel; //skip button
1148
1149            skipTooltipButton = document.createElement("a");
1150            skipTooltipButton.className = "".concat(this._options.buttonClass, " introjs-skipbutton ");
1151            setAnchorAsButton(skipTooltipButton);
1152            skipTooltipButton.innerHTML = this._options.skipLabel;
1153
1154            skipTooltipButton.onclick = function () {
1155                if (self._introItems.length - 1 === self._currentStep && typeof self._introCompleteCallback === "function") {
1156                    self._introCompleteCallback.call(self);
1157                }
1158
1159                if (typeof self._introSkipCallback === "function") {
1160                    self._introSkipCallback.call(self);
1161                }
1162
1163                exitIntro.call(self, self._targetElement);
1164            };
1165
1166            buttonsLayer.appendChild(skipTooltipButton); //in order to prevent displaying next/previous button always
1167
1168            if (this._introItems.length > 1) {
1169                buttonsLayer.appendChild(prevTooltipButton);
1170                buttonsLayer.appendChild(nextTooltipButton);
1171            }
1172
1173            tooltipLayer.appendChild(buttonsLayer); //set proper position
1174
1175            placeTooltip.call(self, targetElement.element, tooltipLayer, arrowLayer, helperNumberLayer); // change the scroll of the window, if needed
1176
1177            scrollTo.call(this, targetElement.scrollTo, targetElement, tooltipLayer); //end of new element if-else condition
1178        } // removing previous disable interaction layer
1179
1180
1181        var disableInteractionLayer = self._targetElement.querySelector(".introjs-disableInteraction");
1182
1183        if (disableInteractionLayer) {
1184            disableInteractionLayer.parentNode.removeChild(disableInteractionLayer);
1185        } //disable interaction
1186
1187
1188        if (targetElement.disableInteraction) {
1189            _disableInteraction.call(self);
1190        } // when it's the first step of tour
1191
1192
1193        if (this._currentStep === 0 && this._introItems.length > 1) {
1194            if (typeof skipTooltipButton !== "undefined" && skipTooltipButton !== null) {
1195                skipTooltipButton.className = "".concat(this._options.buttonClass, " introjs-skipbutton");
1196            }
1197
1198            if (typeof nextTooltipButton !== "undefined" && nextTooltipButton !== null) {
1199                nextTooltipButton.className = "".concat(this._options.buttonClass, " introjs-nextbutton");
1200            }
1201
1202            if (this._options.hidePrev === true) {
1203                if (typeof prevTooltipButton !== "undefined" && prevTooltipButton !== null) {
1204                    prevTooltipButton.className = "".concat(this._options.buttonClass, " introjs-prevbutton introjs-hidden");
1205                }
1206
1207                if (typeof nextTooltipButton !== "undefined" && nextTooltipButton !== null) {
1208                    addClass(nextTooltipButton, "introjs-fullbutton");
1209                }
1210            } else {
1211                if (typeof prevTooltipButton !== "undefined" && prevTooltipButton !== null) {
1212                    prevTooltipButton.className = "".concat(this._options.buttonClass, " introjs-prevbutton introjs-disabled");
1213                }
1214            }
1215
1216            if (typeof skipTooltipButton !== "undefined" && skipTooltipButton !== null) {
1217                skipTooltipButton.innerHTML = this._options.skipLabel;
1218            }
1219        } else if (this._introItems.length - 1 === this._currentStep || this._introItems.length === 1) {
1220            // last step of tour
1221            if (typeof skipTooltipButton !== "undefined" && skipTooltipButton !== null) {
1222                skipTooltipButton.innerHTML = this._options.doneLabel; // adding donebutton class in addition to skipbutton
1223
1224                addClass(skipTooltipButton, "introjs-donebutton");
1225            }
1226
1227            if (typeof prevTooltipButton !== "undefined" && prevTooltipButton !== null) {
1228                prevTooltipButton.className = "".concat(this._options.buttonClass, " introjs-prevbutton");
1229            }
1230
1231            if (this._options.hideNext === true) {
1232                if (typeof nextTooltipButton !== "undefined" && nextTooltipButton !== null) {
1233                    nextTooltipButton.className = "".concat(this._options.buttonClass, " introjs-nextbutton introjs-hidden");
1234                }
1235
1236                if (typeof prevTooltipButton !== "undefined" && prevTooltipButton !== null) {
1237                    addClass(prevTooltipButton, "introjs-fullbutton");
1238                }
1239            } else {
1240                if (typeof nextTooltipButton !== "undefined" && nextTooltipButton !== null) {
1241                    nextTooltipButton.className = "".concat(this._options.buttonClass, " introjs-nextbutton introjs-disabled");
1242                }
1243            }
1244        } else {
1245            // steps between start and end
1246            if (typeof skipTooltipButton !== "undefined" && skipTooltipButton !== null) {
1247                skipTooltipButton.className = "".concat(this._options.buttonClass, " introjs-skipbutton");
1248            }
1249
1250            if (typeof prevTooltipButton !== "undefined" && prevTooltipButton !== null) {
1251                prevTooltipButton.className = "".concat(this._options.buttonClass, " introjs-prevbutton");
1252            }
1253
1254            if (typeof nextTooltipButton !== "undefined" && nextTooltipButton !== null) {
1255                nextTooltipButton.className = "".concat(this._options.buttonClass, " introjs-nextbutton");
1256            }
1257
1258            if (typeof skipTooltipButton !== "undefined" && skipTooltipButton !== null) {
1259                skipTooltipButton.innerHTML = this._options.skipLabel;
1260            }
1261        }
1262
1263        if (typeof prevTooltipButton !== "undefined" && prevTooltipButton !== null) {
1264            prevTooltipButton.setAttribute("role", "button");
1265        }
1266
1267        if (typeof nextTooltipButton !== "undefined" && nextTooltipButton !== null) {
1268            nextTooltipButton.setAttribute("role", "button");
1269        }
1270
1271        if (typeof skipTooltipButton !== "undefined" && skipTooltipButton !== null) {
1272            skipTooltipButton.setAttribute("role", "button");
1273        } //Set focus on "next" button, so that hitting Enter always moves you onto the next step
1274
1275
1276        if (typeof nextTooltipButton !== "undefined" && nextTooltipButton !== null) {
1277            nextTooltipButton.focus();
1278        }
1279
1280        setShowElement(targetElement);
1281
1282        if (typeof this._introAfterChangeCallback !== "undefined") {
1283            this._introAfterChangeCallback.call(this, targetElement.element);
1284        }
1285    }
1286
1287    /**
1288     * Go to specific step of introduction
1289     *
1290     * @api private
1291     * @method _goToStep
1292     */
1293
1294    function goToStep(step) {
1295        //because steps starts with zero
1296        this._currentStep = step - 2;
1297
1298        if (typeof this._introItems !== "undefined") {
1299            nextStep.call(this);
1300        }
1301    }
1302    /**
1303     * Go to the specific step of introduction with the explicit [data-step] number
1304     *
1305     * @api private
1306     * @method _goToStepNumber
1307     */
1308
1309    function goToStepNumber(step) {
1310        this._currentStepNumber = step;
1311
1312        if (typeof this._introItems !== "undefined") {
1313            nextStep.call(this);
1314        }
1315    }
1316    /**
1317     * Go to next step on intro
1318     *
1319     * @api private
1320     * @method _nextStep
1321     */
1322
1323    function nextStep() {
1324        var _this = this;
1325
1326        this._direction = "forward";
1327
1328        if (typeof this._currentStepNumber !== "undefined") {
1329            forEach(this._introItems, function (_ref, i) {
1330                var step = _ref.step;
1331
1332                if (step === _this._currentStepNumber) {
1333                    _this._currentStep = i - 1;
1334                    _this._currentStepNumber = undefined;
1335                }
1336            });
1337        }
1338
1339        if (typeof this._currentStep === "undefined") {
1340            this._currentStep = 0;
1341        } else {
1342            ++this._currentStep;
1343        }
1344
1345        var nextStep = this._introItems[this._currentStep];
1346        var continueStep = true;
1347
1348        if (typeof this._introBeforeChangeCallback !== "undefined") {
1349            continueStep = this._introBeforeChangeCallback.call(this, nextStep.element);
1350        } // if `onbeforechange` returned `false`, stop displaying the element
1351
1352
1353        if (continueStep === false) {
1354            --this._currentStep;
1355            return false;
1356        }
1357
1358        if (this._introItems.length <= this._currentStep) {
1359            //end of the intro
1360            //check if any callback is defined
1361            if (typeof this._introCompleteCallback === "function") {
1362                this._introCompleteCallback.call(this);
1363            }
1364
1365            exitIntro.call(this, this._targetElement);
1366            return;
1367        }
1368
1369        _showElement.call(this, nextStep);
1370    }
1371    /**
1372     * Go to previous step on intro
1373     *
1374     * @api private
1375     * @method _previousStep
1376     */
1377
1378    function previousStep() {
1379        this._direction = "backward";
1380
1381        if (this._currentStep === 0) {
1382            return false;
1383        }
1384
1385        --this._currentStep;
1386        var nextStep = this._introItems[this._currentStep];
1387        var continueStep = true;
1388
1389        if (typeof this._introBeforeChangeCallback !== "undefined") {
1390            continueStep = this._introBeforeChangeCallback.call(this, nextStep.element);
1391        } // if `onbeforechange` returned `false`, stop displaying the element
1392
1393
1394        if (continueStep === false) {
1395            ++this._currentStep;
1396            return false;
1397        }
1398
1399        _showElement.call(this, nextStep);
1400    }
1401    /**
1402     * Returns the current step of the intro
1403     *
1404     * @returns {boolean}
1405     */
1406
1407    function currentStep() {
1408        return this._currentStep;
1409    }
1410
1411    /**
1412     * on keyCode:
1413     * https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode
1414     * This feature has been removed from the Web standards.
1415     * Though some browsers may still support it, it is in
1416     * the process of being dropped.
1417     * Instead, you should use KeyboardEvent.code,
1418     * if it's implemented.
1419     *
1420     * jQuery's approach is to test for
1421     *   (1) e.which, then
1422     *   (2) e.charCode, then
1423     *   (3) e.keyCode
1424     * https://github.com/jquery/jquery/blob/a6b0705294d336ae2f63f7276de0da1195495363/src/event.js#L638
1425     *
1426     * @param type var
1427     * @return type
1428     */
1429
1430    function onKeyDown(e) {
1431        var code = e.code === null ? e.which : e.code; // if code/e.which is null
1432
1433        if (code === null) {
1434            code = e.charCode === null ? e.keyCode : e.charCode;
1435        }
1436
1437        if ((code === "Escape" || code === 27) && this._options.exitOnEsc === true) {
1438            //escape key pressed, exit the intro
1439            //check if exit callback is defined
1440            exitIntro.call(this, this._targetElement);
1441        } else if (code === "ArrowLeft" || code === 37) {
1442            //left arrow
1443            previousStep.call(this);
1444        } else if (code === "ArrowRight" || code === 39) {
1445            //right arrow
1446            nextStep.call(this);
1447        } else if (code === "Enter" || code === 13) {
1448            //srcElement === ie
1449            var target = e.target || e.srcElement;
1450
1451            if (target && target.className.match("introjs-prevbutton")) {
1452                //user hit enter while focusing on previous button
1453                previousStep.call(this);
1454            } else if (target && target.className.match("introjs-skipbutton")) {
1455                //user hit enter while focusing on skip button
1456                if (this._introItems.length - 1 === this._currentStep && typeof this._introCompleteCallback === "function") {
1457                    this._introCompleteCallback.call(this);
1458                }
1459
1460                exitIntro.call(this, this._targetElement);
1461            } else if (target && target.getAttribute("data-stepnumber")) {
1462                // user hit enter while focusing on step bullet
1463                target.click();
1464            } else {
1465                //default behavior for responding to enter
1466                nextStep.call(this);
1467            } //prevent default behaviour on hitting Enter, to prevent steps being skipped in some browsers
1468
1469
1470            if (e.preventDefault) {
1471                e.preventDefault();
1472            } else {
1473                e.returnValue = false;
1474            }
1475        }
1476    }
1477
1478    /*
1479     * makes a copy of the object
1480     * @api private
1481     * @method _cloneObject
1482     */
1483    function cloneObject(object) {
1484        if (object === null || _typeof(object) !== "object" || typeof object.nodeType !== "undefined") {
1485            return object;
1486        }
1487
1488        var temp = {};
1489
1490        for (var key in object) {
1491            if (typeof window.jQuery !== "undefined" && object[key] instanceof window.jQuery) {
1492                temp[key] = object[key];
1493            } else {
1494                temp[key] = cloneObject(object[key]);
1495            }
1496        }
1497
1498        return temp;
1499    }
1500
1501    /**
1502     * Get a queryselector within the hint wrapper
1503     *
1504     * @param {String} selector
1505     * @return {NodeList|Array}
1506     */
1507
1508    function hintQuerySelectorAll(selector) {
1509        var hintsWrapper = document.querySelector(".introjs-hints");
1510        return hintsWrapper ? hintsWrapper.querySelectorAll(selector) : [];
1511    }
1512    /**
1513     * Hide a hint
1514     *
1515     * @api private
1516     * @method hideHint
1517     */
1518
1519    function hideHint(stepId) {
1520        var hint = hintQuerySelectorAll(".introjs-hint[data-step=\"".concat(stepId, "\"]"))[0];
1521        removeHintTooltip.call(this);
1522
1523        if (hint) {
1524            addClass(hint, "introjs-hidehint");
1525        } // call the callback function (if any)
1526
1527
1528        if (typeof this._hintCloseCallback !== "undefined") {
1529            this._hintCloseCallback.call(this, stepId);
1530        }
1531    }
1532    /**
1533     * Hide all hints
1534     *
1535     * @api private
1536     * @method hideHints
1537     */
1538
1539    function hideHints() {
1540        var _this = this;
1541
1542        var hints = hintQuerySelectorAll(".introjs-hint");
1543        forEach(hints, function (hint) {
1544            hideHint.call(_this, hint.getAttribute("data-step"));
1545        });
1546    }
1547    /**
1548     * Show all hints
1549     *
1550     * @api private
1551     * @method _showHints
1552     */
1553
1554    function showHints() {
1555        var _this2 = this;
1556
1557        var hints = hintQuerySelectorAll(".introjs-hint");
1558
1559        if (hints && hints.length) {
1560            forEach(hints, function (hint) {
1561                showHint.call(_this2, hint.getAttribute("data-step"));
1562            });
1563        } else {
1564            populateHints.call(this, this._targetElement);
1565        }
1566    }
1567    /**
1568     * Show a hint
1569     *
1570     * @api private
1571     * @method showHint
1572     */
1573
1574    function showHint(stepId) {
1575        var hint = hintQuerySelectorAll(".introjs-hint[data-step=\"".concat(stepId, "\"]"))[0];
1576
1577        if (hint) {
1578            removeClass(hint, /introjs-hidehint/g);
1579        }
1580    }
1581    /**
1582     * Removes all hint elements on the page
1583     * Useful when you want to destroy the elements and add them again (e.g. a modal or popup)
1584     *
1585     * @api private
1586     * @method removeHints
1587     */
1588
1589    function removeHints() {
1590        var _this3 = this;
1591
1592        var hints = hintQuerySelectorAll(".introjs-hint");
1593        forEach(hints, function (hint) {
1594            removeHint.call(_this3, hint.getAttribute("data-step"));
1595        });
1596    }
1597    /**
1598     * Remove one single hint element from the page
1599     * Useful when you want to destroy the element and add them again (e.g. a modal or popup)
1600     * Use removeHints if you want to remove all elements.
1601     *
1602     * @api private
1603     * @method removeHint
1604     */
1605
1606    function removeHint(stepId) {
1607        var hint = hintQuerySelectorAll(".introjs-hint[data-step=\"".concat(stepId, "\"]"))[0];
1608
1609        if (hint) {
1610            hint.parentNode.removeChild(hint);
1611        }
1612    }
1613    /**
1614     * Add all available hints to the page
1615     *
1616     * @api private
1617     * @method addHints
1618     */
1619
1620    function addHints() {
1621        var _this4 = this;
1622
1623        var self = this;
1624        var hintsWrapper = document.querySelector(".introjs-hints");
1625
1626        if (hintsWrapper === null) {
1627            hintsWrapper = document.createElement("div");
1628            hintsWrapper.className = "introjs-hints";
1629        }
1630        /**
1631         * Returns an event handler unique to the hint iteration
1632         *
1633         * @param {Integer} i
1634         * @return {Function}
1635         */
1636
1637
1638        var getHintClick = function getHintClick(i) {
1639            return function (e) {
1640                var evt = e ? e : window.event;
1641
1642                if (evt.stopPropagation) {
1643                    evt.stopPropagation();
1644                }
1645
1646                if (evt.cancelBubble !== null) {
1647                    evt.cancelBubble = true;
1648                }
1649
1650                showHintDialog.call(self, i);
1651            };
1652        };
1653
1654        forEach(this._introItems, function (item, i) {
1655            // avoid append a hint twice
1656            if (document.querySelector(".introjs-hint[data-step=\"".concat(i, "\"]"))) {
1657                return;
1658            }
1659
1660            var hint = document.createElement("a");
1661            setAnchorAsButton(hint);
1662            hint.onclick = getHintClick(i);
1663            hint.className = "introjs-hint";
1664
1665            if (!item.hintAnimation) {
1666                addClass(hint, "introjs-hint-no-anim");
1667            } // hint's position should be fixed if the target element's position is fixed
1668
1669
1670            if (isFixed(item.element)) {
1671                addClass(hint, "introjs-fixedhint");
1672            }
1673
1674            var hintDot = document.createElement("div");
1675            hintDot.className = "introjs-hint-dot";
1676            var hintPulse = document.createElement("div");
1677            hintPulse.className = "introjs-hint-pulse";
1678            hint.appendChild(hintDot);
1679            hint.appendChild(hintPulse);
1680            hint.setAttribute("data-step", i); // we swap the hint element with target element
1681            // because _setHelperLayerPosition uses `element` property
1682
1683            item.targetElement = item.element;
1684            item.element = hint; // align the hint position
1685
1686            alignHintPosition.call(_this4, item.hintPosition, hint, item.targetElement);
1687            hintsWrapper.appendChild(hint);
1688        }); // adding the hints wrapper
1689
1690        document.body.appendChild(hintsWrapper); // call the callback function (if any)
1691
1692        if (typeof this._hintsAddedCallback !== "undefined") {
1693            this._hintsAddedCallback.call(this);
1694        }
1695    }
1696    /**
1697     * Aligns hint position
1698     *
1699     * @api private
1700     * @method alignHintPosition
1701     * @param {String} position
1702     * @param {Object} hint
1703     * @param {Object} element
1704     */
1705
1706    function alignHintPosition(position, _ref, element) {
1707        var style = _ref.style;
1708        // get/calculate offset of target element
1709        var offset = getOffset.call(this, element);
1710        var iconWidth = 20;
1711        var iconHeight = 20; // align the hint element
1712
1713        switch (position) {
1714            default:
1715            case "top-left":
1716                style.left = "".concat(offset.left, "px");
1717                style.top = "".concat(offset.top, "px");
1718                break;
1719
1720            case "top-right":
1721                style.left = "".concat(offset.left + offset.width - iconWidth, "px");
1722                style.top = "".concat(offset.top, "px");
1723                break;
1724
1725            case "bottom-left":
1726                style.left = "".concat(offset.left, "px");
1727                style.top = "".concat(offset.top + offset.height - iconHeight, "px");
1728                break;
1729
1730            case "bottom-right":
1731                style.left = "".concat(offset.left + offset.width - iconWidth, "px");
1732                style.top = "".concat(offset.top + offset.height - iconHeight, "px");
1733                break;
1734
1735            case "middle-left":
1736                style.left = "".concat(offset.left, "px");
1737                style.top = "".concat(offset.top + (offset.height - iconHeight) / 2, "px");
1738                break;
1739
1740            case "middle-right":
1741                style.left = "".concat(offset.left + offset.width - iconWidth, "px");
1742                style.top = "".concat(offset.top + (offset.height - iconHeight) / 2, "px");
1743                break;
1744
1745            case "middle-middle":
1746                style.left = "".concat(offset.left + (offset.width - iconWidth) / 2, "px");
1747                style.top = "".concat(offset.top + (offset.height - iconHeight) / 2, "px");
1748                break;
1749
1750            case "bottom-middle":
1751                style.left = "".concat(offset.left + (offset.width - iconWidth) / 2, "px");
1752                style.top = "".concat(offset.top + offset.height - iconHeight, "px");
1753                break;
1754
1755            case "top-middle":
1756                style.left = "".concat(offset.left + (offset.width - iconWidth) / 2, "px");
1757                style.top = "".concat(offset.top, "px");
1758                break;
1759        }
1760    }
1761    /**
1762     * Triggers when user clicks on the hint element
1763     *
1764     * @api private
1765     * @method _showHintDialog
1766     * @param {Number} stepId
1767     */
1768
1769    function showHintDialog(stepId) {
1770        var hintElement = document.querySelector(".introjs-hint[data-step=\"".concat(stepId, "\"]"));
1771        var item = this._introItems[stepId]; // call the callback function (if any)
1772
1773        if (typeof this._hintClickCallback !== "undefined") {
1774            this._hintClickCallback.call(this, hintElement, item, stepId
1774);
1775        } // remove all open tooltips
1776
1777
1778        var removedStep = removeHintTooltip.call(this); // to toggle the tooltip
1779
1780        if (parseInt(removedStep, 10) === stepId) {
1781            return;
1782        }
1783
1784        var tooltipLayer = document.createElement("div");
1785        var tooltipTextLayer = document.createElement("div");
1786        var arrowLayer = document.createElement("div");
1787        var referenceLayer = document.createElement("div");
1788        tooltipLayer.className = "introjs-tooltip";
1789
1790        tooltipLayer.onclick = function (e) {
1791            //IE9 & Other Browsers
1792            if (e.stopPropagation) {
1793                e.stopPropagation();
1794            } //IE8 and Lower
1795            else {
1796                e.cancelBubble = true;
1797            }
1798        };
1799
1800        tooltipTextLayer.className = "introjs-tooltiptext";
1801        var tooltipWrapper = document.createElement("p");
1802        tooltipWrapper.innerHTML = item.hint;
1803        var closeButton = document.createElement("a");
1804        closeButton.className = this._options.buttonClass;
1805        closeButton.setAttribute("role", "button");
1806        closeButton.innerHTML = this._options.hintButtonLabel;
1807        closeButton.onclick = hideHint.bind(this, stepId);
1808        tooltipTextLayer.appendChild(tooltipWrapper);
1809        tooltipTextLayer.appendChild(closeButton);
1810        arrowLayer.className = "introjs-arrow";
1811        tooltipLayer.appendChild(arrowLayer);
1812        tooltipLayer.appendChild(tooltipTextLayer); // set current step for _placeTooltip function
1813
1814        this._currentStep = hintElement.getAttribute("data-step"); // align reference layer position
1815
1816        referenceLayer.className = "introjs-tooltipReferenceLayer introjs-hintReference";
1817        referenceLayer.setAttribute("data-step", hintElement.getAttribute("data-step"));
1818        setHelperLayerPosition.call(this, referenceLayer);
1819        referenceLayer.appendChild(tooltipLayer);
1820        document.body.appendChild(referenceLayer); //set proper position
1821
1822        placeTooltip.call(this, hintElement, tooltipLayer, arrowLayer, null, true);
1823    }
1824    /**
1825     * Removes open hint (tooltip hint)
1826     *
1827     * @api private
1828     * @method _removeHintTooltip
1829     */
1830
1831    function removeHintTooltip() {
1832        var tooltip = document.querySelector(".introjs-hintReference");
1833
1834        if (tooltip) {
1835            var step = tooltip.getAttribute("data-step");
1836            tooltip.parentNode.removeChild(tooltip);
1837            return step;
1838        }
1839    }
1840    /**
1841     * Start parsing hint items
1842     *
1843     * @api private
1844     * @param {Object} targetElm
1845     * @method _startHint
1846     */
1847
1848    function populateHints(targetElm) {
1849        var _this5 = this;
1850
1851        this._introItems = [];
1852
1853        if (this._options.hints) {
1854            forEach(this._options.hints, function (hint) {
1855                var currentItem = cloneObject(hint);
1856
1857                if (typeof currentItem.element === "string") {
1858                    //grab the element with given selector from the page
1859                    currentItem.element = document.querySelector(currentItem.element);
1860                }
1861
1862                currentItem.hintPosition = currentItem.hintPosition || _this5._options.hintPosition;
1863                currentItem.hintAnimation = currentItem.hintAnimation || _this5._options.hintAnimation;
1864
1865                if (currentItem.element !== null) {
1866                    _this5._introItems.push(currentItem);
1867                }
1868            });
1869        } else {
1870            var hints = targetElm.querySelectorAll("*[data-hint]");
1871
1872            if (!hints || !hints.length) {
1873                return false;
1874            } //first add intro items with data-step
1875
1876
1877            forEach(hints, function (currentElement) {
1878                // hint animation
1879                var hintAnimation = currentElement.getAttribute("data-hintanimation");
1880
1881                if (hintAnimation) {
1882                    hintAnimation = hintAnimation === "true";
1883                } else {
1884                    hintAnimation = _this5._options.hintAnimation;
1885                }
1886
1887                _this5._introItems.push({
1888                    element: currentElement,
1889                    hint: currentElement.getAttribute("data-hint"),
1890                    hintPosition: currentElement.getAttribute("data-hintposition") || _this5._options.hintPosition,
1891                    hintAnimation: hintAnimation,
1892                    tooltipClass: currentElement.getAttribute("data-tooltipclass"),
1893                    position: currentElement.getAttribute("data-position") || _this5._options.tooltipPosition
1894                });
1895            });
1896        }
1897
1898        addHints.call(this);
1899        /*
1900        todo:
1901        these events should be removed at some point
1902        */
1903
1904        DOMEvent.on(document, "click", removeHintTooltip, this, false);
1905        DOMEvent.on(window, "resize", reAlignHints, this, true);
1906    }
1907    /**
1908     * Re-aligns all hint elements
1909     *
1910     * @api private
1911     * @method _reAlignHints
1912     */
1913
1914    function reAlignHints() {
1915        var _this6 = this;
1916
1917        forEach(this._introItems, function (_ref2) {
1918            var targetElement = _ref2.targetElement,
1919                hintPosition = _ref2.hintPosition,
1920                element = _ref2.element;
1921
1922            if (typeof targetElement === "undefined") {
1923                return;
1924            }
1925
1926            alignHintPosition.call(_this6, hintPosition, element, targetElement);
1927        });
1928    }
1929
1930    /**
1931     * Update placement of the intro objects on the screen
1932     * @api private
1933     */
1934
1935    function refresh() {
1936        // re-align intros
1937        setHelperLayerPosition.call(this, document.querySelector(".introjs-helperLayer"));
1938        setHelperLayerPosition.call(this, document.querySelector(".introjs-tooltipReferenceLayer"));
1939        setHelperLayerPosition.call(this, document.querySelector(".introjs-disableInteraction")); // re-align tooltip
1940
1941        if (this._currentStep !== undefined && this._currentStep !== null) {
1942            var oldHelperNumberLayer = document.querySelector(".introjs-helperNumberLayer");
1943            var oldArrowLayer = document.querySelector(".introjs-arrow");
1944            var oldtooltipContainer = document.querySelector(".introjs-tooltip");
1945            placeTooltip.call(this, this._introItems[this._currentStep].element, oldtooltipContainer, oldArrowLayer, oldHelperNumberLayer);
1946        } //re-align hints
1947
1948
1949        reAlignHints.call(this);
1950        return this;
1951    }
1952
1953    function onResize() {
1954        refresh.call(this);
1955    }
1956
1957    /**
1958     * Exit from intro
1959     *
1960     * @api private
1961     * @method _exitIntro
1962     * @param {Object} targetElement
1963     * @param {Boolean} force - Setting to `true` will skip the result of beforeExit callback
1964     */
1965
1966    function exitIntro(targetElement, force) {
1967        var continueExit = true; // calling onbeforeexit callback
1968        //
1969        // If this callback return `false`, it would halt the process
1970
1971        if (this._introBeforeExitCallback !== undefined) {
1972            continueExit = this._introBeforeExitCallback.call(this);
1973        } // skip this check if `force` parameter is `true`
1974        // otherwise, if `onbeforeexit` returned `false`, don't exit the intro
1975
1976
1977        if (!force && continueExit === false) return; //remove overlay layers from the page
1978
1979        var overlayLayers = targetElement.querySelectorAll(".introjs-overlay");
1980
1981        if (overlayLayers && overlayLayers.length) {
1982            forEach(overlayLayers, function (overlayLayer) {
1983                overlayLayer.style.opacity = 0;
1984                window.setTimeout(function () {
1985                    if (this.parentNode) {
1986                        this.parentNode.removeChild(this);
1987                    }
1988                }.bind(overlayLayer), 500);
1989            });
1990        } //remove all helper layers
1991
1992
1993        var helperLayer = targetElement.querySelector(".introjs-helperLayer");
1994
1995        if (helperLayer) {
1996            helperLayer.parentNode.removeChild(helperLayer);
1997        }
1998
1999        var referenceLayer = targetElement.querySelector(".introjs-tooltipReferenceLayer");
2000
2001        if (referenceLayer) {
2002            referenceLayer.parentNode.removeChild(referenceLayer);
2003        } //remove disableInteractionLayer
2004
2005
2006        var disableInteractionLayer = targetElement.querySelector(".introjs-disableInteraction");
2007
2008        if (disableInteractionLayer) {
2009            disableInteractionLayer.parentNode.removeChild(disableInteractionLayer);
2010        } //remove intro floating element
2011
2012
2013        var floatingElement = document.querySelector(".introjsFloatingElement");
2014
2015        if (floatingElement) {
2016            floatingElement.parentNode.removeChild(floatingElement);
2017        }
2018
2019        removeShowElement(); //remove `introjs-fixParent` class from the elements
2020
2021        var fixParents = document.querySelectorAll(".introjs-fixParent");
2022        forEach(fixParents, function (parent) {
2023            removeClass(parent, /introjs-fixParent/g);
2024        }); //clean listeners
2025
2026        DOMEvent.off(window, "keydown", onKeyDown, this, true);
2027        DOMEvent.off(window, "resize", onResize, this, true); //check if any callback is defined
2028
2029        if (this._introExitCallback !== undefined) {
2030            this._introExitCallback.call(this);
2031        } //set the step to zero
2032
2033
2034        this._currentStep = undefined;
2035    }
2036
2037    /**
2038     * Add overlay layer to the page
2039     *
2040     * @api private
2041     * @method _addOverlayLayer
2042     * @param {Object} targetElm
2043     */
2044
2045    function addOverlayLayer(targetElm) {
2046        var overlayLayer = document.createElement("div");
2047        var styleText = "";
2048        var self = this; //set css class name
2049
2050        overlayLayer.className = "introjs-overlay"; //check if the target element is body, we should calculate the size of overlay layer in a better way
2051
2052        if (!targetElm.tagName || targetElm.tagName.toLowerCase() === "body") {
2053            styleText += "top: 0;bottom: 0; left: 0;right: 0;position: fixed;";
2054            overlayLayer.style.cssText = styleText;
2055        } else {
2056            //set overlay layer position
2057            var elementPosition = getOffset(targetElm);
2058
2059            if (elementPosition) {
2060                styleText += "width: ".concat(elementPosition.width, "px; height:").concat(elementPosition.height, "px; top:").concat(elementPosition.top, "px;left: ").concat(elementPosition.left, "px;");
2061                overlayLayer.style.cssText = styleText;
2062            }
2063        }
2064
2065        targetElm.appendChild(overlayLayer);
2066
2067        overlayLayer.onclick = function () {
2068            if (self._options.exitOnOverlayClick === true) {
2069                exitIntro.call(self, targetElm);
2070            }
2071        };
2072
2073        window.setTimeout(function () {
2074            styleText += "opacity: ".concat(self._options.overlayOpacity.toString(), ";");
2075            overlayLayer.style.cssText = styleText;
2076        }, 10);
2077        return true;
2078    }
2079
2080    /**
2081     * Initiate a new introduction/guide from an element in the page
2082     *
2083     * @api private
2084     * @method _introForElement
2085     * @param {Object} targetElm
2086     * @param {String} group
2087     * @returns {Boolean} Success or not?
2088     */
2089
2090    function introForElement(targetElm, group) {
2091        var _this = this;
2092
2093        var allIntroSteps = targetElm.querySelectorAll("*[data-intro]");
2094        var introItems = [];
2095
2096        if (this._options.steps) {
2097            //use steps passed programmatically
2098            forEach(this._options.steps, function (step) {
2099                var currentItem = cloneObject(step); //set the step
2100
2101                currentItem.step = introItems.length + 1; //use querySelector function only when developer used CSS selector
2102
2103                if (typeof currentItem.element === "string") {
2104                    //grab the element with given selector from the page
2105                    currentItem.element = document.querySelector(currentItem.element);
2106                } //intro without element
2107
2108
2109                if (typeof currentItem.element === "undefined" || currentItem.element === null) {
2110                    var floatingElementQuery = document.querySelector(".introjsFloatingElement");
2111
2112                    if (floatingElementQuery === null) {
2113                        floatingElementQuery = document.createElement("div");
2114                        floatingElementQuery.className = "introjsFloatingElement";
2115                        document.body.appendChild(floatingElementQuery);
2116                    }
2117
2118                    currentItem.element = floatingElementQuery;
2119                    currentItem.position = "floating";
2120                }
2121
2122                currentItem.scrollTo = currentItem.scrollTo || _this._options.scrollTo;
2123
2124                if (typeof currentItem.disableInteraction === "undefined") {
2125                    currentItem.disableInteraction = _this._options.disableInteraction;
2126                }
2127
2128                if (currentItem.element !== null) {
2129                    introItems.push(currentItem);
2130                }
2131            });
2132        } else {
2133            //use steps from data-* annotations
2134            var elmsLength = allIntroSteps.length;
2135            var disableInteraction; //if there's no element to intro
2136
2137            if (elmsLength < 1) {
2138                return false;
2139            }
2140
2141            forEach(allIntroSteps, function (currentElement) {
2142                // PR #80
2143                // start intro for groups of elements
2144                if (group && currentElement.getAttribute("data-intro-group") !== group) {
2145                    return;
2146                } // skip hidden elements
2147
2148
2149                if (currentElement.style.display === "none") {
2150                    return;
2151                }
2152
2153                var step = parseInt(currentElement.getAttribute("data-step"), 10);
2154
2155                if (typeof currentElement.getAttribute("data-disable-interaction") !== "undefined") {
2156                    disableInteraction = !!currentElement.getAttribute("data-disable-interaction");
2157                } else {
2158                    disableInteraction = _this._options.disableInteraction;
2159                }
2160
2161                if (step > 0) {
2162                    introItems[step - 1] = {
2163                        element: currentElement,
2164                        intro: currentElement.getAttribute("data-intro"),
2165                        step: parseInt(currentElement.getAttribute("data-step"), 10),
2166                        tooltipClass: currentElement.getAttribute("data-tooltipclass"),
2167                        highlightClass: currentElement.getAttribute("data-highlightclass"),
2168                        position: currentElement.getAttribute("data-position") || _this._options.tooltipPosition,
2169                        scrollTo: currentElement.getAttribute("data-scrollto") || _this._options.scrollTo,
2170                        disableInteraction: disableInteraction
2171                    };
2172                }
2173            }); //next add intro items without data-step
2174            //todo: we need a cleanup here, two loops are redundant
2175
2176            var _nextStep = 0;
2177            forEach(allIntroSteps, function (currentElement) {
2178                // PR #80
2179                // start intro for groups of elements
2180                if (group && currentElement.getAttribute("data-intro-group") !== group) {
2181                    return;
2182                }
2183
2184                if (currentElement.getAttribute("data-step") === null) {
2185                    while (true) {
2186                        if (typeof introItems[_nextStep] === "undefined") {
2187                            break;
2188                        } else {
2189                            _nextStep++;
2190                        }
2191                    }
2192
2193                    if (typeof currentElement.getAttribute("data-disable-interaction") !== "undefined") {
2194                        disableInteraction = !!currentElement.getAttribute("data-disable-interaction");
2195                    } else {
2196                        disableInteraction = _this._options.disableInteraction;
2197                    }
2198
2199                    introItems[_nextStep] = {
2200                        element: currentElement,
2201                        intro: currentElement.getAttribute("data-intro"),
2202                        step: _nextStep + 1,
2203                        tooltipClass: currentElement.getAttribute("data-tooltipclass"),
2204                        highlightClass: currentElement.getAttribute("data-highlightclass"),
2205                        position: currentElement.getAttribute("data-position") || _this._options.tooltipPosition,
2206                        scrollTo: currentElement.getAttribute("data-scrollto") || _this._options.scrollTo,
2207                        disableInteraction: disableInteraction
2208                    };
2209                }
2210            });
2211        } //removing undefined/null elements
2212
2213
2214        var tempIntroItems = [];
2215
2216        for (var z = 0; z < introItems.length; z++) {
2217            if (introItems[z]) {
2218                // copy non-falsy values to the end of the array
2219                tempIntroItems.push(introItems[z]);
2220            }
2221        }
2222
2223        introItems = tempIntroItems; //Ok, sort all items with given steps
2224
2225        introItems.sort(function (a, b) {
2226            return a.step - b.step;
2227        }); //set it to the introJs object
2228
2229        this._introItems = introItems; //add overlay layer to the page
2230
2231        if (addOverlayLayer.call(this, targetElm)) {
2232            //then, start the show
2233            nextStep.call(this);
2234
2235            if (this._options.keyboardNavigation) {
2236                DOMEvent.on(window, "keydown", onKeyDown, this, true);
2237            } //for window resize
2238
2239
2240            DOMEvent.on(window, "resize", onResize, this, true);
2241        }
2242
2243        return false;
2244    }
2245
2246    var version = "3.0.1";
2247
2248    /**
2249     * IntroJs main class
2250     *
2251     * @class IntroJs
2252     */
2253
2254    function IntroJs(obj) {
2255        this._targetElement = obj;
2256        this._introItems = [];
2257        this._options = {
2258            /* Next button label in tooltip box */
2259            nextLabel: "Next &rarr;",
2260
2261            /* Previous button label in tooltip box */
2262            prevLabel: "&larr; Back",
2263
2264            /* Skip button label in tooltip box */
2265            skipLabel: "Skip",
2266
2267            /* Done button label in tooltip box */
2268            doneLabel: "Done",
2269
2270            /* Hide previous button in the first step? Otherwise, it will be disabled button. */
2271            hidePrev: false,
2272
2273            /* Hide next button in the last step? Otherwise, it will be disabled button. */
2274            hideNext: false,
2275
2276            /* Default tooltip box position */
2277            tooltipPosition: "bottom",
2278
2279            /* Next CSS class for tooltip boxes */
2280            tooltipClass: "",
2281
2282            /* CSS class that is added to the helperLayer */
2283            highlightClass: "",
2284
2285            /* Close introduction when pressing Escape button? */
2286            exitOnEsc: true,
2287
2288            /* Close introduction when clicking on overlay layer? */
2289            exitOnOverlayClick: true,
2290
2291            /* Show step numbers in introduction? */
2292            showStepNumbers: true,
2293
2294            /* Let user use keyboard to navigate the tour? */
2295            keyboardNavigation: true,
2296
2297            /* Show tour control buttons? */
2298            showButtons: true,
2299
2300            /* Show tour bullets? */
2301            showBullets: true,
2302
2303            /* Show tour progress? */
2304            showProgress: false,
2305
2306            /* Scroll to highlighted element? */
2307            scrollToElement: true,
2308
2309            /*
2310             * Should we scroll the tooltip or target element?
2311             *
2312             * Options are: 'element' or 'tooltip'
2313             */
2314            scrollTo: "element",
2315
2316            /* Padding to add after scrolling when element is not in the viewport (in pixels) */
2317            scrollPadding: 30,
2318
2319            /* Set the overlay opacity */
2320            overlayOpacity: 0.8,
2321
2322            /* Precedence of positions, when auto is enabled */
2323            positionPrecedence: ["bottom", "top", "right", "left"],
2324
2325            /* Disable an interaction with element? */
2326            disableInteraction: false,
2327
2328            /* Set how much padding to be used around helper element */
2329            helperElementPadding: 10,
2330
2331            /* Default hint position */
2332            hintPosition: "top-middle",
2333
2334            /* Hint button label */
2335            hintButtonLabel: "Got it",
2336
2337            /* Adding animation to hints? */
2338            hintAnimation: true,
2339
2340            /* additional classes to put on the buttons */
2341            buttonClass: "introjs-button"
2342        };
2343    }
2344
2345    var introJs = function introJs(targetElm) {
2346        var instance;
2347
2348        if (_typeof(targetElm) === "object") {
2349            //Ok, create a new instance
2350            instance = new IntroJs(targetElm);
2351        } else if (typeof targetElm === "string") {
2352            //select the target element with query selector
2353            var targetElement = document.querySelector(targetElm);
2354
2355            if (targetElement) {
2356                instance = new IntroJs(targetElement);
2357            } else {
2358                throw new Error("There is no element with given selector.");
2359            }
2360        } else {
2361            instance = new IntroJs(document.body);
2362        } // add instance to list of _instances
2363        // passing group to stamp to increment
2364        // from 0 onward somewhat reliably
2365
2366
2367        introJs.instances[stamp(instance, "introjs-instance")] = instance;
2368        return instance;
2369    };
2370    /**
2371     * Current IntroJs version
2372     *
2373     * @property version
2374     * @type String
2375     */
2376
2377
2378    introJs.version = version;
2379    /**
2380     * key-val object helper for introJs instances
2381     *
2382     * @property instances
2383     * @type Object
2384     */
2385
2386    introJs.instances = {}; //Prototype
2387
2388    introJs.fn = IntroJs.prototype = {
2389        clone: function clone() {
2390            return new IntroJs(this);
2391        },
2392        setOption: function setOption(option, value) {
2393            this._options[option] = value;
2394            return this;
2395        },
2396        setOptions: function setOptions(options) {
2397            this._options = mergeOptions(this._options, options);
2398            return this;
2399        },
2400        start: function start(group) {
2401            introForElement.call(this, this._targetElement, group);
2402            return this;
2403        },
2404        goToStep: function goToStep$1(step) {
2405            goToStep.call(this, step);
2406
2407            return this;
2408        },
2409        addStep: function addStep(options) {
2410            if (!this._options.steps) {
2411                this._options.steps = [];
2412            }
2413
2414            this._options.steps.push(options);
2415
2416            return this;
2417        },
2418        addSteps: function addSteps(steps) {
2419            if (!steps.length) return;
2420
2421            for (var index = 0; index < steps.length; index++) {
2422                this.addStep(steps[index]);
2423            }
2424
2425            return this;
2426        },
2427        goToStepNumber: function goToStepNumber$1(step) {
2428            goToStepNumber.call(this, step);
2429
2430            return this;
2431        },
2432        nextStep: function nextStep$1() {
2433            nextStep.call(this);
2434
2435            return this;
2436        },
2437        previousStep: function previousStep$1() {
2438            previousStep.call(this);
2439
2440            return this;
2441        },
2442        currentStep: function currentStep$1() {
2443            return currentStep.call(this);
2444        },
2445        exit: function exit(force) {
2446            exitIntro.call(this, this._targetElement, force);
2447            return this;
2448        },
2449        refresh: function refresh$1() {
2450            refresh.call(this);
2451
2452            return this;
2453        },
2454        onbeforechange: function onbeforechange(providedCallback) {
2455            if (typeof providedCallback === "function") {
2456                this._introBeforeChangeCallback = providedCallback;
2457            } else {
2458                throw new Error("Provided callback for onbeforechange was not a function");
2459            }
2460
2461            return this;
2462        },
2463        onchange: function onchange(providedCallback) {
2464            if (typeof providedCallback === "function") {
2465                this._introChangeCallback = providedCallback;
2466            } else {
2467                throw new Error("Provided callback for onchange was not a function.");
2468            }
2469
2470            return this;
2471        },
2472        onafterchange: function onafterchange(providedCallback) {
2473            if (typeof providedCallback === "function") {
2474                this._introAfterChangeCallback = providedCallback;
2475            } else {
2476                throw new Error("Provided callback for onafterchange was not a function");
2477            }
2478
2479            return this;
2480        },
2481        oncomplete: function oncomplete(providedCallback) {
2482            if (typeof providedCallback === "function") {
2483                this._introCompleteCallback = providedCallback;
2484            } else {
2485                throw new Error("Provided callback for oncomplete was not a function.");
2486            }
2487
2488            return this;
2489        },
2490        onhintsadded: function onhintsadded(providedCallback) {
2491            if (typeof providedCallback === "function") {
2492                this._hintsAddedCallback = providedCallback;
2493            } else {
2494                throw new Error("Provided callback for onhintsadded was not a function.");
2495            }
2496
2497            return this;
2498        },
2499        onhintclick: function onhintclick(providedCallback) {
2500            if (typeof providedCallback === "function") {
2501                this._hintClickCallback = providedCallback;
2502            } else {
2503                throw new Error("Provided callback for onhintclick was not a function.");
2504            }
2505
2506            return this;
2507        },
2508        onhintclose: function onhintclose(providedCallback) {
2509            if (typeof providedCallback === "function") {
2510                this._hintCloseCallback = providedCallback;
2511            } else {
2512                throw new Error("Provided callback for onhintclose was not a function.");
2513            }
2514
2515            return this;
2516        },
2517        onexit: function onexit(providedCallback) {
2518            if (typeof providedCallback === "function") {
2519                this._introExitCallback = providedCallback;
2520            } else {
2521                throw new Error("Provided callback for onexit was not a function.");
2522            }
2523
2524            return this;
2525        },
2526        onskip: function onskip(providedCallback) {
2527            if (typeof providedCallback === "function") {
2528                this._introSkipCallback = providedCallback;
2529            } else {
2530                throw new Error("Provided callback for onskip was not a function.");
2531            }
2532
2533            return this;
2534        },
2535        onbeforeexit: function onbeforeexit(providedCallback) {
2536            if (typeof providedCallback === "function") {
2537                this._introBeforeExitCallback = providedCallback;
2538            } else {
2539                throw new Error("Provided callback for onbeforeexit was not a function.");
2540            }
2541
2542            return this;
2543        },
2544        addHints: function addHints() {
2545            populateHints.call(this, this._targetElement);
2546            return this;
2547        },
2548        hideHint: function hideHint$1(stepId) {
2549            hideHint.call(this, stepId);
2550
2551            return this;
2552        },
2553        hideHints: function hideHints$1() {
2554            hideHints.call(this);
2555
2556            return this;
2557        },
2558        showHint: function showHint$1(stepId) {
2559            showHint.call(this, stepId);
2560
2561            return this;
2562        },
2563        showHints: function showHints$1() {
2564            showHints.call(this);
2565
2566            return this;
2567        },
2568        removeHints: function removeHints$1() {
2569            removeHints.call(this);
2570
2571            return this;
2572        },
2573        removeHint: function removeHint$1(stepId) {
2574            removeHint().call(this, stepId);
2575
2576            return this;
2577        },
2578        showHintDialog: function showHintDialog$1(stepId) {
2579            showHintDialog.call(this, stepId);
2580
2581            return this;
2582        }
2583    };
2584
2585    return introJs;
2586
2587})));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.