PageSourceSearch

https://www.pagcom.com.br/js/introjs/introjs.min.js?q=1592779427

js pagcom.com.br collected 2026-10-10 01:09:53 UTC 82,569 bytes, 2,189 lines download raw bytes

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

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.