From 59cff681209504750e194b5866f49101cb718275 Mon Sep 17 00:00:00 2001 From: Miguel Angel Arenas Correa Date: Mon, 4 Dec 2017 21:32:08 -0500 Subject: [PATCH 1/3] Update to 2.7.0 --- .gitignore | 1 + app/assets/javascripts/introjs.js | 2172 +++++++++++++++++++++++++++- app/assets/stylesheets/introjs.css | 520 ++++++- lib/introjs-rails/version.rb | 2 +- 4 files changed, 2660 insertions(+), 35 deletions(-) diff --git a/.gitignore b/.gitignore index 4040c6c..0ec1b46 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.gem .bundle Gemfile.lock +.idea pkg/* diff --git a/app/assets/javascripts/introjs.js b/app/assets/javascripts/introjs.js index d95cd0f..f679916 100644 --- a/app/assets/javascripts/introjs.js +++ b/app/assets/javascripts/introjs.js @@ -1,33 +1,2139 @@ -(function(w,p){"object"===typeof exports?p(exports):"function"===typeof define&&define.amd?define(["exports"],p):p(w)})(this,function(w){function p(a){this._targetElement=a;this._options={nextLabel:"Next →",prevLabel:"← Back",skipLabel:"Skip",doneLabel:"Done",tooltipPosition:"bottom",tooltipClass:"",highlightClass:"",exitOnEsc:!0,exitOnOverlayClick:!0,showStepNumbers:!0,keyboardNavigation:!0,showButtons:!0,showBullets:!0,showProgress:!1,scrollToElement:!0,overlayOpacity:0.8,positionPrecedence:["bottom", -"top","right","left"],disableInteraction:!1}}function J(a){var b=[],c=this;if(this._options.steps)for(var d=[],e=0,d=this._options.steps.length;ed.length)return!1;e=0;for(f=d.length;eh.width||0>l.left+l.width/2-s?(q(f,"bottom"),q(f,"top")):(l.height+l.top+p>h.height&& -q(f,"bottom"),0>l.top-p&&q(f,"top"));l.width+l.left+s>h.width&&q(f,"right");0>l.left-s&&q(f,"left");0h.height&&(c.className="introjs-arrow left-bottom",b.style.top="-"+(f-e.height-20)+"px");c.className="introjs-arrow left"; -break;case "left":!0==this._options.showStepNumbers&&(b.style.top="15px");e.top+f>h.height?(b.style.top="-"+(f-e.height-20)+"px",c.className="introjs-arrow right-bottom"):c.className="introjs-arrow right";b.style.right=e.width+20+"px";break;case "floating":c.style.display="none";a=k(b);b.style.left="50%";b.style.top="50%";b.style.marginLeft="-"+a.width/2+"px";b.style.marginTop="-"+a.height/2+"px";"undefined"!=typeof d&&null!=d&&(d.style.left="-"+(a.width/2+18)+"px",d.style.top="-"+(a.height/2+18)+ -"px");break;case "bottom-right-aligned":c.className="introjs-arrow top-right";b.style.right="0px";b.style.bottom="-"+(k(b).height+10)+"px";break;case "bottom-middle-aligned":d=k(a);a=k(b);c.className="introjs-arrow top-middle";b.style.left=d.width/2-a.width/2+"px";b.style.bottom="-"+(a.height+10)+"px";break;default:b.style.bottom="-"+(k(b).height+10)+"px",b.style.left=k(a).width/2-k(b).width/2+"px",c.className="introjs-arrow top"}}}function q(a,b){-1 a.active").className="";d.querySelector('.introjs-bullets li > a[data-stepnumber="'+ -a.step+'"]').className="active";d.querySelector(".introjs-progress .introjs-progressbar").setAttribute("style","width:"+I.call(b)+"%;");s.style.opacity=1;f&&(f.style.opacity=1);-1===r.tabIndex?l.focus():r.focus()},350)}else{var q=document.createElement("div"),m=document.createElement("div"),c=document.createElement("div"),n=document.createElement("div"),w=document.createElement("div"),D=document.createElement("div"),E=document.createElement("div"),u=document.createElement("div");q.className=e;m.className= -"introjs-tooltipReferenceLayer";t.call(b,q);t.call(b,m);this._targetElement.appendChild(q);this._targetElement.appendChild(m);c.className="introjs-arrow";w.className="introjs-tooltiptext";w.innerHTML=a.intro;D.className="introjs-bullets";!1===this._options.showBullets&&(D.style.display="none");for(var q=document.createElement("ul"),e=0,B=this._introItems.length;en||"none"!==u)g.className+=" introjs-fixParent";g=g.parentNode}M(a.element)||!0!==this._options.scrollToElement||(n=a.element.getBoundingClientRect(),g=F().height,c=n.bottom-(n.bottom-n.top),n=n.bottom-g,0>c||a.element.clientHeight>g?window.scrollBy(0,c-30):window.scrollBy(0,n+100));"undefined"!== -typeof this._introAfterChangeCallback&&this._introAfterChangeCallback.call(this,a.element)}function v(a,b){var c="";a.currentStyle?c=a.currentStyle[b]:document.defaultView&&document.defaultView.getComputedStyle&&(c=document.defaultView.getComputedStyle(a,null).getPropertyValue(b));return c&&c.toLowerCase?c.toLowerCase():c}function F(){if(void 0!=window.innerWidth)return{width:window.innerWidth,height:window.innerHeight};var a=document.documentElement;return{width:a.clientWidth,height:a.clientHeight}} -function M(a){a=a.getBoundingClientRect();return 0<=a.top&&0<=a.left&&a.bottom+80<=window.innerHeight&&a.right<=window.innerWidth}function K(a){var b=document.createElement("div"),c="",d=this;b.className="introjs-overlay";if("body"===a.tagName.toLowerCase())c+="top: 0;bottom: 0; left: 0;right: 0;position: fixed;",b.setAttribute("style",c);else{var e=k(a);e&&(c+="width: "+e.width+"px; height:"+e.height+"px; top:"+e.top+"px;left: "+e.left+"px;",b.setAttribute("style",c))}a.appendChild(b);b.onclick= -function(){!0==d._options.exitOnOverlayClick&&(y.call(d,a),void 0!=d._introExitCallback&&d._introExitCallback.call(d))};setTimeout(function(){c+="opacity: "+d._options.overlayOpacity.toString()+";";b.setAttribute("style",c)},10);return!0}function k(a){var b={};b.width=a.offsetWidth;b.height=a.offsetHeight;for(var c=0,d=0;a&&!isNaN(a.offsetLeft)&&!isNaN(a.offsetTop);)c+=a.offsetLeft,d+=a.offsetTop,a=a.offsetParent;b.top=d;b.left=c;return b}function I(){return 100*(parseInt(this._currentStep+1,10)/ -this._introItems.length)}var B=function(a){if("object"===typeof a)return new p(a);if("string"===typeof a){if(a=document.querySelector(a))return new p(a);throw Error("There is no element with given selector.");}return new p(document.body)};B.version="1.0.0";B.fn=p.prototype={clone:function(){return new p(this)},setOption:function(a,b){this._options[a]=b;return this},setOptions:function(a){var b=this._options,c={},d;for(d in b)c[d]=b[d];for(d in a)c[d]=a[d];this._options=c;return this},start:function(){J.call(this, -this._targetElement);return this},goToStep:function(a){this._currentStep=a-2;"undefined"!==typeof this._introItems&&x.call(this);return this},nextStep:function(){x.call(this);return this},previousStep:function(){C.call(this);return this},exit:function(){y.call(this,this._targetElement);return this},refresh:function(){t.call(this,document.querySelector(".introjs-helperLayer"));t.call(this,document.querySelector(".introjs-tooltipReferenceLayer"));return this},onbeforechange:function(a){if("function"=== -typeof a)this._introBeforeChangeCallback=a;else throw Error("Provided callback for onbeforechange was not a function");return this},onchange:function(a){if("function"===typeof a)this._introChangeCallback=a;else throw Error("Provided callback for onchange was not a function.");return this},onafterchange:function(a){if("function"===typeof a)this._introAfterChangeCallback=a;else throw Error("Provided callback for onafterchange was not a function");return this},oncomplete:function(a){if("function"=== -typeof a)this._introCompleteCallback=a;else throw Error("Provided callback for oncomplete was not a function.");return this},onexit:function(a){if("function"===typeof a)this._introExitCallback=a;else throw Error("Provided callback for onexit was not a function.");return this}};return w.introJs=B}); +/** + * Intro.js v2.7.0 + * https://github.com/usablica/intro.js + * + * Copyright (C) 2017 Afshin Mehrabani (@afshinmeh) + */ + +(function (root, factory) { + if (typeof exports === 'object') { + // CommonJS + factory(exports); + } else if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['exports'], factory); + } else { + // Browser globals + factory(root); + } +} (this, function (exports) { + //Default config/variables + var VERSION = '2.7.0'; + + /** + * IntroJs main class + * + * @class IntroJs + */ + function IntroJs(obj) { + this._targetElement = obj; + this._introItems = []; + + this._options = { + /* Next button label in tooltip box */ + nextLabel: 'Next →', + /* Previous button label in tooltip box */ + prevLabel: '← Back', + /* Skip button label in tooltip box */ + skipLabel: 'Skip', + /* Done button label in tooltip box */ + doneLabel: 'Done', + /* Hide previous button in the first step? Otherwise, it will be disabled button. */ + hidePrev: false, + /* Hide next button in the last step? Otherwise, it will be disabled button. */ + hideNext: false, + /* Default tooltip box position */ + tooltipPosition: 'bottom', + /* Next CSS class for tooltip boxes */ + tooltipClass: '', + /* CSS class that is added to the helperLayer */ + highlightClass: '', + /* Close introduction when pressing Escape button? */ + exitOnEsc: true, + /* Close introduction when clicking on overlay layer? */ + exitOnOverlayClick: true, + /* Show step numbers in introduction? */ + showStepNumbers: true, + /* Let user use keyboard to navigate the tour? */ + keyboardNavigation: true, + /* Show tour control buttons? */ + showButtons: true, + /* Show tour bullets? */ + showBullets: true, + /* Show tour progress? */ + showProgress: false, + /* Scroll to highlighted element? */ + scrollToElement: true, + /* + * Should we scroll the tooltip or target element? + * + * Options are: 'element' or 'tooltip' + */ + scrollTo: 'element', + /* Padding to add after scrolling when element is not in the viewport (in pixels) */ + scrollPadding: 30, + /* Set the overlay opacity */ + overlayOpacity: 0.8, + /* Precedence of positions, when auto is enabled */ + positionPrecedence: ["bottom", "top", "right", "left"], + /* Disable an interaction with element? */ + disableInteraction: false, + /* Default hint position */ + hintPosition: 'top-middle', + /* Hint button label */ + hintButtonLabel: 'Got it', + /* Adding animation to hints? */ + hintAnimation: true + }; + } + + /** + * Initiate a new introduction/guide from an element in the page + * + * @api private + * @method _introForElement + * @param {Object} targetElm + * @returns {Boolean} Success or not? + */ + function _introForElement(targetElm) { + var introItems = [], + self = this; + + if (this._options.steps) { + //use steps passed programmatically + for (var i = 0, stepsLength = this._options.steps.length; i < stepsLength; i++) { + var currentItem = _cloneObject(this._options.steps[i]); + + //set the step + currentItem.step = introItems.length + 1; + + //use querySelector function only when developer used CSS selector + if (typeof (currentItem.element) === 'string') { + //grab the element with given selector from the page + currentItem.element = document.querySelector(currentItem.element); + } + + //intro without element + if (typeof (currentItem.element) === 'undefined' || currentItem.element == null) { + var floatingElementQuery = document.querySelector(".introjsFloatingElement"); + + if (floatingElementQuery == null) { + floatingElementQuery = document.createElement('div'); + floatingElementQuery.className = 'introjsFloatingElement'; + + document.body.appendChild(floatingElementQuery); + } + + currentItem.element = floatingElementQuery; + currentItem.position = 'floating'; + } + + currentItem.scrollTo = currentItem.scrollTo || this._options.scrollTo; + + if (typeof (currentItem.disableInteraction) === 'undefined') { + currentItem.disableInteraction = this._options.disableInteraction; + } + + if (currentItem.element != null) { + introItems.push(currentItem); + } + } + + } else { + //use steps from data-* annotations + var allIntroSteps = targetElm.querySelectorAll('*[data-intro]'); + //if there's no element to intro + if (allIntroSteps.length < 1) { + return false; + } + + //first add intro items with data-step + for (var i = 0, elmsLength = allIntroSteps.length; i < elmsLength; i++) { + var currentElement = allIntroSteps[i]; + + // skip hidden elements + if (currentElement.style.display == 'none') { + continue; + } + + var step = parseInt(currentElement.getAttribute('data-step'), 10); + + var disableInteraction = this._options.disableInteraction; + + if (typeof (currentElement.getAttribute('data-disable-interaction')) != 'undefined') { + disableInteraction = !!currentElement.getAttribute('data-disable-interaction'); + } + + if (step > 0) { + introItems[step - 1] = { + element: currentElement, + intro: currentElement.getAttribute('data-intro'), + step: parseInt(currentElement.getAttribute('data-step'), 10), + tooltipClass: currentElement.getAttribute('data-tooltipClass'), + highlightClass: currentElement.getAttribute('data-highlightClass'), + position: currentElement.getAttribute('data-position') || this._options.tooltipPosition, + scrollTo: currentElement.getAttribute('data-scrollTo') || this._options.scrollTo, + disableInteraction: disableInteraction + }; + } + } + + //next add intro items without data-step + //todo: we need a cleanup here, two loops are redundant + var nextStep = 0; + for (var i = 0, elmsLength = allIntroSteps.length; i < elmsLength; i++) { + var currentElement = allIntroSteps[i]; + + if (currentElement.getAttribute('data-step') == null) { + + while (true) { + if (typeof introItems[nextStep] == 'undefined') { + break; + } else { + nextStep++; + } + } + + var disableInteraction = this._options.disableInteraction; + + if (typeof (currentElement.getAttribute('data-disable-interaction')) != 'undefined') { + disableInteraction = !!currentElement.getAttribute('data-disable-interaction'); + } + + introItems[nextStep] = { + element: currentElement, + intro: currentElement.getAttribute('data-intro'), + step: nextStep + 1, + tooltipClass: currentElement.getAttribute('data-tooltipClass'), + highlightClass: currentElement.getAttribute('data-highlightClass'), + position: currentElement.getAttribute('data-position') || this._options.tooltipPosition, + scrollTo: currentElement.getAttribute('data-scrollTo') || this._options.scrollTo, + disableInteraction: disableInteraction + }; + } + } + } + + //removing undefined/null elements + var tempIntroItems = []; + for (var z = 0; z < introItems.length; z++) { + introItems[z] && tempIntroItems.push(introItems[z]); // copy non-empty values to the end of the array + } + + introItems = tempIntroItems; + + //Ok, sort all items with given steps + introItems.sort(function (a, b) { + return a.step - b.step; + }); + + //set it to the introJs object + self._introItems = introItems; + + //add overlay layer to the page + if(_addOverlayLayer.call(self, targetElm)) { + //then, start the show + _nextStep.call(self); + + var skipButton = targetElm.querySelector('.introjs-skipbutton'), + nextStepButton = targetElm.querySelector('.introjs-nextbutton'); + + self._onKeyDown = function(e) { + if (e.keyCode === 27 && self._options.exitOnEsc == true) { + //escape key pressed, exit the intro + //check if exit callback is defined + _exitIntro.call(self, targetElm); + } else if(e.keyCode === 37) { + //left arrow + _previousStep.call(self); + } else if (e.keyCode === 39) { + //right arrow + _nextStep.call(self); + } else if (e.keyCode === 13) { + //srcElement === ie + var target = e.target || e.srcElement; + if (target && target.className.indexOf('introjs-prevbutton') > 0) { + //user hit enter while focusing on previous button + _previousStep.call(self); + } else if (target && target.className.indexOf('introjs-skipbutton') > 0) { + //user hit enter while focusing on skip button + if (self._introItems.length - 1 == self._currentStep && typeof (self._introCompleteCallback) === 'function') { + self._introCompleteCallback.call(self); + } + + _exitIntro.call(self, targetElm); + } else { + //default behavior for responding to enter + _nextStep.call(self); + } + + //prevent default behaviour on hitting Enter, to prevent steps being skipped in some browsers + if(e.preventDefault) { + e.preventDefault(); + } else { + e.returnValue = false; + } + } + }; + + self._onResize = function(e) { + self.refresh.call(self); + }; + + if (window.addEventListener) { + if (this._options.keyboardNavigation) { + window.addEventListener('keydown', self._onKeyDown, true); + } + //for window resize + window.addEventListener('resize', self._onResize, true); + } else if (document.attachEvent) { //IE + if (this._options.keyboardNavigation) { + document.attachEvent('onkeydown', self._onKeyDown); + } + //for window resize + document.attachEvent('onresize', self._onResize); + } + } + return false; + } + + /* + * makes a copy of the object + * @api private + * @method _cloneObject + */ + function _cloneObject(object) { + if (object == null || typeof (object) != 'object' || typeof (object.nodeType) != 'undefined') { + return object; + } + var temp = {}; + for (var key in object) { + if (typeof (jQuery) != 'undefined' && object[key] instanceof jQuery) { + temp[key] = object[key]; + } else { + temp[key] = _cloneObject(object[key]); + } + } + return temp; + } + /** + * Go to specific step of introduction + * + * @api private + * @method _goToStep + */ + function _goToStep(step) { + //because steps starts with zero + this._currentStep = step - 2; + if (typeof (this._introItems) !== 'undefined') { + _nextStep.call(this); + } + } + + /** + * Go to the specific step of introduction with the explicit [data-step] number + * + * @api private + * @method _goToStepNumber + */ + function _goToStepNumber(step) { + this._currentStepNumber = step; + if (typeof (this._introItems) !== 'undefined') { + _nextStep.call(this); + } + } + + /** + * Go to next step on intro + * + * @api private + * @method _nextStep + */ + function _nextStep() { + this._direction = 'forward'; + + if (typeof (this._currentStepNumber) !== 'undefined') { + for( var i = 0, len = this._introItems.length; i < len; i++ ) { + var item = this._introItems[i]; + if( item.step === this._currentStepNumber ) { + this._currentStep = i - 1; + this._currentStepNumber = undefined; + } + } + } + + if (typeof (this._currentStep) === 'undefined') { + this._currentStep = 0; + } else { + ++this._currentStep; + } + + if ((this._introItems.length) <= this._currentStep) { + //end of the intro + //check if any callback is defined + if (typeof (this._introCompleteCallback) === 'function') { + this._introCompleteCallback.call(this); + } + _exitIntro.call(this, this._targetElement); + return; + } + + var nextStep = this._introItems[this._currentStep]; + if (typeof (this._introBeforeChangeCallback) !== 'undefined') { + this._introBeforeChangeCallback.call(this, nextStep.element); + } + + _showElement.call(this, nextStep); + } + + /** + * Go to previous step on intro + * + * @api private + * @method _previousStep + */ + function _previousStep() { + this._direction = 'backward'; + + if (this._currentStep === 0) { + return false; + } + + var nextStep = this._introItems[--this._currentStep]; + if (typeof (this._introBeforeChangeCallback) !== 'undefined') { + this._introBeforeChangeCallback.call(this, nextStep.element); + } + + _showElement.call(this, nextStep); + } + + /** + * Update placement of the intro objects on the screen + * @api private + */ + function _refresh() { + // re-align intros + _setHelperLayerPosition.call(this, document.querySelector('.introjs-helperLayer')); + _setHelperLayerPosition.call(this, document.querySelector('.introjs-tooltipReferenceLayer')); + + // re-align tooltip + if(this._currentStep !== undefined && this._currentStep !== null) { + var oldHelperNumberLayer = document.querySelector('.introjs-helperNumberLayer'), + oldArrowLayer = document.querySelector('.introjs-arrow'), + oldtooltipContainer = document.querySelector('.introjs-tooltip'); + _placeTooltip.call(this, this._introItems[this._currentStep].element, oldtooltipContainer, oldArrowLayer, oldHelperNumberLayer); + } + + //re-align hints + _reAlignHints.call(this); + return this; + } + + /** + * Exit from intro + * + * @api private + * @method _exitIntro + * @param {Object} targetElement + * @param {Boolean} force - Setting to `true` will skip the result of beforeExit callback + */ + function _exitIntro(targetElement, force) { + var continueExit = true; + + // calling onbeforeexit callback + // + // If this callback return `false`, it would halt the process + if (this._introBeforeExitCallback != undefined) { + continueExit = this._introBeforeExitCallback.call(self); + } + + // skip this check if `force` parameter is `true` + // otherwise, if `onbeforeexit` returned `false`, don't exit the intro + if (!force && continueExit === false) return; + + //remove overlay layers from the page + var overlayLayers = targetElement.querySelectorAll('.introjs-overlay'); + + if (overlayLayers && overlayLayers.length > 0) { + for (var i = overlayLayers.length - 1; i >= 0; i--) { + //for fade-out animation + var overlayLayer = overlayLayers[i]; + overlayLayer.style.opacity = 0; + setTimeout(function () { + if (this.parentNode) { + this.parentNode.removeChild(this); + } + }.bind(overlayLayer), 500); + }; + } + + //remove all helper layers + var helperLayer = targetElement.querySelector('.introjs-helperLayer'); + if (helperLayer) { + helperLayer.parentNode.removeChild(helperLayer); + } + + var referenceLayer = targetElement.querySelector('.introjs-tooltipReferenceLayer'); + if (referenceLayer) { + referenceLayer.parentNode.removeChild(referenceLayer); + } + + //remove disableInteractionLayer + var disableInteractionLayer = targetElement.querySelector('.introjs-disableInteraction'); + if (disableInteractionLayer) { + disableInteractionLayer.parentNode.removeChild(disableInteractionLayer); + } + + //remove intro floating element + var floatingElement = document.querySelector('.introjsFloatingElement'); + if (floatingElement) { + floatingElement.parentNode.removeChild(floatingElement); + } + + _removeShowElement(); + + //remove `introjs-fixParent` class from the elements + var fixParents = document.querySelectorAll('.introjs-fixParent'); + if (fixParents && fixParents.length > 0) { + for (var i = fixParents.length - 1; i >= 0; i--) { + fixParents[i].className = fixParents[i].className.replace(/introjs-fixParent/g, '').replace(/^\s+|\s+$/g, ''); + } + } + + //clean listeners + if (window.removeEventListener) { + window.removeEventListener('keydown', this._onKeyDown, true); + } else if (document.detachEvent) { //IE + document.detachEvent('onkeydown', this._onKeyDown); + } + + //check if any callback is defined + if (this._introExitCallback != undefined) { + this._introExitCallback.call(self); + } + + //set the step to zero + this._currentStep = undefined; + } + + /** + * Render tooltip box in the page + * + * @api private + * @method _placeTooltip + * @param {HTMLElement} targetElement + * @param {HTMLElement} tooltipLayer + * @param {HTMLElement} arrowLayer + * @param {HTMLElement} helperNumberLayer + * @param {Boolean} hintMode + */ + function _placeTooltip(targetElement, tooltipLayer, arrowLayer, helperNumberLayer, hintMode) { + var tooltipCssClass = '', + currentStepObj, + tooltipOffset, + targetOffset, + windowSize, + currentTooltipPosition; + + hintMode = hintMode || false; + + //reset the old style + tooltipLayer.style.top = null; + tooltipLayer.style.right = null; + tooltipLayer.style.bottom = null; + tooltipLayer.style.left = null; + tooltipLayer.style.marginLeft = null; + tooltipLayer.style.marginTop = null; + + arrowLayer.style.display = 'inherit'; + + if (typeof(helperNumberLayer) != 'undefined' && helperNumberLayer != null) { + helperNumberLayer.style.top = null; + helperNumberLayer.style.left = null; + } + + //prevent error when `this._currentStep` is undefined + if (!this._introItems[this._currentStep]) return; + + //if we have a custom css class for each step + currentStepObj = this._introItems[this._currentStep]; + if (typeof (currentStepObj.tooltipClass) === 'string') { + tooltipCssClass = currentStepObj.tooltipClass; + } else { + tooltipCssClass = this._options.tooltipClass; + } + + tooltipLayer.className = ('introjs-tooltip ' + tooltipCssClass).replace(/^\s+|\s+$/g, ''); + + currentTooltipPosition = this._introItems[this._currentStep].position; + + if (currentTooltipPosition != "floating") { // Floating is always valid, no point in calculating + if (currentTooltipPosition === "auto") { + currentTooltipPosition = _determineAutoPosition.call(this, targetElement, tooltipLayer); + } else { + currentTooltipPosition = _determineAutoPosition.call(this, targetElement, tooltipLayer, currentTooltipPosition); + } + } + + targetOffset = _getOffset(targetElement); + tooltipOffset = _getOffset(tooltipLayer); + windowSize = _getWinSize(); + + switch (currentTooltipPosition) { + case 'top': + arrowLayer.className = 'introjs-arrow bottom'; + + if (hintMode) { + var tooltipLayerStyleLeft = 0; + } else { + var tooltipLayerStyleLeft = 15; + } + + _checkRight(targetOffset, tooltipLayerStyleLeft, tooltipOffset, windowSize, tooltipLayer); + tooltipLayer.style.bottom = (targetOffset.height + 20) + 'px'; + break; + case 'right': + tooltipLayer.style.left = (targetOffset.width + 20) + 'px'; + if (targetOffset.top + tooltipOffset.height > windowSize.height) { + // In this case, right would have fallen below the bottom of the screen. + // Modify so that the bottom of the tooltip connects with the target + arrowLayer.className = "introjs-arrow left-bottom"; + tooltipLayer.style.top = "-" + (tooltipOffset.height - targetOffset.height - 20) + "px"; + } else { + arrowLayer.className = 'introjs-arrow left'; + } + break; + case 'left': + if (!hintMode && this._options.showStepNumbers == true) { + tooltipLayer.style.top = '15px'; + } + + if (targetOffset.top + tooltipOffset.height > windowSize.height) { + // In this case, left would have fallen below the bottom of the screen. + // Modify so that the bottom of the tooltip connects with the target + tooltipLayer.style.top = "-" + (tooltipOffset.height - targetOffset.height - 20) + "px"; + arrowLayer.className = 'introjs-arrow right-bottom'; + } else { + arrowLayer.className = 'introjs-arrow right'; + } + tooltipLayer.style.right = (targetOffset.width + 20) + 'px'; + + break; + case 'floating': + arrowLayer.style.display = 'none'; + + //we have to adjust the top and left of layer manually for intro items without element + tooltipLayer.style.left = '50%'; + tooltipLayer.style.top = '50%'; + tooltipLayer.style.marginLeft = '-' + (tooltipOffset.width / 2) + 'px'; + tooltipLayer.style.marginTop = '-' + (tooltipOffset.height / 2) + 'px'; + + if (typeof(helperNumberLayer) != 'undefined' && helperNumberLayer != null) { + helperNumberLayer.style.left = '-' + ((tooltipOffset.width / 2) + 18) + 'px'; + helperNumberLayer.style.top = '-' + ((tooltipOffset.height / 2) + 18) + 'px'; + } + + break; + case 'bottom-right-aligned': + arrowLayer.className = 'introjs-arrow top-right'; + + var tooltipLayerStyleRight = 0; + _checkLeft(targetOffset, tooltipLayerStyleRight, tooltipOffset, tooltipLayer); + tooltipLayer.style.top = (targetOffset.height + 20) + 'px'; + break; + + case 'bottom-middle-aligned': + arrowLayer.className = 'introjs-arrow top-middle'; + + var tooltipLayerStyleLeftRight = targetOffset.width / 2 - tooltipOffset.width / 2; + + // a fix for middle aligned hints + if (hintMode) { + tooltipLayerStyleLeftRight += 5; + } + + if (_checkLeft(targetOffset, tooltipLayerStyleLeftRight, tooltipOffset, tooltipLayer)) { + tooltipLayer.style.right = null; + _checkRight(targetOffset, tooltipLayerStyleLeftRight, tooltipOffset, windowSize, tooltipLayer); + } + tooltipLayer.style.top = (targetOffset.height + 20) + 'px'; + break; + + case 'bottom-left-aligned': + // Bottom-left-aligned is the same as the default bottom + case 'bottom': + // Bottom going to follow the default behavior + default: + arrowLayer.className = 'introjs-arrow top'; + + var tooltipLayerStyleLeft = 0; + _checkRight(targetOffset, tooltipLayerStyleLeft, tooltipOffset, windowSize, tooltipLayer); + tooltipLayer.style.top = (targetOffset.height + 20) + 'px'; + break; + } + } + + /** + * Set tooltip left so it doesn't go off the right side of the window + * + * @return boolean true, if tooltipLayerStyleLeft is ok. false, otherwise. + */ + function _checkRight(targetOffset, tooltipLayerStyleLeft, tooltipOffset, windowSize, tooltipLayer) { + if (targetOffset.left + tooltipLayerStyleLeft + tooltipOffset.width > windowSize.width) { + // off the right side of the window + tooltipLayer.style.left = (windowSize.width - tooltipOffset.width - targetOffset.left) + 'px'; + return false; + } + tooltipLayer.style.left = tooltipLayerStyleLeft + 'px'; + return true; + } + + /** + * Set tooltip right so it doesn't go off the left side of the window + * + * @return boolean true, if tooltipLayerStyleRight is ok. false, otherwise. + */ + function _checkLeft(targetOffset, tooltipLayerStyleRight, tooltipOffset, tooltipLayer) { + if (targetOffset.left + targetOffset.width - tooltipLayerStyleRight - tooltipOffset.width < 0) { + // off the left side of the window + tooltipLayer.style.left = (-targetOffset.left) + 'px'; + return false; + } + tooltipLayer.style.right = tooltipLayerStyleRight + 'px'; + return true; + } + + /** + * Determines the position of the tooltip based on the position precedence and availability + * of screen space. + * + * @param {Object} targetElement + * @param {Object} tooltipLayer + * @param {Object} desiredTooltipPosition + * + */ + function _determineAutoPosition(targetElement, tooltipLayer, desiredTooltipPosition) { + + // Take a clone of position precedence. These will be the available + var possiblePositions = this._options.positionPrecedence.slice(); + + var windowSize = _getWinSize(); + var tooltipHeight = _getOffset(tooltipLayer).height + 10; + var tooltipWidth = _getOffset(tooltipLayer).width + 20; + var targetOffset = _getOffset(targetElement); + + // If we check all the possible areas, and there are no valid places for the tooltip, the element + // must take up most of the screen real estate. Show the tooltip floating in the middle of the screen. + var calculatedPosition = "floating"; + + // Check if the width of the tooltip + the starting point would spill off the right side of the screen + // If no, neither bottom or top are valid + if (targetOffset.left + tooltipWidth > windowSize.width || ((targetOffset.left + (targetOffset.width / 2)) - tooltipWidth) < 0) { + _removeEntry(possiblePositions, "bottom"); + _removeEntry(possiblePositions, "top"); + } else { + // Check for space below + if ((targetOffset.height + targetOffset.top + tooltipHeight) > windowSize.height) { + _removeEntry(possiblePositions, "bottom"); + } + + // Check for space above + if (targetOffset.top - tooltipHeight < 0) { + _removeEntry(possiblePositions, "top"); + } + } + + // Check for space to the right + if (targetOffset.width + targetOffset.left + tooltipWidth > windowSize.width) { + _removeEntry(possiblePositions, "right"); + } + + // Check for space to the left + if (targetOffset.left - tooltipWidth < 0) { + _removeEntry(possiblePositions, "left"); + } + + // At this point, our array only has positions that are valid. Pick the first one, as it remains in order + if (possiblePositions.length > 0) { + calculatedPosition = possiblePositions[0]; + } + + // If the requested position is in the list, replace our calculated choice with that + if (desiredTooltipPosition && desiredTooltipPosition != "auto") { + if (possiblePositions.indexOf(desiredTooltipPosition) > -1) { + calculatedPosition = desiredTooltipPosition; + } + } + + return calculatedPosition; + } + + /** + * Remove an entry from a string array if it's there, does nothing if it isn't there. + * + * @param {Array} stringArray + * @param {String} stringToRemove + */ + function _removeEntry(stringArray, stringToRemove) { + if (stringArray.indexOf(stringToRemove) > -1) { + stringArray.splice(stringArray.indexOf(stringToRemove), 1); + } + } + + /** + * Update the position of the helper layer on the screen + * + * @api private + * @method _setHelperLayerPosition + * @param {Object} helperLayer + */ + function _setHelperLayerPosition(helperLayer) { + if (helperLayer) { + //prevent error when `this._currentStep` in undefined + if (!this._introItems[this._currentStep]) return; + + var currentElement = this._introItems[this._currentStep], + elementPosition = _getOffset(currentElement.element), + widthHeightPadding = 10; + + // If the target element is fixed, the tooltip should be fixed as well. + // Otherwise, remove a fixed class that may be left over from the previous + // step. + if (_isFixed(currentElement.element)) { + helperLayer.className += ' introjs-fixedTooltip'; + } else { + helperLayer.className = helperLayer.className.replace(' introjs-fixedTooltip', ''); + } + + if (currentElement.position == 'floating') { + widthHeightPadding = 0; + } + + //set new position to helper layer + helperLayer.setAttribute('style', 'width: ' + (elementPosition.width + widthHeightPadding) + 'px; ' + + 'height:' + (elementPosition.height + widthHeightPadding) + 'px; ' + + 'top:' + (elementPosition.top - 5) + 'px;' + + 'left: ' + (elementPosition.left - 5) + 'px;'); + + } + } + + /** + * Add disableinteraction layer and adjust the size and position of the layer + * + * @api private + * @method _disableInteraction + */ + function _disableInteraction() { + var disableInteractionLayer = document.querySelector('.introjs-disableInteraction'); + + if (disableInteractionLayer === null) { + disableInteractionLayer = document.createElement('div'); + disableInteractionLayer.className = 'introjs-disableInteraction'; + this._targetElement.appendChild(disableInteractionLayer); + } + + _setHelperLayerPosition.call(this, disableInteractionLayer); + } + + /** + * Setting anchors to behave like buttons + * + * @api private + * @method _setAnchorAsButton + */ + function _setAnchorAsButton(anchor){ + anchor.setAttribute('role', 'button'); + anchor.tabIndex = 0; + } + + /** + * Show an element on the page + * + * @api private + * @method _showElement + * @param {Object} targetElement + */ + function _showElement(targetElement) { + if (typeof (this._introChangeCallback) !== 'undefined') { + this._introChangeCallback.call(this, targetElement.element); + } + + var self = this, + oldHelperLayer = document.querySelector('.introjs-helperLayer'), + oldReferenceLayer = document.querySelector('.introjs-tooltipReferenceLayer'), + highlightClass = 'introjs-helperLayer', + elementPosition = _getOffset(targetElement.element); + + //check for a current step highlight class + if (typeof (targetElement.highlightClass) === 'string') { + highlightClass += (' ' + targetElement.highlightClass); + } + //check for options highlight class + if (typeof (this._options.highlightClass) === 'string') { + highlightClass += (' ' + this._options.highlightClass); + } + + if (oldHelperLayer != null) { + var oldHelperNumberLayer = oldReferenceLayer.querySelector('.introjs-helperNumberLayer'), + oldtooltipLayer = oldReferenceLayer.querySelector('.introjs-tooltiptext'), + oldArrowLayer = oldReferenceLayer.querySelector('.introjs-arrow'), + oldtooltipContainer = oldReferenceLayer.querySelector('.introjs-tooltip'), + skipTooltipButton = oldReferenceLayer.querySelector('.introjs-skipbutton'), + prevTooltipButton = oldReferenceLayer.querySelector('.introjs-prevbutton'), + nextTooltipButton = oldReferenceLayer.querySelector('.introjs-nextbutton'); + + //update or reset the helper highlight class + oldHelperLayer.className = highlightClass; + //hide the tooltip + oldtooltipContainer.style.opacity = 0; + oldtooltipContainer.style.display = "none"; + + if (oldHelperNumberLayer != null) { + var lastIntroItem = this._introItems[(targetElement.step - 2 >= 0 ? targetElement.step - 2 : 0)]; + + if (lastIntroItem != null && (this._direction == 'forward' && lastIntroItem.position == 'floating') || (this._direction == 'backward' && targetElement.position == 'floating')) { + oldHelperNumberLayer.style.opacity = 0; + } + } + + //set new position to helper layer + _setHelperLayerPosition.call(self, oldHelperLayer); + _setHelperLayerPosition.call(self, oldReferenceLayer); + + //remove `introjs-fixParent` class from the elements + var fixParents = document.querySelectorAll('.introjs-fixParent'); + if (fixParents && fixParents.length > 0) { + for (var i = fixParents.length - 1; i >= 0; i--) { + fixParents[i].className = fixParents[i].className.replace(/introjs-fixParent/g, '').replace(/^\s+|\s+$/g, ''); + }; + } + + //remove old classes if the element still exist + _removeShowElement(); + + //we should wait until the CSS3 transition is competed (it's 0.3 sec) to prevent incorrect `height` and `width` calculation + if (self._lastShowElementTimer) { + clearTimeout(self._lastShowElementTimer); + } + + self._lastShowElementTimer = setTimeout(function() { + //set current step to the label + if (oldHelperNumberLayer != null) { + oldHelperNumberLayer.innerHTML = targetElement.step; + } + //set current tooltip text + oldtooltipLayer.innerHTML = targetElement.intro; + //set the tooltip position + oldtooltipContainer.style.display = "block"; + _placeTooltip.call(self, targetElement.element, oldtooltipContainer, oldArrowLayer, oldHelperNumberLayer); + + //change active bullet + if (self._options.showBullets) { + oldReferenceLayer.querySelector('.introjs-bullets li > a.active').className = ''; + oldReferenceLayer.querySelector('.introjs-bullets li > a[data-stepnumber="' + targetElement.step + '"]').className = 'active'; + } + oldReferenceLayer.querySelector('.introjs-progress .introjs-progressbar').setAttribute('style', 'width:' + _getProgress.call(self) + '%;'); + + //show the tooltip + oldtooltipContainer.style.opacity = 1; + if (oldHelperNumberLayer) oldHelperNumberLayer.style.opacity = 1; + + //reset button focus + if (typeof skipTooltipButton !== "undefined" && skipTooltipButton != null && /introjs-donebutton/gi.test(skipTooltipButton.className)) { + // skip button is now "done" button + skipTooltipButton.focus(); + } else if (typeof nextTooltipButton !== "undefined" && nextTooltipButton != null) { + //still in the tour, focus on next + nextTooltipButton.focus(); + } + + // change the scroll of the window, if needed + _scrollTo.call(self, targetElement.scrollTo, targetElement, oldtooltipLayer); + }, 350); + + // end of old element if-else condition + } else { + var helperLayer = document.createElement('div'), + referenceLayer = document.createElement('div'), + arrowLayer = document.createElement('div'), + tooltipLayer = document.createElement('div'), + tooltipTextLayer = document.createElement('div'), + bulletsLayer = document.createElement('div'), + progressLayer = document.createElement('div'), + buttonsLayer = document.createElement('div'); + + helperLayer.className = highlightClass; + referenceLayer.className = 'introjs-tooltipReferenceLayer'; + + //set new position to helper layer + _setHelperLayerPosition.call(self, helperLayer); + _setHelperLayerPosition.call(self, referenceLayer); + + //add helper layer to target element + this._targetElement.appendChild(helperLayer); + this._targetElement.appendChild(referenceLayer); + + arrowLayer.className = 'introjs-arrow'; + + tooltipTextLayer.className = 'introjs-tooltiptext'; + tooltipTextLayer.innerHTML = targetElement.intro; + + bulletsLayer.className = 'introjs-bullets'; + + if (this._options.showBullets === false) { + bulletsLayer.style.display = 'none'; + } + + var ulContainer = document.createElement('ul'); + + for (var i = 0, stepsLength = this._introItems.length; i < stepsLength; i++) { + var innerLi = document.createElement('li'); + var anchorLink = document.createElement('a'); + + anchorLink.onclick = function() { + self.goToStep(this.getAttribute('data-stepnumber')); + }; + + if (i === (targetElement.step-1)) anchorLink.className = 'active'; + + _setAnchorAsButton(anchorLink); + anchorLink.innerHTML = " "; + anchorLink.setAttribute('data-stepnumber', this._introItems[i].step); + + innerLi.appendChild(anchorLink); + ulContainer.appendChild(innerLi); + } + + bulletsLayer.appendChild(ulContainer); + + progressLayer.className = 'introjs-progress'; + + if (this._options.showProgress === false) { + progressLayer.style.display = 'none'; + } + var progressBar = document.createElement('div'); + progressBar.className = 'introjs-progressbar'; + progressBar.setAttribute('style', 'width:' + _getProgress.call(this) + '%;'); + + progressLayer.appendChild(progressBar); + + buttonsLayer.className = 'introjs-tooltipbuttons'; + if (this._options.showButtons === false) { + buttonsLayer.style.display = 'none'; + } + + tooltipLayer.className = 'introjs-tooltip'; + tooltipLayer.appendChild(tooltipTextLayer); + tooltipLayer.appendChild(bulletsLayer); + tooltipLayer.appendChild(progressLayer); + + //add helper layer number + if (this._options.showStepNumbers == true) { + var helperNumberLayer = document.createElement('span'); + helperNumberLayer.className = 'introjs-helperNumberLayer'; + helperNumberLayer.innerHTML = targetElement.step; + referenceLayer.appendChild(helperNumberLayer); + } + + tooltipLayer.appendChild(arrowLayer); + referenceLayer.appendChild(tooltipLayer); + + //next button + var nextTooltipButton = document.createElement('a'); + + nextTooltipButton.onclick = function() { + if (self._introItems.length - 1 != self._currentStep) { + _nextStep.call(self); + } + }; + + _setAnchorAsButton(nextTooltipButton); + nextTooltipButton.innerHTML = this._options.nextLabel; + + //previous button + var prevTooltipButton = document.createElement('a'); + + prevTooltipButton.onclick = function() { + if (self._currentStep != 0) { + _previousStep.call(self); + } + }; + + _setAnchorAsButton(prevTooltipButton); + prevTooltipButton.innerHTML = this._options.prevLabel; + + //skip button + var skipTooltipButton = document.createElement('a'); + skipTooltipButton.className = 'introjs-button introjs-skipbutton'; + _setAnchorAsButton(skipTooltipButton); + skipTooltipButton.innerHTML = this._options.skipLabel; + + skipTooltipButton.onclick = function() { + if (self._introItems.length - 1 == self._currentStep && typeof (self._introCompleteCallback) === 'function') { + self._introCompleteCallback.call(self); + } + + _exitIntro.call(self, self._targetElement); + }; + + buttonsLayer.appendChild(skipTooltipButton); + + //in order to prevent displaying next/previous button always + if (this._introItems.length > 1) { + buttonsLayer.appendChild(prevTooltipButton); + buttonsLayer.appendChild(nextTooltipButton); + } + + tooltipLayer.appendChild(buttonsLayer); + + //set proper position + _placeTooltip.call(self, targetElement.element, tooltipLayer, arrowLayer, helperNumberLayer); + + // change the scroll of the window, if needed + _scrollTo.call(this, targetElement.scrollTo, targetElement, tooltipLayer); + + //end of new element if-else condition + } + + // removing previous disable interaction layer + var disableInteractionLayer = self._targetElement.querySelector('.introjs-disableInteraction'); + if (disableInteractionLayer) { + disableInteractionLayer.parentNode.removeChild(disableInteractionLayer); + } + + //disable interaction + if (targetElement.disableInteraction) { + _disableInteraction.call(self); + } + + if (typeof nextTooltipButton !== "undefined" && nextTooltipButton != null) { + nextTooltipButton.removeAttribute('tabIndex'); + } + if (typeof prevTooltipButton !== "undefined" && prevTooltipButton != null) { + prevTooltipButton.removeAttribute('tabIndex'); + } + + // when it's the first step of tour + if (this._currentStep == 0 && this._introItems.length > 1) { + if (typeof skipTooltipButton !== "undefined" && skipTooltipButton != null) { + skipTooltipButton.className = 'introjs-button introjs-skipbutton'; + } + if (typeof nextTooltipButton !== "undefined" && nextTooltipButton != null) { + nextTooltipButton.className = 'introjs-button introjs-nextbutton'; + } + + if (this._options.hidePrev == true) { + if (typeof prevTooltipButton !== "undefined" && prevTooltipButton != null) { + prevTooltipButton.className = 'introjs-button introjs-prevbutton introjs-hidden'; + } + if (typeof nextTooltipButton !== "undefined" && nextTooltipButton != null) { + nextTooltipButton.className += ' introjs-fullbutton'; + } + } else { + if (typeof prevTooltipButton !== "undefined" && prevTooltipButton != null) { + prevTooltipButton.className = 'introjs-button introjs-prevbutton introjs-disabled'; + } + } + + if (typeof prevTooltipButton !== "undefined" && prevTooltipButton != null) { + prevTooltipButton.tabIndex = '-1'; + } + if (typeof skipTooltipButton !== "undefined" && skipTooltipButton != null) { + skipTooltipButton.innerHTML = this._options.skipLabel; + } + } else if (this._introItems.length - 1 == this._currentStep || this._introItems.length == 1) { + // last step of tour + if (typeof skipTooltipButton !== "undefined" && skipTooltipButton != null) { + skipTooltipButton.innerHTML = this._options.doneLabel; + // adding donebutton class in addition to skipbutton + skipTooltipButton.className += ' introjs-donebutton'; + } + if (typeof prevTooltipButton !== "undefined" && prevTooltipButton != null) { + prevTooltipButton.className = 'introjs-button introjs-prevbutton'; + } + + if (this._options.hideNext == true) { + if (typeof nextTooltipButton !== "undefined" && nextTooltipButton != null) { + nextTooltipButton.className = 'introjs-button introjs-nextbutton introjs-hidden'; + } + if (typeof prevTooltipButton !== "undefined" && prevTooltipButton != null) { + prevTooltipButton.className += ' introjs-fullbutton'; + } + } else { + if (typeof nextTooltipButton !== "undefined" && nextTooltipButton != null) { + nextTooltipButton.className = 'introjs-button introjs-nextbutton introjs-disabled'; + } + } + + if (typeof nextTooltipButton !== "undefined" && nextTooltipButton != null) { + nextTooltipButton.tabIndex = '-1'; + } + } else { + // steps between start and end + if (typeof skipTooltipButton !== "undefined" && skipTooltipButton != null) { + skipTooltipButton.className = 'introjs-button introjs-skipbutton'; + } + if (typeof prevTooltipButton !== "undefined" && prevTooltipButton != null) { + prevTooltipButton.className = 'introjs-button introjs-prevbutton'; + } + if (typeof nextTooltipButton !== "undefined" && nextTooltipButton != null) { + nextTooltipButton.className = 'introjs-button introjs-nextbutton'; + } + if (typeof skipTooltipButton !== "undefined" && skipTooltipButton != null) { + skipTooltipButton.innerHTML = this._options.skipLabel; + } + } + + //Set focus on "next" button, so that hitting Enter always moves you onto the next step + if (typeof nextTooltipButton !== "undefined" && nextTooltipButton != null) { + nextTooltipButton.focus(); + } + + _setShowElement(targetElement); + + if (typeof (this._introAfterChangeCallback) !== 'undefined') { + this._introAfterChangeCallback.call(this, targetElement.element); + } + } + + /** + * To change the scroll of `window` after highlighting an element + * + * @api private + * @method _scrollTo + * @param {String} scrollTo + * @param {Object} targetElement + * @param {Object} tooltipLayer + */ + function _scrollTo(scrollTo, targetElement, tooltipLayer) { + if (!this._options.scrollToElement) return; + + if (scrollTo === 'tooltip') { + var rect = tooltipLayer.getBoundingClientRect(); + } else { + var rect = targetElement.element.getBoundingClientRect(); + } + + if (!_elementInViewport(targetElement.element)) { + var winHeight = _getWinSize().height; + var top = rect.bottom - (rect.bottom - rect.top); + var bottom = rect.bottom - winHeight; + + // TODO (afshinm): do we need scroll padding now? + // I have changed the scroll option and now it scrolls the window to + // the center of the target element or tooltip. + + if (top < 0 || targetElement.element.clientHeight > winHeight) { + window.scrollBy(0, rect.top - ((winHeight / 2) - (rect.height / 2)) - this._options.scrollPadding); // 30px padding from edge to look nice + + //Scroll down + } else { + window.scrollBy(0, rect.top - ((winHeight / 2) - (rect.height / 2)) + this._options.scrollPadding); // 30px padding from edge to look nice + } + } + } + + /** + * To remove all show element(s) + * + * @api private + * @method _removeShowElement + */ + function _removeShowElement() { + var elms = document.querySelectorAll('.introjs-showElement'); + + for (var i = 0, l = elms.length; i < l; i++) { + var elm = elms[i]; + _removeClass(elm, /introjs-[a-zA-Z]+/g); + } + } + + /** + * To set the show element + * This function set a relative (in most cases) position and changes the z-index + * + * @api private + * @method _setShowElement + * @param {Object} targetElement + */ + function _setShowElement(targetElement) { + // we need to add this show element class to the parent of SVG elements + // because the SVG elements can't have independent z-index + if (targetElement.element instanceof SVGElement) { + var parentElm = targetElement.element.parentNode; + + while (targetElement.element.parentNode != null) { + if (!parentElm.tagName || parentElm.tagName.toLowerCase() === 'body') break; + + if (parentElm.tagName.toLowerCase() === 'svg') { + _setClass(parentElm, 'introjs-showElement introjs-relativePosition'); + } + + parentElm = parentElm.parentNode; + } + } + + _setClass(targetElement.element, 'introjs-showElement'); + + var currentElementPosition = _getPropValue(targetElement.element, 'position'); + if (currentElementPosition !== 'absolute' && + currentElementPosition !== 'relative' && + currentElementPosition !== 'fixed') { + //change to new intro item + //targetElement.element.className += ' introjs-relativePosition'; + _setClass(targetElement.element, 'introjs-relativePosition') + } + + var parentElm = targetElement.element.parentNode; + while (parentElm != null) { + if (!parentElm.tagName || parentElm.tagName.toLowerCase() === 'body') break; + + //fix The Stacking Context problem. + //More detail: https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context + var zIndex = _getPropValue(parentElm, 'z-index'); + var opacity = parseFloat(_getPropValue(parentElm, 'opacity')); + var transform = _getPropValue(parentElm, 'transform') || _getPropValue(parentElm, '-webkit-transform') || _getPropValue(parentElm, '-moz-transform') || _getPropValue(parentElm, '-ms-transform') || _getPropValue(parentElm, '-o-transform'); + if (/[0-9]+/.test(zIndex) || opacity < 1 || (transform !== 'none' && transform !== undefined)) { + parentElm.className += ' introjs-fixParent'; + } + + parentElm = parentElm.parentNode; + } + } + + function _setClass(element, className) { + if (element instanceof SVGElement) { + var pre = element.getAttribute('class') || ''; + + element.setAttribute('class', pre + ' ' + className); + } else { + element.className += ' ' + className; + } + } + + function _removeClass(element, classNameRegex) { + if (element instanceof SVGElement) { + var pre = element.getAttribute('class') || ''; + + element.setAttribute('class', pre.replace(classNameRegex, '').replace(/^\s+|\s+$/g, '')); + } else { + element.className = element.className.replace(classNameRegex, '').replace(/^\s+|\s+$/g, ''); + } + } + + /** + * Get an element CSS property on the page + * Thanks to JavaScript Kit: http://www.javascriptkit.com/dhtmltutors/dhtmlcascade4.shtml + * + * @api private + * @method _getPropValue + * @param {Object} element + * @param {String} propName + * @returns Element's property value + */ + function _getPropValue (element, propName) { + var propValue = ''; + if (element.currentStyle) { //IE + propValue = element.currentStyle[propName]; + } else if (document.defaultView && document.defaultView.getComputedStyle) { //Others + propValue = document.defaultView.getComputedStyle(element, null).getPropertyValue(propName); + } + + //Prevent exception in IE + if (propValue && propValue.toLowerCase) { + return propValue.toLowerCase(); + } else { + return propValue; + } + } + + /** + * Checks to see if target element (or parents) position is fixed or not + * + * @api private + * @method _isFixed + * @param {Object} element + * @returns Boolean + */ + function _isFixed (element) { + var p = element.parentNode; + + if (!p || p.nodeName === 'HTML') { + return false; + } + + if (_getPropValue(element, 'position') == 'fixed') { + return true; + } + + return _isFixed(p); + } + + /** + * Provides a cross-browser way to get the screen dimensions + * via: http://stackoverflow.com/questions/5864467/internet-explorer-innerheight + * + * @api private + * @method _getWinSize + * @returns {Object} width and height attributes + */ + function _getWinSize() { + if (window.innerWidth != undefined) { + return { width: window.innerWidth, height: window.innerHeight }; + } else { + var D = document.documentElement; + return { width: D.clientWidth, height: D.clientHeight }; + } + } + + /** + * Check to see if the element is in the viewport or not + * http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport + * + * @api private + * @method _elementInViewport + * @param {Object} el + */ + function _elementInViewport(el) { + var rect = el.getBoundingClientRect(); + + return ( + rect.top >= 0 && + rect.left >= 0 && + (rect.bottom+80) <= window.innerHeight && // add 80 to get the text right + rect.right <= window.innerWidth + ); + } + + /** + * Add overlay layer to the page + * + * @api private + * @method _addOverlayLayer + * @param {Object} targetElm + */ + function _addOverlayLayer(targetElm) { + var overlayLayer = document.createElement('div'), + styleText = '', + self = this; + + //set css class name + overlayLayer.className = 'introjs-overlay'; + + //check if the target element is body, we should calculate the size of overlay layer in a better way + if (!targetElm.tagName || targetElm.tagName.toLowerCase() === 'body') { + styleText += 'top: 0;bottom: 0; left: 0;right: 0;position: fixed;'; + overlayLayer.setAttribute('style', styleText); + } else { + //set overlay layer position + var elementPosition = _getOffset(targetElm); + if (elementPosition) { + styleText += 'width: ' + elementPosition.width + 'px; height:' + elementPosition.height + 'px; top:' + elementPosition.top + 'px;left: ' + elementPosition.left + 'px;'; + overlayLayer.setAttribute('style', styleText); + } + } + + targetElm.appendChild(overlayLayer); + + overlayLayer.onclick = function() { + if (self._options.exitOnOverlayClick == true) { + _exitIntro.call(self, targetElm); + } + }; + + setTimeout(function() { + styleText += 'opacity: ' + self._options.overlayOpacity.toString() + ';'; + overlayLayer.setAttribute('style', styleText); + }, 10); + + return true; + } + + /** + * Removes open hint (tooltip hint) + * + * @api private + * @method _removeHintTooltip + */ + function _removeHintTooltip() { + var tooltip = this._targetElement.querySelector('.introjs-hintReference'); + + if (tooltip) { + var step = tooltip.getAttribute('data-step'); + tooltip.parentNode.removeChild(tooltip); + return step; + } + } + + /** + * Start parsing hint items + * + * @api private + * @param {Object} targetElm + * @method _startHint + */ + function _populateHints(targetElm) { + var self = this; + this._introItems = []; + + if (this._options.hints) { + for (var i = 0, l = this._options.hints.length; i < l; i++) { + var currentItem = _cloneObject(this._options.hints[i]); + + if (typeof(currentItem.element) === 'string') { + //grab the element with given selector from the page + currentItem.element = document.querySelector(currentItem.element); + } + + currentItem.hintPosition = currentItem.hintPosition || this._options.hintPosition; + currentItem.hintAnimation = currentItem.hintAnimation || this._options.hintAnimation; + + if (currentItem.element != null) { + this._introItems.push(currentItem); + } + } + } else { + var hints = targetElm.querySelectorAll('*[data-hint]'); + + if (hints.length < 1) { + return false; + } + + //first add intro items with data-step + for (var i = 0, l = hints.length; i < l; i++) { + var currentElement = hints[i]; + + // hint animation + var hintAnimation = currentElement.getAttribute('data-hintAnimation'); + + if (hintAnimation) { + hintAnimation = (hintAnimation == 'true'); + } else { + hintAnimation = this._options.hintAnimation; + } + + this._introItems.push({ + element: currentElement, + hint: currentElement.getAttribute('data-hint'), + hintPosition: currentElement.getAttribute('data-hintPosition') || this._options.hintPosition, + hintAnimation: hintAnimation, + tooltipClass: currentElement.getAttribute('data-tooltipClass'), + position: currentElement.getAttribute('data-position') || this._options.tooltipPosition + }); + } + } + + _addHints.call(this); + + if (document.addEventListener) { + document.addEventListener('click', _removeHintTooltip.bind(this), false); + //for window resize + window.addEventListener('resize', _reAlignHints.bind(this), true); + } else if (document.attachEvent) { //IE + //for window resize + document.attachEvent('onclick', _removeHintTooltip.bind(this)); + document.attachEvent('onresize', _reAlignHints.bind(this)); + } + } + + /** + * Re-aligns all hint elements + * + * @api private + * @method _reAlignHints + */ + function _reAlignHints() { + for (var i = 0, l = this._introItems.length; i < l; i++) { + var item = this._introItems[i]; + + if (typeof (item.targetElement) == 'undefined') continue; + + _alignHintPosition.call(this, item.hintPosition, item.element, item.targetElement) + } + } + + /** + * Hide a hint + * + * @api private + * @method _hideHint + */ + function _hideHint(stepId) { + _removeHintTooltip.call(this); + var hint = this._targetElement.querySelector('.introjs-hint[data-step="' + stepId + '"]'); + + if (hint) { + hint.className += ' introjs-hidehint'; + } + + // call the callback function (if any) + if (typeof (this._hintCloseCallback) !== 'undefined') { + this._hintCloseCallback.call(this, stepId); + } + } + + /** + * Hide all hints + * + * @api private + * @method _hideHints + */ + function _hideHints() { + var hints = this._targetElement.querySelectorAll('.introjs-hint'); + + if (hints && hints.length > 0) { + for (var i = 0; i < hints.length; i++) { + _hideHint.call(this, hints[i].getAttribute('data-step')); + } + } + } + + /** + * Show all hints + * + * @api private + * @method _showHints + */ + function _showHints() { + var hints = this._targetElement.querySelectorAll('.introjs-hint'); + + if (hints && hints.length > 0) { + for (var i = 0; i < hints.length; i++) { + _showHint.call(this, hints[i].getAttribute('data-step')); + } + } else { + _populateHints.call(this, this._targetElement); + } + }; + + /** + * Show a hint + * + * @api private + * @method _showHint + */ + function _showHint(stepId) { + var hint = this._targetElement.querySelector('.introjs-hint[data-step="' + stepId + '"]'); + + if (hint) { + hint.className = hint.className.replace(/introjs\-hidehint/g, ''); + } + }; + + /** + * Removes all hint elements on the page + * Useful when you want to destroy the elements and add them again (e.g. a modal or popup) + * + * @api private + * @method _removeHints + */ + function _removeHints() { + var hints = this._targetElement.querySelectorAll('.introjs-hint'); + + if (hints && hints.length > 0) { + for (var i = 0; i < hints.length; i++) { + _removeHint.call(this, hints[i].getAttribute('data-step')); + } + } + }; + + /** + * Remove one single hint element from the page + * Useful when you want to destroy the element and add them again (e.g. a modal or popup) + * Use removeHints if you want to remove all elements. + * + * @api private + * @method _removeHint + */ + function _removeHint(stepId) { + var hint = this._targetElement.querySelector('.introjs-hint[data-step="' + stepId + '"]'); + + if (hint) { + hint.parentNode.removeChild(hint); + } + }; + + /** + * Add all available hints to the page + * + * @api private + * @method _addHints + */ + function _addHints() { + var self = this; + + var oldHintsWrapper = document.querySelector('.introjs-hints'); + + if (oldHintsWrapper != null) { + hintsWrapper = oldHintsWrapper; + } else { + var hintsWrapper = document.createElement('div'); + hintsWrapper.className = 'introjs-hints'; + } + + for (var i = 0, l = this._introItems.length; i < l; i++) { + var item = this._introItems[i]; + + // avoid append a hint twice + if (document.querySelector('.introjs-hint[data-step="' + i + '"]')) + continue; + + var hint = document.createElement('a'); + _setAnchorAsButton(hint); + + (function (hint, item, i) { + // when user clicks on the hint element + hint.onclick = function(e) { + var evt = e ? e : window.event; + if (evt.stopPropagation) evt.stopPropagation(); + if (evt.cancelBubble != null) evt.cancelBubble = true; + + _showHintDialog.call(self, i); + }; + }(hint, item, i)); + + hint.className = 'introjs-hint'; + + if (!item.hintAnimation) { + hint.className += ' introjs-hint-no-anim'; + } + + // hint's position should be fixed if the target element's position is fixed + if (_isFixed(item.element)) { + hint.className += ' introjs-fixedhint'; + } + + var hintDot = document.createElement('div'); + hintDot.className = 'introjs-hint-dot'; + var hintPulse = document.createElement('div'); + hintPulse.className = 'introjs-hint-pulse'; + + hint.appendChild(hintDot); + hint.appendChild(hintPulse); + hint.setAttribute('data-step', i); + + // we swap the hint element with target element + // because _setHelperLayerPosition uses `element` property + item.targetElement = item.element; + item.element = hint; + + // align the hint position + _alignHintPosition.call(this, item.hintPosition, hint, item.targetElement); + + hintsWrapper.appendChild(hint); + } + + // adding the hints wrapper + document.body.appendChild(hintsWrapper); + + // call the callback function (if any) + if (typeof (this._hintsAddedCallback) !== 'undefined') { + this._hintsAddedCallback.call(this); + } + } + + /** + * Aligns hint position + * + * @api private + * @method _alignHintPosition + * @param {String} position + * @param {Object} hint + * @param {Object} element + */ + function _alignHintPosition(position, hint, element) { + // get/calculate offset of target element + var offset = _getOffset.call(this, element); + var iconWidth = 20; + var iconHeight = 20; + + // align the hint element + switch (position) { + default: + case 'top-left': + hint.style.left = offset.left + 'px'; + hint.style.top = offset.top + 'px'; + break; + case 'top-right': + hint.style.left = (offset.left + offset.width - iconWidth) + 'px'; + hint.style.top = offset.top + 'px'; + break; + case 'bottom-left': + hint.style.left = offset.left + 'px'; + hint.style.top = (offset.top + offset.height - iconHeight) + 'px'; + break; + case 'bottom-right': + hint.style.left = (offset.left + offset.width - iconWidth) + 'px'; + hint.style.top = (offset.top + offset.height - iconHeight) + 'px'; + break; + case 'middle-left': + hint.style.left = offset.left + 'px'; + hint.style.top = (offset.top + (offset.height - iconHeight) / 2) + 'px'; + break; + case 'middle-right': + hint.style.left = (offset.left + offset.width - iconWidth) + 'px'; + hint.style.top = (offset.top + (offset.height - iconHeight) / 2) + 'px'; + break; + case 'middle-middle': + hint.style.left = (offset.left + (offset.width - iconWidth) / 2) + 'px'; + hint.style.top = (offset.top + (offset.height - iconHeight) / 2) + 'px'; + break; + case 'bottom-middle': + hint.style.left = (offset.left + (offset.width - iconWidth) / 2) + 'px'; + hint.style.top = (offset.top + offset.height - iconHeight) + 'px'; + break; + case 'top-middle': + hint.style.left = (offset.left + (offset.width - iconWidth) / 2) + 'px'; + hint.style.top = offset.top + 'px'; + break; + } + } + + /** + * Triggers when user clicks on the hint element + * + * @api private + * @method _showHintDialog + * @param {Number} stepId + */ + function _showHintDialog(stepId) { + var hintElement = document.querySelector('.introjs-hint[data-step="' + stepId + '"]'); + var item = this._introItems[stepId]; + + // call the callback function (if any) + if (typeof (this._hintClickCallback) !== 'undefined') { + this._hintClickCallback.call(this, hintElement, item, stepId); + } + + // remove all open tooltips + var removedStep = _removeHintTooltip.call(this); + + // to toggle the tooltip + if (parseInt(removedStep, 10) == stepId) { + return; + } + + var tooltipLayer = document.createElement('div'); + var tooltipTextLayer = document.createElement('div'); + var arrowLayer = document.createElement('div'); + var referenceLayer = document.createElement('div'); + + tooltipLayer.className = 'introjs-tooltip'; + + tooltipLayer.onclick = function (e) { + //IE9 & Other Browsers + if (e.stopPropagation) { + e.stopPropagation(); + } + //IE8 and Lower + else { + e.cancelBubble = true; + } + }; + + tooltipTextLayer.className = 'introjs-tooltiptext'; + + var tooltipWrapper = document.createElement('p'); + tooltipWrapper.innerHTML = item.hint; + + var closeButton = document.createElement('a'); + closeButton.className = 'introjs-button'; + closeButton.innerHTML = this._options.hintButtonLabel; + closeButton.onclick = _hideHint.bind(this, stepId); + + tooltipTextLayer.appendChild(tooltipWrapper); + tooltipTextLayer.appendChild(closeButton); + + arrowLayer.className = 'introjs-arrow'; + tooltipLayer.appendChild(arrowLayer); + + tooltipLayer.appendChild(tooltipTextLayer); + + // set current step for _placeTooltip function + this._currentStep = hintElement.getAttribute('data-step'); + + // align reference layer position + referenceLayer.className = 'introjs-tooltipReferenceLayer introjs-hintReference'; + referenceLayer.setAttribute('data-step', hintElement.getAttribute('data-step')); + _setHelperLayerPosition.call(this, referenceLayer); + + referenceLayer.appendChild(tooltipLayer); + document.body.appendChild(referenceLayer); + + //set proper position + _placeTooltip.call(this, hintElement, tooltipLayer, arrowLayer, null, true); + } + + /** + * Get an element position on the page + * Thanks to `meouw`: http://stackoverflow.com/a/442474/375966 + * + * @api private + * @method _getOffset + * @param {Object} element + * @returns Element's position info + */ + function _getOffset(element) { + var elementPosition = {}; + + var body = document.body; + var docEl = document.documentElement; + + var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop; + var scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft; + + if (element instanceof SVGElement) { + var x = element.getBoundingClientRect() + elementPosition.top = x.top + scrollTop; + elementPosition.width = x.width; + elementPosition.height = x.height; + elementPosition.left = x.left + scrollLeft; + } else { + //set width + elementPosition.width = element.offsetWidth; + + //set height + elementPosition.height = element.offsetHeight; + + //calculate element top and left + var _x = 0; + var _y = 0; + while (element && !isNaN(element.offsetLeft) && !isNaN(element.offsetTop)) { + _x += element.offsetLeft; + _y += element.offsetTop; + element = element.offsetParent; + } + //set top + elementPosition.top = _y; + //set left + elementPosition.left = _x; + } + + return elementPosition; + } + + /** + * Gets the current progress percentage + * + * @api private + * @method _getProgress + * @returns current progress percentage + */ + function _getProgress() { + // Steps are 0 indexed + var currentStep = parseInt((this._currentStep + 1), 10); + return ((currentStep / this._introItems.length) * 100); + } + + /** + * Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1 + * via: http://stackoverflow.com/questions/171251/how-can-i-merge-properties-of-two-javascript-objects-dynamically + * + * @param obj1 + * @param obj2 + * @returns obj3 a new object based on obj1 and obj2 + */ + function _mergeOptions(obj1,obj2) { + var obj3 = {}; + for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; } + for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; } + return obj3; + } + + var introJs = function (targetElm) { + if (typeof (targetElm) === 'object') { + //Ok, create a new instance + return new IntroJs(targetElm); + + } else if (typeof (targetElm) === 'string') { + //select the target element with query selector + var targetElement = document.querySelector(targetElm); + + if (targetElement) { + return new IntroJs(targetElement); + } else { + throw new Error('There is no element with given selector.'); + } + } else { + return new IntroJs(document.body); + } + }; + + /** + * Current IntroJs version + * + * @property version + * @type String + */ + introJs.version = VERSION; + + //Prototype + introJs.fn = IntroJs.prototype = { + clone: function () { + return new IntroJs(this); + }, + setOption: function(option, value) { + this._options[option] = value; + return this; + }, + setOptions: function(options) { + this._options = _mergeOptions(this._options, options); + return this; + }, + start: function () { + _introForElement.call(this, this._targetElement); + return this; + }, + goToStep: function(step) { + _goToStep.call(this, step); + return this; + }, + addStep: function(options) { + if (!this._options.steps) { + this._options.steps = []; + } + + this._options.steps.push(options); + + return this; + }, + addSteps: function(steps) { + if (!steps.length) return; + + for(var index = 0; index < steps.length; index++) { + this.addStep(steps[index]); + } + + return this; + }, + goToStepNumber: function(step) { + _goToStepNumber.call(this, step); + + return this; + }, + nextStep: function() { + _nextStep.call(this); + return this; + }, + previousStep: function() { + _previousStep.call(this); + return this; + }, + exit: function(force) { + _exitIntro.call(this, this._targetElement, force); + return this; + }, + refresh: function() { + _refresh.call(this); + return this; + }, + onbeforechange: function(providedCallback) { + if (typeof (providedCallback) === 'function') { + this._introBeforeChangeCallback = providedCallback; + } else { + throw new Error('Provided callback for onbeforechange was not a function'); + } + return this; + }, + onchange: function(providedCallback) { + if (typeof (providedCallback) === 'function') { + this._introChangeCallback = providedCallback; + } else { + throw new Error('Provided callback for onchange was not a function.'); + } + return this; + }, + onafterchange: function(providedCallback) { + if (typeof (providedCallback) === 'function') { + this._introAfterChangeCallback = providedCallback; + } else { + throw new Error('Provided callback for onafterchange was not a function'); + } + return this; + }, + oncomplete: function(providedCallback) { + if (typeof (providedCallback) === 'function') { + this._introCompleteCallback = providedCallback; + } else { + throw new Error('Provided callback for oncomplete was not a function.'); + } + return this; + }, + onhintsadded: function(providedCallback) { + if (typeof (providedCallback) === 'function') { + this._hintsAddedCallback = providedCallback; + } else { + throw new Error('Provided callback for onhintsadded was not a function.'); + } + return this; + }, + onhintclick: function(providedCallback) { + if (typeof (providedCallback) === 'function') { + this._hintClickCallback = providedCallback; + } else { + throw new Error('Provided callback for onhintclick was not a function.'); + } + return this; + }, + onhintclose: function(providedCallback) { + if (typeof (providedCallback) === 'function') { + this._hintCloseCallback = providedCallback; + } else { + throw new Error('Provided callback for onhintclose was not a function.'); + } + return this; + }, + onexit: function(providedCallback) { + if (typeof (providedCallback) === 'function') { + this._introExitCallback = providedCallback; + } else { + throw new Error('Provided callback for onexit was not a function.'); + } + return this; + }, + onbeforeexit: function(providedCallback) { + if (typeof (providedCallback) === 'function') { + this._introBeforeExitCallback = providedCallback; + } else { + throw new Error('Provided callback for onbeforeexit was not a function.'); + } + return this; + }, + addHints: function() { + _populateHints.call(this, this._targetElement); + return this; + }, + hideHint: function (stepId) { + _hideHint.call(this, stepId); + return this; + }, + hideHints: function () { + _hideHints.call(this); + return this; + }, + showHint: function (stepId) { + _showHint.call(this, stepId); + return this; + }, + showHints: function () { + _showHints.call(this); + return this; + }, + removeHints: function () { + _removeHints.call(this); + return this; + }, + removeHint: function (stepId) { + _removeHint.call(this, stepId); + return this; + }, + showHintDialog: function (stepId) { + _showHintDialog.call(this, stepId); + return this; + } + }; + + exports.introJs = introJs; + return introJs; +})); diff --git a/app/assets/stylesheets/introjs.css b/app/assets/stylesheets/introjs.css index 94afec6..8cd9ae0 100644 --- a/app/assets/stylesheets/introjs.css +++ b/app/assets/stylesheets/introjs.css @@ -1 +1,519 @@ -.introjs-overlay{position:absolute;z-index:999999;background-color:#000;opacity:0;background:-moz-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);background:-webkit-gradient(radial,center center,0px,center center,100%,color-stop(0%,rgba(0,0,0,0.4)),color-stop(100%,rgba(0,0,0,0.9)));background:-webkit-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);background:-o-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);background:-ms-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);background:radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#66000000',endColorstr='#e6000000',GradientType=1);-ms-filter:"alpha(opacity=50)";filter:alpha(opacity=50);-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-ms-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}.introjs-fixParent{z-index:auto!important;opacity:1.0!important;position:absolute!important;-webkit-transform:none!important;-moz-transform:none!important;-ms-transform:none!important;-o-transform:none!important;transform:none!important}.introjs-showElement,tr.introjs-showElement>td,tr.introjs-showElement>th{z-index:9999999!important}.introjs-disableInteraction{z-index:99999999!important;position:absolute}.introjs-relativePosition,tr.introjs-showElement>td,tr.introjs-showElement>th{position:relative}.introjs-helperLayer{position:absolute;z-index:9999998;background-color:#FFF;background-color:rgba(255,255,255,.9);border:1px solid #777;border:1px solid rgba(0,0,0,.5);border-radius:4px;box-shadow:0 2px 15px rgba(0,0,0,.4);-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-ms-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}.introjs-tooltipReferenceLayer{position:absolute;z-index:10000000;background-color:transparent;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-ms-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}.introjs-helperLayer *,.introjs-helperLayer *:before,.introjs-helperLayer *:after{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;-ms-box-sizing:content-box;-o-box-sizing:content-box;box-sizing:content-box}.introjs-helperNumberLayer{position:absolute;top:-16px;left:-16px;z-index:9999999999!important;padding:2px;font-family:Arial,verdana,tahoma;font-size:13px;font-weight:bold;color:white;text-align:center;text-shadow:1px 1px 1px rgba(0,0,0,.3);background:#ff3019;background:-webkit-linear-gradient(top,#ff3019 0,#cf0404 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#ff3019),color-stop(100%,#cf0404));background:-moz-linear-gradient(top,#ff3019 0,#cf0404 100%);background:-ms-linear-gradient(top,#ff3019 0,#cf0404 100%);background:-o-linear-gradient(top,#ff3019 0,#cf0404 100%);background:linear-gradient(to bottom,#ff3019 0,#cf0404 100%);width:20px;height:20px;line-height:20px;border:3px solid white;border-radius:50%;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3019',endColorstr='#cf0404',GradientType=0);filter:progid:DXImageTransform.Microsoft.Shadow(direction=135,strength=2,color=ff0000);box-shadow:0 2px 5px rgba(0,0,0,.4)}.introjs-arrow{border:5px solid white;content:'';position:absolute}.introjs-arrow.top{top:-10px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:white;border-left-color:transparent}.introjs-arrow.top-right{top:-10px;right:10px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:white;border-left-color:transparent}.introjs-arrow.top-middle{top:-10px;left:50%;margin-left:-5px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:white;border-left-color:transparent}.introjs-arrow.right{right:-10px;top:10px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:transparent;border-left-color:white}.introjs-arrow.right-bottom{bottom:10px;right:-10px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:transparent;border-left-color:white}.introjs-arrow.bottom{bottom:-10px;border-top-color:white;border-right-color:transparent;border-bottom-color:transparent;border-left-color:transparent}.introjs-arrow.left{left:-10px;top:10px;border-top-color:transparent;border-right-color:white;border-bottom-color:transparent;border-left-color:transparent}.introjs-arrow.left-bottom{left:-10px;bottom:10px;border-top-color:transparent;border-right-color:white;border-bottom-color:transparent;border-left-color:transparent}.introjs-tooltip{position:absolute;padding:10px;background-color:white;min-width:200px;max-width:300px;border-radius:3px;box-shadow:0 1px 10px rgba(0,0,0,.4);-webkit-transition:opacity .1s ease-out;-moz-transition:opacity .1s ease-out;-ms-transition:opacity .1s ease-out;-o-transition:opacity .1s ease-out;transition:opacity .1s ease-out}.introjs-tooltipbuttons{text-align:right;white-space:nowrap}.introjs-button{position:relative;overflow:visible;display:inline-block;padding:.3em .8em;border:1px solid #d4d4d4;margin:0;text-decoration:none;text-shadow:1px 1px 0 #fff;font:11px/normal sans-serif;color:#333;white-space:nowrap;cursor:pointer;outline:0;background-color:#ececec;background-image:-webkit-gradient(linear,0 0,0 100%,from(#f4f4f4),to(#ececec));background-image:-moz-linear-gradient(#f4f4f4,#ececec);background-image:-o-linear-gradient(#f4f4f4,#ececec);background-image:linear-gradient(#f4f4f4,#ececec);-webkit-background-clip:padding;-moz-background-clip:padding;-o-background-clip:padding-box;-webkit-border-radius:.2em;-moz-border-radius:.2em;border-radius:.2em;zoom:1;*display:inline;margin-top:10px}.introjs-button:hover{border-color:#bcbcbc;text-decoration:none;box-shadow:0 1px 1px #e3e3e3}.introjs-button:focus,.introjs-button:active{background-image:-webkit-gradient(linear,0 0,0 100%,from(#ececec),to(#f4f4f4));background-image:-moz-linear-gradient(#ececec,#f4f4f4);background-image:-o-linear-gradient(#ececec,#f4f4f4);background-image:linear-gradient(#ececec,#f4f4f4)}.introjs-button::-moz-focus-inner{padding:0;border:0}.introjs-skipbutton{margin-right:5px;color:#7a7a7a}.introjs-prevbutton{-webkit-border-radius:.2em 0 0 .2em;-moz-border-radius:.2em 0 0 .2em;border-radius:.2em 0 0 .2em;border-right:0}.introjs-nextbutton{-webkit-border-radius:0 .2em .2em 0;-moz-border-radius:0 .2em .2em 0;border-radius:0 .2em .2em 0}.introjs-disabled,.introjs-disabled:hover,.introjs-disabled:focus{color:#9a9a9a;border-color:#d4d4d4;box-shadow:none;cursor:default;background-color:#f4f4f4;background-image:none;text-decoration:none}.introjs-bullets{text-align:center}.introjs-bullets ul{clear:both;margin:15px auto 0;padding:0;display:inline-block}.introjs-bullets ul li{list-style:none;float:left;margin:0 2px}.introjs-bullets ul li a{display:block;width:6px;height:6px;background:#ccc;border-radius:10px;-moz-border-radius:10px;-webkit-border-radius:10px;text-decoration:none}.introjs-bullets ul li a:hover{background:#999}.introjs-bullets ul li a.active{background:#999}.introjs-progress{overflow:hidden;height:10px;margin:10px 0 5px 0;border-radius:4px;background-color:#ecf0f1}.introjs-progressbar{float:left;width:0;height:100%;font-size:10px;line-height:10px;text-align:center;background-color:#08c}.introjsFloatingElement{position:absolute;height:0;width:0;left:50%;top:50%} \ No newline at end of file +.introjs-overlay { + position: absolute; + box-sizing: content-box; + z-index: 999999; + background-color: #000; + opacity: 0; + background: -moz-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%); + background: -webkit-gradient(radial,center center,0px,center center,100%,color-stop(0%,rgba(0,0,0,0.4)),color-stop(100%,rgba(0,0,0,0.9))); + background: -webkit-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%); + background: -o-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%); + background: -ms-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%); + background: radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%); + filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#66000000',endColorstr='#e6000000',GradientType=1)"; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; + filter: alpha(opacity=50); + -webkit-transition: all 0.3s ease-out; + -moz-transition: all 0.3s ease-out; + -ms-transition: all 0.3s ease-out; + -o-transition: all 0.3s ease-out; + transition: all 0.3s ease-out; +} + +.introjs-fixParent { + z-index: auto !important; + opacity: 1.0 !important; + -webkit-transform: none !important; + -moz-transform: none !important; + -ms-transform: none !important; + -o-transform: none !important; + transform: none !important; +} + +.introjs-showElement, +tr.introjs-showElement > td, +tr.introjs-showElement > th { + z-index: 9999999 !important; +} + +.introjs-disableInteraction { + z-index: 99999999 !important; + position: absolute; + background-color: white; + opacity: 0; + filter: alpha(opacity=0); +} + +.introjs-relativePosition, +tr.introjs-showElement > td, +tr.introjs-showElement > th { + position: relative; +} + +.introjs-helperLayer { + box-sizing: content-box; + position: absolute; + z-index: 9999998; + background-color: #FFF; + background-color: rgba(255,255,255,.9); + border: 1px solid #777; + border: 1px solid rgba(0,0,0,.5); + border-radius: 4px; + box-shadow: 0 2px 15px rgba(0,0,0,.4); + -webkit-transition: all 0.3s ease-out; + -moz-transition: all 0.3s ease-out; + -ms-transition: all 0.3s ease-out; + -o-transition: all 0.3s ease-out; + transition: all 0.3s ease-out; +} + +.introjs-tooltipReferenceLayer { + box-sizing: content-box; + position: absolute; + visibility: hidden; + z-index: 10000000; + background-color: transparent; + -webkit-transition: all 0.3s ease-out; + -moz-transition: all 0.3s ease-out; + -ms-transition: all 0.3s ease-out; + -o-transition: all 0.3s ease-out; + transition: all 0.3s ease-out; +} + +.introjs-helperLayer *, +.introjs-helperLayer *:before, +.introjs-helperLayer *:after { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + -ms-box-sizing: content-box; + -o-box-sizing: content-box; + box-sizing: content-box; +} + +.introjs-helperNumberLayer { + box-sizing: content-box; + position: absolute; + visibility: visible; + top: -16px; + left: -16px; + z-index: 9999999999 !important; + padding: 2px; + font-family: Arial, verdana, tahoma; + font-size: 13px; + font-weight: bold; + color: white; + text-align: center; + text-shadow: 1px 1px 1px rgba(0,0,0,.3); + background: #ff3019; /* Old browsers */ + background: -webkit-linear-gradient(top, #ff3019 0%, #cf0404 100%); /* Chrome10+,Safari5.1+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ff3019), color-stop(100%, #cf0404)); /* Chrome,Safari4+ */ + background: -moz-linear-gradient(top, #ff3019 0%, #cf0404 100%); /* FF3.6+ */ + background: -ms-linear-gradient(top, #ff3019 0%, #cf0404 100%); /* IE10+ */ + background: -o-linear-gradient(top, #ff3019 0%, #cf0404 100%); /* Opera 11.10+ */ + background: linear-gradient(to bottom, #ff3019 0%, #cf0404 100%); /* W3C */ + width: 20px; + height:20px; + line-height: 20px; + border: 3px solid white; + border-radius: 50%; + filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3019', endColorstr='#cf0404', GradientType=0)"; /* IE6-9 */ + filter: "progid:DXImageTransform.Microsoft.Shadow(direction=135, strength=2, color=ff0000)"; /* IE10 text shadows */ + box-shadow: 0 2px 5px rgba(0,0,0,.4); +} + +.introjs-arrow { + border: 5px solid white; + content:''; + position: absolute; +} +.introjs-arrow.top { + top: -10px; + border-top-color:transparent; + border-right-color:transparent; + border-bottom-color:white; + border-left-color:transparent; +} +.introjs-arrow.top-right { + top: -10px; + right: 10px; + border-top-color:transparent; + border-right-color:transparent; + border-bottom-color:white; + border-left-color:transparent; +} +.introjs-arrow.top-middle { + top: -10px; + left: 50%; + margin-left: -5px; + border-top-color:transparent; + border-right-color:transparent; + border-bottom-color:white; + border-left-color:transparent; +} +.introjs-arrow.right { + right: -10px; + top: 10px; + border-top-color:transparent; + border-right-color:transparent; + border-bottom-color:transparent; + border-left-color:white; +} +.introjs-arrow.right-bottom { + bottom:10px; + right: -10px; + border-top-color:transparent; + border-right-color:transparent; + border-bottom-color:transparent; + border-left-color:white; +} +.introjs-arrow.bottom { + bottom: -10px; + border-top-color:white; + border-right-color:transparent; + border-bottom-color:transparent; + border-left-color:transparent; +} +.introjs-arrow.left { + left: -10px; + top: 10px; + border-top-color:transparent; + border-right-color:white; + border-bottom-color:transparent; + border-left-color:transparent; +} +.introjs-arrow.left-bottom { + left: -10px; + bottom:10px; + border-top-color:transparent; + border-right-color:white; + border-bottom-color:transparent; + border-left-color:transparent; +} + +.introjs-tooltip { + box-sizing: content-box; + position: absolute; + visibility: visible; + padding: 10px; + background-color: white; + min-width: 200px; + max-width: 300px; + border-radius: 3px; + box-shadow: 0 1px 10px rgba(0,0,0,.4); + -webkit-transition: opacity 0.1s ease-out; + -moz-transition: opacity 0.1s ease-out; + -ms-transition: opacity 0.1s ease-out; + -o-transition: opacity 0.1s ease-out; + transition: opacity 0.1s ease-out; +} + +.introjs-tooltipbuttons { + text-align: right; + white-space: nowrap; +} + +/* + Buttons style by http://nicolasgallagher.com/lab/css3-github-buttons/ + Changed by Afshin Mehrabani +*/ +.introjs-button { + box-sizing: content-box; + position: relative; + overflow: visible; + display: inline-block; + padding: 0.3em 0.8em; + border: 1px solid #d4d4d4; + margin: 0; + text-decoration: none; + text-shadow: 1px 1px 0 #fff; + font: 11px/normal sans-serif; + color: #333; + white-space: nowrap; + cursor: pointer; + outline: none; + background-color: #ececec; + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f4f4f4), to(#ececec)); + background-image: -moz-linear-gradient(#f4f4f4, #ececec); + background-image: -o-linear-gradient(#f4f4f4, #ececec); + background-image: linear-gradient(#f4f4f4, #ececec); + -webkit-background-clip: padding; + -moz-background-clip: padding; + -o-background-clip: padding-box; + /*background-clip: padding-box;*/ /* commented out due to Opera 11.10 bug */ + -webkit-border-radius: 0.2em; + -moz-border-radius: 0.2em; + border-radius: 0.2em; + /* IE hacks */ + zoom: 1; + *display: inline; + margin-top: 10px; +} + +.introjs-button:hover { + border-color: #bcbcbc; + text-decoration: none; + box-shadow: 0px 1px 1px #e3e3e3; +} + +.introjs-button:focus, +.introjs-button:active { + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ececec), to(#f4f4f4)); + background-image: -moz-linear-gradient(#ececec, #f4f4f4); + background-image: -o-linear-gradient(#ececec, #f4f4f4); + background-image: linear-gradient(#ececec, #f4f4f4); +} + +/* overrides extra padding on button elements in Firefox */ +.introjs-button::-moz-focus-inner { + padding: 0; + border: 0; +} + +.introjs-skipbutton { + box-sizing: content-box; + margin-right: 5px; + color: #7a7a7a; +} + +.introjs-prevbutton { + -webkit-border-radius: 0.2em 0 0 0.2em; + -moz-border-radius: 0.2em 0 0 0.2em; + border-radius: 0.2em 0 0 0.2em; + border-right: none; +} + +.introjs-prevbutton.introjs-fullbutton { + border: 1px solid #d4d4d4; + -webkit-border-radius: 0.2em; + -moz-border-radius: 0.2em; + border-radius: 0.2em; +} + +.introjs-nextbutton { + -webkit-border-radius: 0 0.2em 0.2em 0; + -moz-border-radius: 0 0.2em 0.2em 0; + border-radius: 0 0.2em 0.2em 0; +} + +.introjs-nextbutton.introjs-fullbutton { + -webkit-border-radius: 0.2em; + -moz-border-radius: 0.2em; + border-radius: 0.2em; +} + +.introjs-disabled, .introjs-disabled:hover, .introjs-disabled:focus { + color: #9a9a9a; + border-color: #d4d4d4; + box-shadow: none; + cursor: default; + background-color: #f4f4f4; + background-image: none; + text-decoration: none; +} + +.introjs-hidden { + display: none; +} + +.introjs-bullets { + text-align: center; +} +.introjs-bullets ul { + box-sizing: content-box; + clear: both; + margin: 15px auto 0; + padding: 0; + display: inline-block; +} +.introjs-bullets ul li { + box-sizing: content-box; + list-style: none; + float: left; + margin: 0 2px; +} +.introjs-bullets ul li a { + box-sizing: content-box; + display: block; + width: 6px; + height: 6px; + background: #ccc; + border-radius: 10px; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + text-decoration: none; + cursor: pointer; +} +.introjs-bullets ul li a:hover { + background: #999; +} +.introjs-bullets ul li a.active { + background: #999; +} + +.introjs-progress { + box-sizing: content-box; + overflow: hidden; + height: 10px; + margin: 10px 0 5px 0; + border-radius: 4px; + background-color: #ecf0f1 +} +.introjs-progressbar { + box-sizing: content-box; + float: left; + width: 0%; + height: 100%; + font-size: 10px; + line-height: 10px; + text-align: center; + background-color: #08c; +} + +.introjsFloatingElement { + position: absolute; + height: 0; + width: 0; + left: 50%; + top: 50%; +} + +.introjs-fixedTooltip { + position: fixed; +} + +.introjs-hint { + box-sizing: content-box; + position: absolute; + background: transparent; + width: 20px; + height: 15px; + cursor: pointer; +} +.introjs-hint:focus { + border: 0; + outline: 0; +} +.introjs-hidehint { + display: none; +} + +.introjs-fixedhint { + position: fixed; +} + +.introjs-hint:hover > .introjs-hint-pulse { + border: 5px solid rgba(60, 60, 60, 0.57); +} + +.introjs-hint-pulse { + box-sizing: content-box; + width: 10px; + height: 10px; + border: 5px solid rgba(60, 60, 60, 0.27); + -webkit-border-radius: 30px; + -moz-border-radius: 30px; + border-radius: 30px; + background-color: rgba(136, 136, 136, 0.24); + z-index: 10; + position: absolute; + -webkit-transition: all 0.2s ease-out; + -moz-transition: all 0.2s ease-out; + -ms-transition: all 0.2s ease-out; + -o-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; +} +.introjs-hint-no-anim .introjs-hint-dot { + -webkit-animation: none; + -moz-animation: none; + animation: none; +} +.introjs-hint-dot { + box-sizing: content-box; + border: 10px solid rgba(146, 146, 146, 0.36); + background: transparent; + -webkit-border-radius: 60px; + -moz-border-radius: 60px; + border-radius: 60px; + height: 50px; + width: 50px; + -webkit-animation: introjspulse 3s ease-out; + -moz-animation: introjspulse 3s ease-out; + animation: introjspulse 3s ease-out; + -webkit-animation-iteration-count: infinite; + -moz-animation-iteration-count: infinite; + animation-iteration-count: infinite; + position: absolute; + top: -25px; + left: -25px; + z-index: 1; + opacity: 0; +} + +@-webkit-keyframes introjspulse { + 0% { + -webkit-transform: scale(0); + opacity: 0.0; + } + 25% { + -webkit-transform: scale(0); + opacity: 0.1; + } + 50% { + -webkit-transform: scale(0.1); + opacity: 0.3; + } + 75% { + -webkit-transform: scale(0.5); + opacity: 0.5; + } + 100% { + -webkit-transform: scale(1); + opacity: 0.0; + } +} + +@-moz-keyframes introjspulse { + 0% { + -moz-transform: scale(0); + opacity: 0.0; + } + 25% { + -moz-transform: scale(0); + opacity: 0.1; + } + 50% { + -moz-transform: scale(0.1); + opacity: 0.3; + } + 75% { + -moz-transform: scale(0.5); + opacity: 0.5; + } + 100% { + -moz-transform: scale(1); + opacity: 0.0; + } +} + +@keyframes introjspulse { + 0% { + transform: scale(0); + opacity: 0.0; + } + 25% { + transform: scale(0); + opacity: 0.1; + } + 50% { + transform: scale(0.1); + opacity: 0.3; + } + 75% { + transform: scale(0.5); + opacity: 0.5; + } + 100% { + transform: scale(1); + opacity: 0.0; + } +} diff --git a/lib/introjs-rails/version.rb b/lib/introjs-rails/version.rb index ac9c084..31963c4 100644 --- a/lib/introjs-rails/version.rb +++ b/lib/introjs-rails/version.rb @@ -1,5 +1,5 @@ module Introjs module Rails - VERSION = "1.0.0" + VERSION = "2.7.0" end end From d9e254ed8319bb6794562fe505317df915bc558e Mon Sep 17 00:00:00 2001 From: Miguel Angel Arenas Correa Date: Mon, 4 Dec 2017 21:46:07 -0500 Subject: [PATCH 2/3] Add minified files js and css --- app/assets/javascripts/introjs.js | 2193 +------------------- app/assets/stylesheets/introjs-rtl.css | 1 + app/assets/stylesheets/introjs-rtl.min.css | 1 + app/assets/stylesheets/introjs.css | 520 +---- 4 files changed, 57 insertions(+), 2658 deletions(-) create mode 100755 app/assets/stylesheets/introjs-rtl.css create mode 100755 app/assets/stylesheets/introjs-rtl.min.css diff --git a/app/assets/javascripts/introjs.js b/app/assets/javascripts/introjs.js index f679916..d7ebc0c 100644 --- a/app/assets/javascripts/introjs.js +++ b/app/assets/javascripts/introjs.js @@ -1,2139 +1,54 @@ -/** - * Intro.js v2.7.0 - * https://github.com/usablica/intro.js - * - * Copyright (C) 2017 Afshin Mehrabani (@afshinmeh) - */ - -(function (root, factory) { - if (typeof exports === 'object') { - // CommonJS - factory(exports); - } else if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module. - define(['exports'], factory); - } else { - // Browser globals - factory(root); - } -} (this, function (exports) { - //Default config/variables - var VERSION = '2.7.0'; - - /** - * IntroJs main class - * - * @class IntroJs - */ - function IntroJs(obj) { - this._targetElement = obj; - this._introItems = []; - - this._options = { - /* Next button label in tooltip box */ - nextLabel: 'Next →', - /* Previous button label in tooltip box */ - prevLabel: '← Back', - /* Skip button label in tooltip box */ - skipLabel: 'Skip', - /* Done button label in tooltip box */ - doneLabel: 'Done', - /* Hide previous button in the first step? Otherwise, it will be disabled button. */ - hidePrev: false, - /* Hide next button in the last step? Otherwise, it will be disabled button. */ - hideNext: false, - /* Default tooltip box position */ - tooltipPosition: 'bottom', - /* Next CSS class for tooltip boxes */ - tooltipClass: '', - /* CSS class that is added to the helperLayer */ - highlightClass: '', - /* Close introduction when pressing Escape button? */ - exitOnEsc: true, - /* Close introduction when clicking on overlay layer? */ - exitOnOverlayClick: true, - /* Show step numbers in introduction? */ - showStepNumbers: true, - /* Let user use keyboard to navigate the tour? */ - keyboardNavigation: true, - /* Show tour control buttons? */ - showButtons: true, - /* Show tour bullets? */ - showBullets: true, - /* Show tour progress? */ - showProgress: false, - /* Scroll to highlighted element? */ - scrollToElement: true, - /* - * Should we scroll the tooltip or target element? - * - * Options are: 'element' or 'tooltip' - */ - scrollTo: 'element', - /* Padding to add after scrolling when element is not in the viewport (in pixels) */ - scrollPadding: 30, - /* Set the overlay opacity */ - overlayOpacity: 0.8, - /* Precedence of positions, when auto is enabled */ - positionPrecedence: ["bottom", "top", "right", "left"], - /* Disable an interaction with element? */ - disableInteraction: false, - /* Default hint position */ - hintPosition: 'top-middle', - /* Hint button label */ - hintButtonLabel: 'Got it', - /* Adding animation to hints? */ - hintAnimation: true - }; - } - - /** - * Initiate a new introduction/guide from an element in the page - * - * @api private - * @method _introForElement - * @param {Object} targetElm - * @returns {Boolean} Success or not? - */ - function _introForElement(targetElm) { - var introItems = [], - self = this; - - if (this._options.steps) { - //use steps passed programmatically - for (var i = 0, stepsLength = this._options.steps.length; i < stepsLength; i++) { - var currentItem = _cloneObject(this._options.steps[i]); - - //set the step - currentItem.step = introItems.length + 1; - - //use querySelector function only when developer used CSS selector - if (typeof (currentItem.element) === 'string') { - //grab the element with given selector from the page - currentItem.element = document.querySelector(currentItem.element); - } - - //intro without element - if (typeof (currentItem.element) === 'undefined' || currentItem.element == null) { - var floatingElementQuery = document.querySelector(".introjsFloatingElement"); - - if (floatingElementQuery == null) { - floatingElementQuery = document.createElement('div'); - floatingElementQuery.className = 'introjsFloatingElement'; - - document.body.appendChild(floatingElementQuery); - } - - currentItem.element = floatingElementQuery; - currentItem.position = 'floating'; - } - - currentItem.scrollTo = currentItem.scrollTo || this._options.scrollTo; - - if (typeof (currentItem.disableInteraction) === 'undefined') { - currentItem.disableInteraction = this._options.disableInteraction; - } - - if (currentItem.element != null) { - introItems.push(currentItem); - } - } - - } else { - //use steps from data-* annotations - var allIntroSteps = targetElm.querySelectorAll('*[data-intro]'); - //if there's no element to intro - if (allIntroSteps.length < 1) { - return false; - } - - //first add intro items with data-step - for (var i = 0, elmsLength = allIntroSteps.length; i < elmsLength; i++) { - var currentElement = allIntroSteps[i]; - - // skip hidden elements - if (currentElement.style.display == 'none') { - continue; - } - - var step = parseInt(currentElement.getAttribute('data-step'), 10); - - var disableInteraction = this._options.disableInteraction; - - if (typeof (currentElement.getAttribute('data-disable-interaction')) != 'undefined') { - disableInteraction = !!currentElement.getAttribute('data-disable-interaction'); - } - - if (step > 0) { - introItems[step - 1] = { - element: currentElement, - intro: currentElement.getAttribute('data-intro'), - step: parseInt(currentElement.getAttribute('data-step'), 10), - tooltipClass: currentElement.getAttribute('data-tooltipClass'), - highlightClass: currentElement.getAttribute('data-highlightClass'), - position: currentElement.getAttribute('data-position') || this._options.tooltipPosition, - scrollTo: currentElement.getAttribute('data-scrollTo') || this._options.scrollTo, - disableInteraction: disableInteraction - }; - } - } - - //next add intro items without data-step - //todo: we need a cleanup here, two loops are redundant - var nextStep = 0; - for (var i = 0, elmsLength = allIntroSteps.length; i < elmsLength; i++) { - var currentElement = allIntroSteps[i]; - - if (currentElement.getAttribute('data-step') == null) { - - while (true) { - if (typeof introItems[nextStep] == 'undefined') { - break; - } else { - nextStep++; - } - } - - var disableInteraction = this._options.disableInteraction; - - if (typeof (currentElement.getAttribute('data-disable-interaction')) != 'undefined') { - disableInteraction = !!currentElement.getAttribute('data-disable-interaction'); - } - - introItems[nextStep] = { - element: currentElement, - intro: currentElement.getAttribute('data-intro'), - step: nextStep + 1, - tooltipClass: currentElement.getAttribute('data-tooltipClass'), - highlightClass: currentElement.getAttribute('data-highlightClass'), - position: currentElement.getAttribute('data-position') || this._options.tooltipPosition, - scrollTo: currentElement.getAttribute('data-scrollTo') || this._options.scrollTo, - disableInteraction: disableInteraction - }; - } - } - } - - //removing undefined/null elements - var tempIntroItems = []; - for (var z = 0; z < introItems.length; z++) { - introItems[z] && tempIntroItems.push(introItems[z]); // copy non-empty values to the end of the array - } - - introItems = tempIntroItems; - - //Ok, sort all items with given steps - introItems.sort(function (a, b) { - return a.step - b.step; - }); - - //set it to the introJs object - self._introItems = introItems; - - //add overlay layer to the page - if(_addOverlayLayer.call(self, targetElm)) { - //then, start the show - _nextStep.call(self); - - var skipButton = targetElm.querySelector('.introjs-skipbutton'), - nextStepButton = targetElm.querySelector('.introjs-nextbutton'); - - self._onKeyDown = function(e) { - if (e.keyCode === 27 && self._options.exitOnEsc == true) { - //escape key pressed, exit the intro - //check if exit callback is defined - _exitIntro.call(self, targetElm); - } else if(e.keyCode === 37) { - //left arrow - _previousStep.call(self); - } else if (e.keyCode === 39) { - //right arrow - _nextStep.call(self); - } else if (e.keyCode === 13) { - //srcElement === ie - var target = e.target || e.srcElement; - if (target && target.className.indexOf('introjs-prevbutton') > 0) { - //user hit enter while focusing on previous button - _previousStep.call(self); - } else if (target && target.className.indexOf('introjs-skipbutton') > 0) { - //user hit enter while focusing on skip button - if (self._introItems.length - 1 == self._currentStep && typeof (self._introCompleteCallback) === 'function') { - self._introCompleteCallback.call(self); - } - - _exitIntro.call(self, targetElm); - } else { - //default behavior for responding to enter - _nextStep.call(self); - } - - //prevent default behaviour on hitting Enter, to prevent steps being skipped in some browsers - if(e.preventDefault) { - e.preventDefault(); - } else { - e.returnValue = false; - } - } - }; - - self._onResize = function(e) { - self.refresh.call(self); - }; - - if (window.addEventListener) { - if (this._options.keyboardNavigation) { - window.addEventListener('keydown', self._onKeyDown, true); - } - //for window resize - window.addEventListener('resize', self._onResize, true); - } else if (document.attachEvent) { //IE - if (this._options.keyboardNavigation) { - document.attachEvent('onkeydown', self._onKeyDown); - } - //for window resize - document.attachEvent('onresize', self._onResize); - } - } - return false; - } - - /* - * makes a copy of the object - * @api private - * @method _cloneObject - */ - function _cloneObject(object) { - if (object == null || typeof (object) != 'object' || typeof (object.nodeType) != 'undefined') { - return object; - } - var temp = {}; - for (var key in object) { - if (typeof (jQuery) != 'undefined' && object[key] instanceof jQuery) { - temp[key] = object[key]; - } else { - temp[key] = _cloneObject(object[key]); - } - } - return temp; - } - /** - * Go to specific step of introduction - * - * @api private - * @method _goToStep - */ - function _goToStep(step) { - //because steps starts with zero - this._currentStep = step - 2; - if (typeof (this._introItems) !== 'undefined') { - _nextStep.call(this); - } - } - - /** - * Go to the specific step of introduction with the explicit [data-step] number - * - * @api private - * @method _goToStepNumber - */ - function _goToStepNumber(step) { - this._currentStepNumber = step; - if (typeof (this._introItems) !== 'undefined') { - _nextStep.call(this); - } - } - - /** - * Go to next step on intro - * - * @api private - * @method _nextStep - */ - function _nextStep() { - this._direction = 'forward'; - - if (typeof (this._currentStepNumber) !== 'undefined') { - for( var i = 0, len = this._introItems.length; i < len; i++ ) { - var item = this._introItems[i]; - if( item.step === this._currentStepNumber ) { - this._currentStep = i - 1; - this._currentStepNumber = undefined; - } - } - } - - if (typeof (this._currentStep) === 'undefined') { - this._currentStep = 0; - } else { - ++this._currentStep; - } - - if ((this._introItems.length) <= this._currentStep) { - //end of the intro - //check if any callback is defined - if (typeof (this._introCompleteCallback) === 'function') { - this._introCompleteCallback.call(this); - } - _exitIntro.call(this, this._targetElement); - return; - } - - var nextStep = this._introItems[this._currentStep]; - if (typeof (this._introBeforeChangeCallback) !== 'undefined') { - this._introBeforeChangeCallback.call(this, nextStep.element); - } - - _showElement.call(this, nextStep); - } - - /** - * Go to previous step on intro - * - * @api private - * @method _previousStep - */ - function _previousStep() { - this._direction = 'backward'; - - if (this._currentStep === 0) { - return false; - } - - var nextStep = this._introItems[--this._currentStep]; - if (typeof (this._introBeforeChangeCallback) !== 'undefined') { - this._introBeforeChangeCallback.call(this, nextStep.element); - } - - _showElement.call(this, nextStep); - } - - /** - * Update placement of the intro objects on the screen - * @api private - */ - function _refresh() { - // re-align intros - _setHelperLayerPosition.call(this, document.querySelector('.introjs-helperLayer')); - _setHelperLayerPosition.call(this, document.querySelector('.introjs-tooltipReferenceLayer')); - - // re-align tooltip - if(this._currentStep !== undefined && this._currentStep !== null) { - var oldHelperNumberLayer = document.querySelector('.introjs-helperNumberLayer'), - oldArrowLayer = document.querySelector('.introjs-arrow'), - oldtooltipContainer = document.querySelector('.introjs-tooltip'); - _placeTooltip.call(this, this._introItems[this._currentStep].element, oldtooltipContainer, oldArrowLayer, oldHelperNumberLayer); - } - - //re-align hints - _reAlignHints.call(this); - return this; - } - - /** - * Exit from intro - * - * @api private - * @method _exitIntro - * @param {Object} targetElement - * @param {Boolean} force - Setting to `true` will skip the result of beforeExit callback - */ - function _exitIntro(targetElement, force) { - var continueExit = true; - - // calling onbeforeexit callback - // - // If this callback return `false`, it would halt the process - if (this._introBeforeExitCallback != undefined) { - continueExit = this._introBeforeExitCallback.call(self); - } - - // skip this check if `force` parameter is `true` - // otherwise, if `onbeforeexit` returned `false`, don't exit the intro - if (!force && continueExit === false) return; - - //remove overlay layers from the page - var overlayLayers = targetElement.querySelectorAll('.introjs-overlay'); - - if (overlayLayers && overlayLayers.length > 0) { - for (var i = overlayLayers.length - 1; i >= 0; i--) { - //for fade-out animation - var overlayLayer = overlayLayers[i]; - overlayLayer.style.opacity = 0; - setTimeout(function () { - if (this.parentNode) { - this.parentNode.removeChild(this); - } - }.bind(overlayLayer), 500); - }; - } - - //remove all helper layers - var helperLayer = targetElement.querySelector('.introjs-helperLayer'); - if (helperLayer) { - helperLayer.parentNode.removeChild(helperLayer); - } - - var referenceLayer = targetElement.querySelector('.introjs-tooltipReferenceLayer'); - if (referenceLayer) { - referenceLayer.parentNode.removeChild(referenceLayer); - } - - //remove disableInteractionLayer - var disableInteractionLayer = targetElement.querySelector('.introjs-disableInteraction'); - if (disableInteractionLayer) { - disableInteractionLayer.parentNode.removeChild(disableInteractionLayer); - } - - //remove intro floating element - var floatingElement = document.querySelector('.introjsFloatingElement'); - if (floatingElement) { - floatingElement.parentNode.removeChild(floatingElement); - } - - _removeShowElement(); - - //remove `introjs-fixParent` class from the elements - var fixParents = document.querySelectorAll('.introjs-fixParent'); - if (fixParents && fixParents.length > 0) { - for (var i = fixParents.length - 1; i >= 0; i--) { - fixParents[i].className = fixParents[i].className.replace(/introjs-fixParent/g, '').replace(/^\s+|\s+$/g, ''); - } - } - - //clean listeners - if (window.removeEventListener) { - window.removeEventListener('keydown', this._onKeyDown, true); - } else if (document.detachEvent) { //IE - document.detachEvent('onkeydown', this._onKeyDown); - } - - //check if any callback is defined - if (this._introExitCallback != undefined) { - this._introExitCallback.call(self); - } - - //set the step to zero - this._currentStep = undefined; - } - - /** - * Render tooltip box in the page - * - * @api private - * @method _placeTooltip - * @param {HTMLElement} targetElement - * @param {HTMLElement} tooltipLayer - * @param {HTMLElement} arrowLayer - * @param {HTMLElement} helperNumberLayer - * @param {Boolean} hintMode - */ - function _placeTooltip(targetElement, tooltipLayer, arrowLayer, helperNumberLayer, hintMode) { - var tooltipCssClass = '', - currentStepObj, - tooltipOffset, - targetOffset, - windowSize, - currentTooltipPosition; - - hintMode = hintMode || false; - - //reset the old style - tooltipLayer.style.top = null; - tooltipLayer.style.right = null; - tooltipLayer.style.bottom = null; - tooltipLayer.style.left = null; - tooltipLayer.style.marginLeft = null; - tooltipLayer.style.marginTop = null; - - arrowLayer.style.display = 'inherit'; - - if (typeof(helperNumberLayer) != 'undefined' && helperNumberLayer != null) { - helperNumberLayer.style.top = null; - helperNumberLayer.style.left = null; - } - - //prevent error when `this._currentStep` is undefined - if (!this._introItems[this._currentStep]) return; - - //if we have a custom css class for each step - currentStepObj = this._introItems[this._currentStep]; - if (typeof (currentStepObj.tooltipClass) === 'string') { - tooltipCssClass = currentStepObj.tooltipClass; - } else { - tooltipCssClass = this._options.tooltipClass; - } - - tooltipLayer.className = ('introjs-tooltip ' + tooltipCssClass).replace(/^\s+|\s+$/g, ''); - - currentTooltipPosition = this._introItems[this._currentStep].position; - - if (currentTooltipPosition != "floating") { // Floating is always valid, no point in calculating - if (currentTooltipPosition === "auto") { - currentTooltipPosition = _determineAutoPosition.call(this, targetElement, tooltipLayer); - } else { - currentTooltipPosition = _determineAutoPosition.call(this, targetElement, tooltipLayer, currentTooltipPosition); - } - } - - targetOffset = _getOffset(targetElement); - tooltipOffset = _getOffset(tooltipLayer); - windowSize = _getWinSize(); - - switch (currentTooltipPosition) { - case 'top': - arrowLayer.className = 'introjs-arrow bottom'; - - if (hintMode) { - var tooltipLayerStyleLeft = 0; - } else { - var tooltipLayerStyleLeft = 15; - } - - _checkRight(targetOffset, tooltipLayerStyleLeft, tooltipOffset, windowSize, tooltipLayer); - tooltipLayer.style.bottom = (targetOffset.height + 20) + 'px'; - break; - case 'right': - tooltipLayer.style.left = (targetOffset.width + 20) + 'px'; - if (targetOffset.top + tooltipOffset.height > windowSize.height) { - // In this case, right would have fallen below the bottom of the screen. - // Modify so that the bottom of the tooltip connects with the target - arrowLayer.className = "introjs-arrow left-bottom"; - tooltipLayer.style.top = "-" + (tooltipOffset.height - targetOffset.height - 20) + "px"; - } else { - arrowLayer.className = 'introjs-arrow left'; - } - break; - case 'left': - if (!hintMode && this._options.showStepNumbers == true) { - tooltipLayer.style.top = '15px'; - } - - if (targetOffset.top + tooltipOffset.height > windowSize.height) { - // In this case, left would have fallen below the bottom of the screen. - // Modify so that the bottom of the tooltip connects with the target - tooltipLayer.style.top = "-" + (tooltipOffset.height - targetOffset.height - 20) + "px"; - arrowLayer.className = 'introjs-arrow right-bottom'; - } else { - arrowLayer.className = 'introjs-arrow right'; - } - tooltipLayer.style.right = (targetOffset.width + 20) + 'px'; - - break; - case 'floating': - arrowLayer.style.display = 'none'; - - //we have to adjust the top and left of layer manually for intro items without element - tooltipLayer.style.left = '50%'; - tooltipLayer.style.top = '50%'; - tooltipLayer.style.marginLeft = '-' + (tooltipOffset.width / 2) + 'px'; - tooltipLayer.style.marginTop = '-' + (tooltipOffset.height / 2) + 'px'; - - if (typeof(helperNumberLayer) != 'undefined' && helperNumberLayer != null) { - helperNumberLayer.style.left = '-' + ((tooltipOffset.width / 2) + 18) + 'px'; - helperNumberLayer.style.top = '-' + ((tooltipOffset.height / 2) + 18) + 'px'; - } - - break; - case 'bottom-right-aligned': - arrowLayer.className = 'introjs-arrow top-right'; - - var tooltipLayerStyleRight = 0; - _checkLeft(targetOffset, tooltipLayerStyleRight, tooltipOffset, tooltipLayer); - tooltipLayer.style.top = (targetOffset.height + 20) + 'px'; - break; - - case 'bottom-middle-aligned': - arrowLayer.className = 'introjs-arrow top-middle'; - - var tooltipLayerStyleLeftRight = targetOffset.width / 2 - tooltipOffset.width / 2; - - // a fix for middle aligned hints - if (hintMode) { - tooltipLayerStyleLeftRight += 5; - } - - if (_checkLeft(targetOffset, tooltipLayerStyleLeftRight, tooltipOffset, tooltipLayer)) { - tooltipLayer.style.right = null; - _checkRight(targetOffset, tooltipLayerStyleLeftRight, tooltipOffset, windowSize, tooltipLayer); - } - tooltipLayer.style.top = (targetOffset.height + 20) + 'px'; - break; - - case 'bottom-left-aligned': - // Bottom-left-aligned is the same as the default bottom - case 'bottom': - // Bottom going to follow the default behavior - default: - arrowLayer.className = 'introjs-arrow top'; - - var tooltipLayerStyleLeft = 0; - _checkRight(targetOffset, tooltipLayerStyleLeft, tooltipOffset, windowSize, tooltipLayer); - tooltipLayer.style.top = (targetOffset.height + 20) + 'px'; - break; - } - } - - /** - * Set tooltip left so it doesn't go off the right side of the window - * - * @return boolean true, if tooltipLayerStyleLeft is ok. false, otherwise. - */ - function _checkRight(targetOffset, tooltipLayerStyleLeft, tooltipOffset, windowSize, tooltipLayer) { - if (targetOffset.left + tooltipLayerStyleLeft + tooltipOffset.width > windowSize.width) { - // off the right side of the window - tooltipLayer.style.left = (windowSize.width - tooltipOffset.width - targetOffset.left) + 'px'; - return false; - } - tooltipLayer.style.left = tooltipLayerStyleLeft + 'px'; - return true; - } - - /** - * Set tooltip right so it doesn't go off the left side of the window - * - * @return boolean true, if tooltipLayerStyleRight is ok. false, otherwise. - */ - function _checkLeft(targetOffset, tooltipLayerStyleRight, tooltipOffset, tooltipLayer) { - if (targetOffset.left + targetOffset.width - tooltipLayerStyleRight - tooltipOffset.width < 0) { - // off the left side of the window - tooltipLayer.style.left = (-targetOffset.left) + 'px'; - return false; - } - tooltipLayer.style.right = tooltipLayerStyleRight + 'px'; - return true; - } - - /** - * Determines the position of the tooltip based on the position precedence and availability - * of screen space. - * - * @param {Object} targetElement - * @param {Object} tooltipLayer - * @param {Object} desiredTooltipPosition - * - */ - function _determineAutoPosition(targetElement, tooltipLayer, desiredTooltipPosition) { - - // Take a clone of position precedence. These will be the available - var possiblePositions = this._options.positionPrecedence.slice(); - - var windowSize = _getWinSize(); - var tooltipHeight = _getOffset(tooltipLayer).height + 10; - var tooltipWidth = _getOffset(tooltipLayer).width + 20; - var targetOffset = _getOffset(targetElement); - - // If we check all the possible areas, and there are no valid places for the tooltip, the element - // must take up most of the screen real estate. Show the tooltip floating in the middle of the screen. - var calculatedPosition = "floating"; - - // Check if the width of the tooltip + the starting point would spill off the right side of the screen - // If no, neither bottom or top are valid - if (targetOffset.left + tooltipWidth > windowSize.width || ((targetOffset.left + (targetOffset.width / 2)) - tooltipWidth) < 0) { - _removeEntry(possiblePositions, "bottom"); - _removeEntry(possiblePositions, "top"); - } else { - // Check for space below - if ((targetOffset.height + targetOffset.top + tooltipHeight) > windowSize.height) { - _removeEntry(possiblePositions, "bottom"); - } - - // Check for space above - if (targetOffset.top - tooltipHeight < 0) { - _removeEntry(possiblePositions, "top"); - } - } - - // Check for space to the right - if (targetOffset.width + targetOffset.left + tooltipWidth > windowSize.width) { - _removeEntry(possiblePositions, "right"); - } - - // Check for space to the left - if (targetOffset.left - tooltipWidth < 0) { - _removeEntry(possiblePositions, "left"); - } - - // At this point, our array only has positions that are valid. Pick the first one, as it remains in order - if (possiblePositions.length > 0) { - calculatedPosition = possiblePositions[0]; - } - - // If the requested position is in the list, replace our calculated choice with that - if (desiredTooltipPosition && desiredTooltipPosition != "auto") { - if (possiblePositions.indexOf(desiredTooltipPosition) > -1) { - calculatedPosition = desiredTooltipPosition; - } - } - - return calculatedPosition; - } - - /** - * Remove an entry from a string array if it's there, does nothing if it isn't there. - * - * @param {Array} stringArray - * @param {String} stringToRemove - */ - function _removeEntry(stringArray, stringToRemove) { - if (stringArray.indexOf(stringToRemove) > -1) { - stringArray.splice(stringArray.indexOf(stringToRemove), 1); - } - } - - /** - * Update the position of the helper layer on the screen - * - * @api private - * @method _setHelperLayerPosition - * @param {Object} helperLayer - */ - function _setHelperLayerPosition(helperLayer) { - if (helperLayer) { - //prevent error when `this._currentStep` in undefined - if (!this._introItems[this._currentStep]) return; - - var currentElement = this._introItems[this._currentStep], - elementPosition = _getOffset(currentElement.element), - widthHeightPadding = 10; - - // If the target element is fixed, the tooltip should be fixed as well. - // Otherwise, remove a fixed class that may be left over from the previous - // step. - if (_isFixed(currentElement.element)) { - helperLayer.className += ' introjs-fixedTooltip'; - } else { - helperLayer.className = helperLayer.className.replace(' introjs-fixedTooltip', ''); - } - - if (currentElement.position == 'floating') { - widthHeightPadding = 0; - } - - //set new position to helper layer - helperLayer.setAttribute('style', 'width: ' + (elementPosition.width + widthHeightPadding) + 'px; ' + - 'height:' + (elementPosition.height + widthHeightPadding) + 'px; ' + - 'top:' + (elementPosition.top - 5) + 'px;' + - 'left: ' + (elementPosition.left - 5) + 'px;'); - - } - } - - /** - * Add disableinteraction layer and adjust the size and position of the layer - * - * @api private - * @method _disableInteraction - */ - function _disableInteraction() { - var disableInteractionLayer = document.querySelector('.introjs-disableInteraction'); - - if (disableInteractionLayer === null) { - disableInteractionLayer = document.createElement('div'); - disableInteractionLayer.className = 'introjs-disableInteraction'; - this._targetElement.appendChild(disableInteractionLayer); - } - - _setHelperLayerPosition.call(this, disableInteractionLayer); - } - - /** - * Setting anchors to behave like buttons - * - * @api private - * @method _setAnchorAsButton - */ - function _setAnchorAsButton(anchor){ - anchor.setAttribute('role', 'button'); - anchor.tabIndex = 0; - } - - /** - * Show an element on the page - * - * @api private - * @method _showElement - * @param {Object} targetElement - */ - function _showElement(targetElement) { - if (typeof (this._introChangeCallback) !== 'undefined') { - this._introChangeCallback.call(this, targetElement.element); - } - - var self = this, - oldHelperLayer = document.querySelector('.introjs-helperLayer'), - oldReferenceLayer = document.querySelector('.introjs-tooltipReferenceLayer'), - highlightClass = 'introjs-helperLayer', - elementPosition = _getOffset(targetElement.element); - - //check for a current step highlight class - if (typeof (targetElement.highlightClass) === 'string') { - highlightClass += (' ' + targetElement.highlightClass); - } - //check for options highlight class - if (typeof (this._options.highlightClass) === 'string') { - highlightClass += (' ' + this._options.highlightClass); - } - - if (oldHelperLayer != null) { - var oldHelperNumberLayer = oldReferenceLayer.querySelector('.introjs-helperNumberLayer'), - oldtooltipLayer = oldReferenceLayer.querySelector('.introjs-tooltiptext'), - oldArrowLayer = oldReferenceLayer.querySelector('.introjs-arrow'), - oldtooltipContainer = oldReferenceLayer.querySelector('.introjs-tooltip'), - skipTooltipButton = oldReferenceLayer.querySelector('.introjs-skipbutton'), - prevTooltipButton = oldReferenceLayer.querySelector('.introjs-prevbutton'), - nextTooltipButton = oldReferenceLayer.querySelector('.introjs-nextbutton'); - - //update or reset the helper highlight class - oldHelperLayer.className = highlightClass; - //hide the tooltip - oldtooltipContainer.style.opacity = 0; - oldtooltipContainer.style.display = "none"; - - if (oldHelperNumberLayer != null) { - var lastIntroItem = this._introItems[(targetElement.step - 2 >= 0 ? targetElement.step - 2 : 0)]; - - if (lastIntroItem != null && (this._direction == 'forward' && lastIntroItem.position == 'floating') || (this._direction == 'backward' && targetElement.position == 'floating')) { - oldHelperNumberLayer.style.opacity = 0; - } - } - - //set new position to helper layer - _setHelperLayerPosition.call(self, oldHelperLayer); - _setHelperLayerPosition.call(self, oldReferenceLayer); - - //remove `introjs-fixParent` class from the elements - var fixParents = document.querySelectorAll('.introjs-fixParent'); - if (fixParents && fixParents.length > 0) { - for (var i = fixParents.length - 1; i >= 0; i--) { - fixParents[i].className = fixParents[i].className.replace(/introjs-fixParent/g, '').replace(/^\s+|\s+$/g, ''); - }; - } - - //remove old classes if the element still exist - _removeShowElement(); - - //we should wait until the CSS3 transition is competed (it's 0.3 sec) to prevent incorrect `height` and `width` calculation - if (self._lastShowElementTimer) { - clearTimeout(self._lastShowElementTimer); - } - - self._lastShowElementTimer = setTimeout(function() { - //set current step to the label - if (oldHelperNumberLayer != null) { - oldHelperNumberLayer.innerHTML = targetElement.step; - } - //set current tooltip text - oldtooltipLayer.innerHTML = targetElement.intro; - //set the tooltip position - oldtooltipContainer.style.display = "block"; - _placeTooltip.call(self, targetElement.element, oldtooltipContainer, oldArrowLayer, oldHelperNumberLayer); - - //change active bullet - if (self._options.showBullets) { - oldReferenceLayer.querySelector('.introjs-bullets li > a.active').className = ''; - oldReferenceLayer.querySelector('.introjs-bullets li > a[data-stepnumber="' + targetElement.step + '"]').className = 'active'; - } - oldReferenceLayer.querySelector('.introjs-progress .introjs-progressbar').setAttribute('style', 'width:' + _getProgress.call(self) + '%;'); - - //show the tooltip - oldtooltipContainer.style.opacity = 1; - if (oldHelperNumberLayer) oldHelperNumberLayer.style.opacity = 1; - - //reset button focus - if (typeof skipTooltipButton !== "undefined" && skipTooltipButton != null && /introjs-donebutton/gi.test(skipTooltipButton.className)) { - // skip button is now "done" button - skipTooltipButton.focus(); - } else if (typeof nextTooltipButton !== "undefined" && nextTooltipButton != null) { - //still in the tour, focus on next - nextTooltipButton.focus(); - } - - // change the scroll of the window, if needed - _scrollTo.call(self, targetElement.scrollTo, targetElement, oldtooltipLayer); - }, 350); - - // end of old element if-else condition - } else { - var helperLayer = document.createElement('div'), - referenceLayer = document.createElement('div'), - arrowLayer = document.createElement('div'), - tooltipLayer = document.createElement('div'), - tooltipTextLayer = document.createElement('div'), - bulletsLayer = document.createElement('div'), - progressLayer = document.createElement('div'), - buttonsLayer = document.createElement('div'); - - helperLayer.className = highlightClass; - referenceLayer.className = 'introjs-tooltipReferenceLayer'; - - //set new position to helper layer - _setHelperLayerPosition.call(self, helperLayer); - _setHelperLayerPosition.call(self, referenceLayer); - - //add helper layer to target element - this._targetElement.appendChild(helperLayer); - this._targetElement.appendChild(referenceLayer); - - arrowLayer.className = 'introjs-arrow'; - - tooltipTextLayer.className = 'introjs-tooltiptext'; - tooltipTextLayer.innerHTML = targetElement.intro; - - bulletsLayer.className = 'introjs-bullets'; - - if (this._options.showBullets === false) { - bulletsLayer.style.display = 'none'; - } - - var ulContainer = document.createElement('ul'); - - for (var i = 0, stepsLength = this._introItems.length; i < stepsLength; i++) { - var innerLi = document.createElement('li'); - var anchorLink = document.createElement('a'); - - anchorLink.onclick = function() { - self.goToStep(this.getAttribute('data-stepnumber')); - }; - - if (i === (targetElement.step-1)) anchorLink.className = 'active'; - - _setAnchorAsButton(anchorLink); - anchorLink.innerHTML = " "; - anchorLink.setAttribute('data-stepnumber', this._introItems[i].step); - - innerLi.appendChild(anchorLink); - ulContainer.appendChild(innerLi); - } - - bulletsLayer.appendChild(ulContainer); - - progressLayer.className = 'introjs-progress'; - - if (this._options.showProgress === false) { - progressLayer.style.display = 'none'; - } - var progressBar = document.createElement('div'); - progressBar.className = 'introjs-progressbar'; - progressBar.setAttribute('style', 'width:' + _getProgress.call(this) + '%;'); - - progressLayer.appendChild(progressBar); - - buttonsLayer.className = 'introjs-tooltipbuttons'; - if (this._options.showButtons === false) { - buttonsLayer.style.display = 'none'; - } - - tooltipLayer.className = 'introjs-tooltip'; - tooltipLayer.appendChild(tooltipTextLayer); - tooltipLayer.appendChild(bulletsLayer); - tooltipLayer.appendChild(progressLayer); - - //add helper layer number - if (this._options.showStepNumbers == true) { - var helperNumberLayer = document.createElement('span'); - helperNumberLayer.className = 'introjs-helperNumberLayer'; - helperNumberLayer.innerHTML = targetElement.step; - referenceLayer.appendChild(helperNumberLayer); - } - - tooltipLayer.appendChild(arrowLayer); - referenceLayer.appendChild(tooltipLayer); - - //next button - var nextTooltipButton = document.createElement('a'); - - nextTooltipButton.onclick = function() { - if (self._introItems.length - 1 != self._currentStep) { - _nextStep.call(self); - } - }; - - _setAnchorAsButton(nextTooltipButton); - nextTooltipButton.innerHTML = this._options.nextLabel; - - //previous button - var prevTooltipButton = document.createElement('a'); - - prevTooltipButton.onclick = function() { - if (self._currentStep != 0) { - _previousStep.call(self); - } - }; - - _setAnchorAsButton(prevTooltipButton); - prevTooltipButton.innerHTML = this._options.prevLabel; - - //skip button - var skipTooltipButton = document.createElement('a'); - skipTooltipButton.className = 'introjs-button introjs-skipbutton'; - _setAnchorAsButton(skipTooltipButton); - skipTooltipButton.innerHTML = this._options.skipLabel; - - skipTooltipButton.onclick = function() { - if (self._introItems.length - 1 == self._currentStep && typeof (self._introCompleteCallback) === 'function') { - self._introCompleteCallback.call(self); - } - - _exitIntro.call(self, self._targetElement); - }; - - buttonsLayer.appendChild(skipTooltipButton); - - //in order to prevent displaying next/previous button always - if (this._introItems.length > 1) { - buttonsLayer.appendChild(prevTooltipButton); - buttonsLayer.appendChild(nextTooltipButton); - } - - tooltipLayer.appendChild(buttonsLayer); - - //set proper position - _placeTooltip.call(self, targetElement.element, tooltipLayer, arrowLayer, helperNumberLayer); - - // change the scroll of the window, if needed - _scrollTo.call(this, targetElement.scrollTo, targetElement, tooltipLayer); - - //end of new element if-else condition - } - - // removing previous disable interaction layer - var disableInteractionLayer = self._targetElement.querySelector('.introjs-disableInteraction'); - if (disableInteractionLayer) { - disableInteractionLayer.parentNode.removeChild(disableInteractionLayer); - } - - //disable interaction - if (targetElement.disableInteraction) { - _disableInteraction.call(self); - } - - if (typeof nextTooltipButton !== "undefined" && nextTooltipButton != null) { - nextTooltipButton.removeAttribute('tabIndex'); - } - if (typeof prevTooltipButton !== "undefined" && prevTooltipButton != null) { - prevTooltipButton.removeAttribute('tabIndex'); - } - - // when it's the first step of tour - if (this._currentStep == 0 && this._introItems.length > 1) { - if (typeof skipTooltipButton !== "undefined" && skipTooltipButton != null) { - skipTooltipButton.className = 'introjs-button introjs-skipbutton'; - } - if (typeof nextTooltipButton !== "undefined" && nextTooltipButton != null) { - nextTooltipButton.className = 'introjs-button introjs-nextbutton'; - } - - if (this._options.hidePrev == true) { - if (typeof prevTooltipButton !== "undefined" && prevTooltipButton != null) { - prevTooltipButton.className = 'introjs-button introjs-prevbutton introjs-hidden'; - } - if (typeof nextTooltipButton !== "undefined" && nextTooltipButton != null) { - nextTooltipButton.className += ' introjs-fullbutton'; - } - } else { - if (typeof prevTooltipButton !== "undefined" && prevTooltipButton != null) { - prevTooltipButton.className = 'introjs-button introjs-prevbutton introjs-disabled'; - } - } - - if (typeof prevTooltipButton !== "undefined" && prevTooltipButton != null) { - prevTooltipButton.tabIndex = '-1'; - } - if (typeof skipTooltipButton !== "undefined" && skipTooltipButton != null) { - skipTooltipButton.innerHTML = this._options.skipLabel; - } - } else if (this._introItems.length - 1 == this._currentStep || this._introItems.length == 1) { - // last step of tour - if (typeof skipTooltipButton !== "undefined" && skipTooltipButton != null) { - skipTooltipButton.innerHTML = this._options.doneLabel; - // adding donebutton class in addition to skipbutton - skipTooltipButton.className += ' introjs-donebutton'; - } - if (typeof prevTooltipButton !== "undefined" && prevTooltipButton != null) { - prevTooltipButton.className = 'introjs-button introjs-prevbutton'; - } - - if (this._options.hideNext == true) { - if (typeof nextTooltipButton !== "undefined" && nextTooltipButton != null) { - nextTooltipButton.className = 'introjs-button introjs-nextbutton introjs-hidden'; - } - if (typeof prevTooltipButton !== "undefined" && prevTooltipButton != null) { - prevTooltipButton.className += ' introjs-fullbutton'; - } - } else { - if (typeof nextTooltipButton !== "undefined" && nextTooltipButton != null) { - nextTooltipButton.className = 'introjs-button introjs-nextbutton introjs-disabled'; - } - } - - if (typeof nextTooltipButton !== "undefined" && nextTooltipButton != null) { - nextTooltipButton.tabIndex = '-1'; - } - } else { - // steps between start and end - if (typeof skipTooltipButton !== "undefined" && skipTooltipButton != null) { - skipTooltipButton.className = 'introjs-button introjs-skipbutton'; - } - if (typeof prevTooltipButton !== "undefined" && prevTooltipButton != null) { - prevTooltipButton.className = 'introjs-button introjs-prevbutton'; - } - if (typeof nextTooltipButton !== "undefined" && nextTooltipButton != null) { - nextTooltipButton.className = 'introjs-button introjs-nextbutton'; - } - if (typeof skipTooltipButton !== "undefined" && skipTooltipButton != null) { - skipTooltipButton.innerHTML = this._options.skipLabel; - } - } - - //Set focus on "next" button, so that hitting Enter always moves you onto the next step - if (typeof nextTooltipButton !== "undefined" && nextTooltipButton != null) { - nextTooltipButton.focus(); - } - - _setShowElement(targetElement); - - if (typeof (this._introAfterChangeCallback) !== 'undefined') { - this._introAfterChangeCallback.call(this, targetElement.element); - } - } - - /** - * To change the scroll of `window` after highlighting an element - * - * @api private - * @method _scrollTo - * @param {String} scrollTo - * @param {Object} targetElement - * @param {Object} tooltipLayer - */ - function _scrollTo(scrollTo, targetElement, tooltipLayer) { - if (!this._options.scrollToElement) return; - - if (scrollTo === 'tooltip') { - var rect = tooltipLayer.getBoundingClientRect(); - } else { - var rect = targetElement.element.getBoundingClientRect(); - } - - if (!_elementInViewport(targetElement.element)) { - var winHeight = _getWinSize().height; - var top = rect.bottom - (rect.bottom - rect.top); - var bottom = rect.bottom - winHeight; - - // TODO (afshinm): do we need scroll padding now? - // I have changed the scroll option and now it scrolls the window to - // the center of the target element or tooltip. - - if (top < 0 || targetElement.element.clientHeight > winHeight) { - window.scrollBy(0, rect.top - ((winHeight / 2) - (rect.height / 2)) - this._options.scrollPadding); // 30px padding from edge to look nice - - //Scroll down - } else { - window.scrollBy(0, rect.top - ((winHeight / 2) - (rect.height / 2)) + this._options.scrollPadding); // 30px padding from edge to look nice - } - } - } - - /** - * To remove all show element(s) - * - * @api private - * @method _removeShowElement - */ - function _removeShowElement() { - var elms = document.querySelectorAll('.introjs-showElement'); - - for (var i = 0, l = elms.length; i < l; i++) { - var elm = elms[i]; - _removeClass(elm, /introjs-[a-zA-Z]+/g); - } - } - - /** - * To set the show element - * This function set a relative (in most cases) position and changes the z-index - * - * @api private - * @method _setShowElement - * @param {Object} targetElement - */ - function _setShowElement(targetElement) { - // we need to add this show element class to the parent of SVG elements - // because the SVG elements can't have independent z-index - if (targetElement.element instanceof SVGElement) { - var parentElm = targetElement.element.parentNode; - - while (targetElement.element.parentNode != null) { - if (!parentElm.tagName || parentElm.tagName.toLowerCase() === 'body') break; - - if (parentElm.tagName.toLowerCase() === 'svg') { - _setClass(parentElm, 'introjs-showElement introjs-relativePosition'); - } - - parentElm = parentElm.parentNode; - } - } - - _setClass(targetElement.element, 'introjs-showElement'); - - var currentElementPosition = _getPropValue(targetElement.element, 'position'); - if (currentElementPosition !== 'absolute' && - currentElementPosition !== 'relative' && - currentElementPosition !== 'fixed') { - //change to new intro item - //targetElement.element.className += ' introjs-relativePosition'; - _setClass(targetElement.element, 'introjs-relativePosition') - } - - var parentElm = targetElement.element.parentNode; - while (parentElm != null) { - if (!parentElm.tagName || parentElm.tagName.toLowerCase() === 'body') break; - - //fix The Stacking Context problem. - //More detail: https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context - var zIndex = _getPropValue(parentElm, 'z-index'); - var opacity = parseFloat(_getPropValue(parentElm, 'opacity')); - var transform = _getPropValue(parentElm, 'transform') || _getPropValue(parentElm, '-webkit-transform') || _getPropValue(parentElm, '-moz-transform') || _getPropValue(parentElm, '-ms-transform') || _getPropValue(parentElm, '-o-transform'); - if (/[0-9]+/.test(zIndex) || opacity < 1 || (transform !== 'none' && transform !== undefined)) { - parentElm.className += ' introjs-fixParent'; - } - - parentElm = parentElm.parentNode; - } - } - - function _setClass(element, className) { - if (element instanceof SVGElement) { - var pre = element.getAttribute('class') || ''; - - element.setAttribute('class', pre + ' ' + className); - } else { - element.className += ' ' + className; - } - } - - function _removeClass(element, classNameRegex) { - if (element instanceof SVGElement) { - var pre = element.getAttribute('class') || ''; - - element.setAttribute('class', pre.replace(classNameRegex, '').replace(/^\s+|\s+$/g, '')); - } else { - element.className = element.className.replace(classNameRegex, '').replace(/^\s+|\s+$/g, ''); - } - } - - /** - * Get an element CSS property on the page - * Thanks to JavaScript Kit: http://www.javascriptkit.com/dhtmltutors/dhtmlcascade4.shtml - * - * @api private - * @method _getPropValue - * @param {Object} element - * @param {String} propName - * @returns Element's property value - */ - function _getPropValue (element, propName) { - var propValue = ''; - if (element.currentStyle) { //IE - propValue = element.currentStyle[propName]; - } else if (document.defaultView && document.defaultView.getComputedStyle) { //Others - propValue = document.defaultView.getComputedStyle(element, null).getPropertyValue(propName); - } - - //Prevent exception in IE - if (propValue && propValue.toLowerCase) { - return propValue.toLowerCase(); - } else { - return propValue; - } - } - - /** - * Checks to see if target element (or parents) position is fixed or not - * - * @api private - * @method _isFixed - * @param {Object} element - * @returns Boolean - */ - function _isFixed (element) { - var p = element.parentNode; - - if (!p || p.nodeName === 'HTML') { - return false; - } - - if (_getPropValue(element, 'position') == 'fixed') { - return true; - } - - return _isFixed(p); - } - - /** - * Provides a cross-browser way to get the screen dimensions - * via: http://stackoverflow.com/questions/5864467/internet-explorer-innerheight - * - * @api private - * @method _getWinSize - * @returns {Object} width and height attributes - */ - function _getWinSize() { - if (window.innerWidth != undefined) { - return { width: window.innerWidth, height: window.innerHeight }; - } else { - var D = document.documentElement; - return { width: D.clientWidth, height: D.clientHeight }; - } - } - - /** - * Check to see if the element is in the viewport or not - * http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport - * - * @api private - * @method _elementInViewport - * @param {Object} el - */ - function _elementInViewport(el) { - var rect = el.getBoundingClientRect(); - - return ( - rect.top >= 0 && - rect.left >= 0 && - (rect.bottom+80) <= window.innerHeight && // add 80 to get the text right - rect.right <= window.innerWidth - ); - } - - /** - * Add overlay layer to the page - * - * @api private - * @method _addOverlayLayer - * @param {Object} targetElm - */ - function _addOverlayLayer(targetElm) { - var overlayLayer = document.createElement('div'), - styleText = '', - self = this; - - //set css class name - overlayLayer.className = 'introjs-overlay'; - - //check if the target element is body, we should calculate the size of overlay layer in a better way - if (!targetElm.tagName || targetElm.tagName.toLowerCase() === 'body') { - styleText += 'top: 0;bottom: 0; left: 0;right: 0;position: fixed;'; - overlayLayer.setAttribute('style', styleText); - } else { - //set overlay layer position - var elementPosition = _getOffset(targetElm); - if (elementPosition) { - styleText += 'width: ' + elementPosition.width + 'px; height:' + elementPosition.height + 'px; top:' + elementPosition.top + 'px;left: ' + elementPosition.left + 'px;'; - overlayLayer.setAttribute('style', styleText); - } - } - - targetElm.appendChild(overlayLayer); - - overlayLayer.onclick = function() { - if (self._options.exitOnOverlayClick == true) { - _exitIntro.call(self, targetElm); - } - }; - - setTimeout(function() { - styleText += 'opacity: ' + self._options.overlayOpacity.toString() + ';'; - overlayLayer.setAttribute('style', styleText); - }, 10); - - return true; - } - - /** - * Removes open hint (tooltip hint) - * - * @api private - * @method _removeHintTooltip - */ - function _removeHintTooltip() { - var tooltip = this._targetElement.querySelector('.introjs-hintReference'); - - if (tooltip) { - var step = tooltip.getAttribute('data-step'); - tooltip.parentNode.removeChild(tooltip); - return step; - } - } - - /** - * Start parsing hint items - * - * @api private - * @param {Object} targetElm - * @method _startHint - */ - function _populateHints(targetElm) { - var self = this; - this._introItems = []; - - if (this._options.hints) { - for (var i = 0, l = this._options.hints.length; i < l; i++) { - var currentItem = _cloneObject(this._options.hints[i]); - - if (typeof(currentItem.element) === 'string') { - //grab the element with given selector from the page - currentItem.element = document.querySelector(currentItem.element); - } - - currentItem.hintPosition = currentItem.hintPosition || this._options.hintPosition; - currentItem.hintAnimation = currentItem.hintAnimation || this._options.hintAnimation; - - if (currentItem.element != null) { - this._introItems.push(currentItem); - } - } - } else { - var hints = targetElm.querySelectorAll('*[data-hint]'); - - if (hints.length < 1) { - return false; - } - - //first add intro items with data-step - for (var i = 0, l = hints.length; i < l; i++) { - var currentElement = hints[i]; - - // hint animation - var hintAnimation = currentElement.getAttribute('data-hintAnimation'); - - if (hintAnimation) { - hintAnimation = (hintAnimation == 'true'); - } else { - hintAnimation = this._options.hintAnimation; - } - - this._introItems.push({ - element: currentElement, - hint: currentElement.getAttribute('data-hint'), - hintPosition: currentElement.getAttribute('data-hintPosition') || this._options.hintPosition, - hintAnimation: hintAnimation, - tooltipClass: currentElement.getAttribute('data-tooltipClass'), - position: currentElement.getAttribute('data-position') || this._options.tooltipPosition - }); - } - } - - _addHints.call(this); - - if (document.addEventListener) { - document.addEventListener('click', _removeHintTooltip.bind(this), false); - //for window resize - window.addEventListener('resize', _reAlignHints.bind(this), true); - } else if (document.attachEvent) { //IE - //for window resize - document.attachEvent('onclick', _removeHintTooltip.bind(this)); - document.attachEvent('onresize', _reAlignHints.bind(this)); - } - } - - /** - * Re-aligns all hint elements - * - * @api private - * @method _reAlignHints - */ - function _reAlignHints() { - for (var i = 0, l = this._introItems.length; i < l; i++) { - var item = this._introItems[i]; - - if (typeof (item.targetElement) == 'undefined') continue; - - _alignHintPosition.call(this, item.hintPosition, item.element, item.targetElement) - } - } - - /** - * Hide a hint - * - * @api private - * @method _hideHint - */ - function _hideHint(stepId) { - _removeHintTooltip.call(this); - var hint = this._targetElement.querySelector('.introjs-hint[data-step="' + stepId + '"]'); - - if (hint) { - hint.className += ' introjs-hidehint'; - } - - // call the callback function (if any) - if (typeof (this._hintCloseCallback) !== 'undefined') { - this._hintCloseCallback.call(this, stepId); - } - } - - /** - * Hide all hints - * - * @api private - * @method _hideHints - */ - function _hideHints() { - var hints = this._targetElement.querySelectorAll('.introjs-hint'); - - if (hints && hints.length > 0) { - for (var i = 0; i < hints.length; i++) { - _hideHint.call(this, hints[i].getAttribute('data-step')); - } - } - } - - /** - * Show all hints - * - * @api private - * @method _showHints - */ - function _showHints() { - var hints = this._targetElement.querySelectorAll('.introjs-hint'); - - if (hints && hints.length > 0) { - for (var i = 0; i < hints.length; i++) { - _showHint.call(this, hints[i].getAttribute('data-step')); - } - } else { - _populateHints.call(this, this._targetElement); - } - }; - - /** - * Show a hint - * - * @api private - * @method _showHint - */ - function _showHint(stepId) { - var hint = this._targetElement.querySelector('.introjs-hint[data-step="' + stepId + '"]'); - - if (hint) { - hint.className = hint.className.replace(/introjs\-hidehint/g, ''); - } - }; - - /** - * Removes all hint elements on the page - * Useful when you want to destroy the elements and add them again (e.g. a modal or popup) - * - * @api private - * @method _removeHints - */ - function _removeHints() { - var hints = this._targetElement.querySelectorAll('.introjs-hint'); - - if (hints && hints.length > 0) { - for (var i = 0; i < hints.length; i++) { - _removeHint.call(this, hints[i].getAttribute('data-step')); - } - } - }; - - /** - * Remove one single hint element from the page - * Useful when you want to destroy the element and add them again (e.g. a modal or popup) - * Use removeHints if you want to remove all elements. - * - * @api private - * @method _removeHint - */ - function _removeHint(stepId) { - var hint = this._targetElement.querySelector('.introjs-hint[data-step="' + stepId + '"]'); - - if (hint) { - hint.parentNode.removeChild(hint); - } - }; - - /** - * Add all available hints to the page - * - * @api private - * @method _addHints - */ - function _addHints() { - var self = this; - - var oldHintsWrapper = document.querySelector('.introjs-hints'); - - if (oldHintsWrapper != null) { - hintsWrapper = oldHintsWrapper; - } else { - var hintsWrapper = document.createElement('div'); - hintsWrapper.className = 'introjs-hints'; - } - - for (var i = 0, l = this._introItems.length; i < l; i++) { - var item = this._introItems[i]; - - // avoid append a hint twice - if (document.querySelector('.introjs-hint[data-step="' + i + '"]')) - continue; - - var hint = document.createElement('a'); - _setAnchorAsButton(hint); - - (function (hint, item, i) { - // when user clicks on the hint element - hint.onclick = function(e) { - var evt = e ? e : window.event; - if (evt.stopPropagation) evt.stopPropagation(); - if (evt.cancelBubble != null) evt.cancelBubble = true; - - _showHintDialog.call(self, i); - }; - }(hint, item, i)); - - hint.className = 'introjs-hint'; - - if (!item.hintAnimation) { - hint.className += ' introjs-hint-no-anim'; - } - - // hint's position should be fixed if the target element's position is fixed - if (_isFixed(item.element)) { - hint.className += ' introjs-fixedhint'; - } - - var hintDot = document.createElement('div'); - hintDot.className = 'introjs-hint-dot'; - var hintPulse = document.createElement('div'); - hintPulse.className = 'introjs-hint-pulse'; - - hint.appendChild(hintDot); - hint.appendChild(hintPulse); - hint.setAttribute('data-step', i); - - // we swap the hint element with target element - // because _setHelperLayerPosition uses `element` property - item.targetElement = item.element; - item.element = hint; - - // align the hint position - _alignHintPosition.call(this, item.hintPosition, hint, item.targetElement); - - hintsWrapper.appendChild(hint); - } - - // adding the hints wrapper - document.body.appendChild(hintsWrapper); - - // call the callback function (if any) - if (typeof (this._hintsAddedCallback) !== 'undefined') { - this._hintsAddedCallback.call(this); - } - } - - /** - * Aligns hint position - * - * @api private - * @method _alignHintPosition - * @param {String} position - * @param {Object} hint - * @param {Object} element - */ - function _alignHintPosition(position, hint, element) { - // get/calculate offset of target element - var offset = _getOffset.call(this, element); - var iconWidth = 20; - var iconHeight = 20; - - // align the hint element - switch (position) { - default: - case 'top-left': - hint.style.left = offset.left + 'px'; - hint.style.top = offset.top + 'px'; - break; - case 'top-right': - hint.style.left = (offset.left + offset.width - iconWidth) + 'px'; - hint.style.top = offset.top + 'px'; - break; - case 'bottom-left': - hint.style.left = offset.left + 'px'; - hint.style.top = (offset.top + offset.height - iconHeight) + 'px'; - break; - case 'bottom-right': - hint.style.left = (offset.left + offset.width - iconWidth) + 'px'; - hint.style.top = (offset.top + offset.height - iconHeight) + 'px'; - break; - case 'middle-left': - hint.style.left = offset.left + 'px'; - hint.style.top = (offset.top + (offset.height - iconHeight) / 2) + 'px'; - break; - case 'middle-right': - hint.style.left = (offset.left + offset.width - iconWidth) + 'px'; - hint.style.top = (offset.top + (offset.height - iconHeight) / 2) + 'px'; - break; - case 'middle-middle': - hint.style.left = (offset.left + (offset.width - iconWidth) / 2) + 'px'; - hint.style.top = (offset.top + (offset.height - iconHeight) / 2) + 'px'; - break; - case 'bottom-middle': - hint.style.left = (offset.left + (offset.width - iconWidth) / 2) + 'px'; - hint.style.top = (offset.top + offset.height - iconHeight) + 'px'; - break; - case 'top-middle': - hint.style.left = (offset.left + (offset.width - iconWidth) / 2) + 'px'; - hint.style.top = offset.top + 'px'; - break; - } - } - - /** - * Triggers when user clicks on the hint element - * - * @api private - * @method _showHintDialog - * @param {Number} stepId - */ - function _showHintDialog(stepId) { - var hintElement = document.querySelector('.introjs-hint[data-step="' + stepId + '"]'); - var item = this._introItems[stepId]; - - // call the callback function (if any) - if (typeof (this._hintClickCallback) !== 'undefined') { - this._hintClickCallback.call(this, hintElement, item, stepId); - } - - // remove all open tooltips - var removedStep = _removeHintTooltip.call(this); - - // to toggle the tooltip - if (parseInt(removedStep, 10) == stepId) { - return; - } - - var tooltipLayer = document.createElement('div'); - var tooltipTextLayer = document.createElement('div'); - var arrowLayer = document.createElement('div'); - var referenceLayer = document.createElement('div'); - - tooltipLayer.className = 'introjs-tooltip'; - - tooltipLayer.onclick = function (e) { - //IE9 & Other Browsers - if (e.stopPropagation) { - e.stopPropagation(); - } - //IE8 and Lower - else { - e.cancelBubble = true; - } - }; - - tooltipTextLayer.className = 'introjs-tooltiptext'; - - var tooltipWrapper = document.createElement('p'); - tooltipWrapper.innerHTML = item.hint; - - var closeButton = document.createElement('a'); - closeButton.className = 'introjs-button'; - closeButton.innerHTML = this._options.hintButtonLabel; - closeButton.onclick = _hideHint.bind(this, stepId); - - tooltipTextLayer.appendChild(tooltipWrapper); - tooltipTextLayer.appendChild(closeButton); - - arrowLayer.className = 'introjs-arrow'; - tooltipLayer.appendChild(arrowLayer); - - tooltipLayer.appendChild(tooltipTextLayer); - - // set current step for _placeTooltip function - this._currentStep = hintElement.getAttribute('data-step'); - - // align reference layer position - referenceLayer.className = 'introjs-tooltipReferenceLayer introjs-hintReference'; - referenceLayer.setAttribute('data-step', hintElement.getAttribute('data-step')); - _setHelperLayerPosition.call(this, referenceLayer); - - referenceLayer.appendChild(tooltipLayer); - document.body.appendChild(referenceLayer); - - //set proper position - _placeTooltip.call(this, hintElement, tooltipLayer, arrowLayer, null, true); - } - - /** - * Get an element position on the page - * Thanks to `meouw`: http://stackoverflow.com/a/442474/375966 - * - * @api private - * @method _getOffset - * @param {Object} element - * @returns Element's position info - */ - function _getOffset(element) { - var elementPosition = {}; - - var body = document.body; - var docEl = document.documentElement; - - var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop; - var scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft; - - if (element instanceof SVGElement) { - var x = element.getBoundingClientRect() - elementPosition.top = x.top + scrollTop; - elementPosition.width = x.width; - elementPosition.height = x.height; - elementPosition.left = x.left + scrollLeft; - } else { - //set width - elementPosition.width = element.offsetWidth; - - //set height - elementPosition.height = element.offsetHeight; - - //calculate element top and left - var _x = 0; - var _y = 0; - while (element && !isNaN(element.offsetLeft) && !isNaN(element.offsetTop)) { - _x += element.offsetLeft; - _y += element.offsetTop; - element = element.offsetParent; - } - //set top - elementPosition.top = _y; - //set left - elementPosition.left = _x; - } - - return elementPosition; - } - - /** - * Gets the current progress percentage - * - * @api private - * @method _getProgress - * @returns current progress percentage - */ - function _getProgress() { - // Steps are 0 indexed - var currentStep = parseInt((this._currentStep + 1), 10); - return ((currentStep / this._introItems.length) * 100); - } - - /** - * Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1 - * via: http://stackoverflow.com/questions/171251/how-can-i-merge-properties-of-two-javascript-objects-dynamically - * - * @param obj1 - * @param obj2 - * @returns obj3 a new object based on obj1 and obj2 - */ - function _mergeOptions(obj1,obj2) { - var obj3 = {}; - for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; } - for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; } - return obj3; - } - - var introJs = function (targetElm) { - if (typeof (targetElm) === 'object') { - //Ok, create a new instance - return new IntroJs(targetElm); - - } else if (typeof (targetElm) === 'string') { - //select the target element with query selector - var targetElement = document.querySelector(targetElm); - - if (targetElement) { - return new IntroJs(targetElement); - } else { - throw new Error('There is no element with given selector.'); - } - } else { - return new IntroJs(document.body); - } - }; - - /** - * Current IntroJs version - * - * @property version - * @type String - */ - introJs.version = VERSION; - - //Prototype - introJs.fn = IntroJs.prototype = { - clone: function () { - return new IntroJs(this); - }, - setOption: function(option, value) { - this._options[option] = value; - return this; - }, - setOptions: function(options) { - this._options = _mergeOptions(this._options, options); - return this; - }, - start: function () { - _introForElement.call(this, this._targetElement); - return this; - }, - goToStep: function(step) { - _goToStep.call(this, step); - return this; - }, - addStep: function(options) { - if (!this._options.steps) { - this._options.steps = []; - } - - this._options.steps.push(options); - - return this; - }, - addSteps: function(steps) { - if (!steps.length) return; - - for(var index = 0; index < steps.length; index++) { - this.addStep(steps[index]); - } - - return this; - }, - goToStepNumber: function(step) { - _goToStepNumber.call(this, step); - - return this; - }, - nextStep: function() { - _nextStep.call(this); - return this; - }, - previousStep: function() { - _previousStep.call(this); - return this; - }, - exit: function(force) { - _exitIntro.call(this, this._targetElement, force); - return this; - }, - refresh: function() { - _refresh.call(this); - return this; - }, - onbeforechange: function(providedCallback) { - if (typeof (providedCallback) === 'function') { - this._introBeforeChangeCallback = providedCallback; - } else { - throw new Error('Provided callback for onbeforechange was not a function'); - } - return this; - }, - onchange: function(providedCallback) { - if (typeof (providedCallback) === 'function') { - this._introChangeCallback = providedCallback; - } else { - throw new Error('Provided callback for onchange was not a function.'); - } - return this; - }, - onafterchange: function(providedCallback) { - if (typeof (providedCallback) === 'function') { - this._introAfterChangeCallback = providedCallback; - } else { - throw new Error('Provided callback for onafterchange was not a function'); - } - return this; - }, - oncomplete: function(providedCallback) { - if (typeof (providedCallback) === 'function') { - this._introCompleteCallback = providedCallback; - } else { - throw new Error('Provided callback for oncomplete was not a function.'); - } - return this; - }, - onhintsadded: function(providedCallback) { - if (typeof (providedCallback) === 'function') { - this._hintsAddedCallback = providedCallback; - } else { - throw new Error('Provided callback for onhintsadded was not a function.'); - } - return this; - }, - onhintclick: function(providedCallback) { - if (typeof (providedCallback) === 'function') { - this._hintClickCallback = providedCallback; - } else { - throw new Error('Provided callback for onhintclick was not a function.'); - } - return this; - }, - onhintclose: function(providedCallback) { - if (typeof (providedCallback) === 'function') { - this._hintCloseCallback = providedCallback; - } else { - throw new Error('Provided callback for onhintclose was not a function.'); - } - return this; - }, - onexit: function(providedCallback) { - if (typeof (providedCallback) === 'function') { - this._introExitCallback = providedCallback; - } else { - throw new Error('Provided callback for onexit was not a function.'); - } - return this; - }, - onbeforeexit: function(providedCallback) { - if (typeof (providedCallback) === 'function') { - this._introBeforeExitCallback = providedCallback; - } else { - throw new Error('Provided callback for onbeforeexit was not a function.'); - } - return this; - }, - addHints: function() { - _populateHints.call(this, this._targetElement); - return this; - }, - hideHint: function (stepId) { - _hideHint.call(this, stepId); - return this; - }, - hideHints: function () { - _hideHints.call(this); - return this; - }, - showHint: function (stepId) { - _showHint.call(this, stepId); - return this; - }, - showHints: function () { - _showHints.call(this); - return this; - }, - removeHints: function () { - _removeHints.call(this); - return this; - }, - removeHint: function (stepId) { - _removeHint.call(this, stepId); - return this; - }, - showHintDialog: function (stepId) { - _showHintDialog.call(this, stepId); - return this; - } - }; - - exports.introJs = introJs; - return introJs; -})); +(function(C,n){"object"===typeof exports?n(exports):"function"===typeof define&&define.amd?define(["exports"],n):n(C)})(this,function(C){function n(a){this._targetElement=a;this._introItems=[];this._options={nextLabel:"Next \x26rarr;",prevLabel:"\x26larr; Back",skipLabel:"Skip",doneLabel:"Done",hidePrev:!1,hideNext:!1,tooltipPosition:"bottom",tooltipClass:"",highlightClass:"",exitOnEsc:!0,exitOnOverlayClick:!0,showStepNumbers:!0,keyboardNavigation:!0,showButtons:!0,showBullets:!0,showProgress:!1, +scrollToElement:!0,scrollTo:"element",scrollPadding:30,overlayOpacity:.8,positionPrecedence:["bottom","top","right","left"],disableInteraction:!1,hintPosition:"top-middle",hintButtonLabel:"Got it",hintAnimation:!0}}function Z(a){var b,c=[],d=this;if(this._options.steps){var f=0;for(b=this._options.steps.length;fg.length)return!1;for(var f=0,r=g.length;fr.height?(c.className= +"introjs-arrow left-bottom",b.style.top="-"+(a.height-e.height-20)+"px"):c.className="introjs-arrow left";break;case "left":f||1!=this._options.showStepNumbers||(b.style.top="15px");e.top+a.height>r.height?(b.style.top="-"+(a.height-e.height-20)+"px",c.className="introjs-arrow right-bottom"):c.className="introjs-arrow right";b.style.right=e.width+20+"px";break;case "floating":c.style.display="none";b.style.left="50%";b.style.top="50%";b.style.marginLeft="-"+a.width/2+"px";b.style.marginTop="-"+a.height/ +2+"px";"undefined"!=typeof d&&null!=d&&(d.style.left="-"+(a.width/2+18)+"px",d.style.top="-"+(a.height/2+18)+"px");break;case "bottom-right-aligned":c.className="introjs-arrow top-right";R(e,0,a,b);b.style.top=e.height+20+"px";break;case "bottom-middle-aligned":c.className="introjs-arrow top-middle";c=e.width/2-a.width/2;f&&(c+=5);R(e,c,a,b)&&(b.style.right=null,I(e,c,a,r,b));b.style.top=e.height+20+"px";break;default:c.className="introjs-arrow top",I(e,0,a,r,b),b.style.top=e.height+20+"px"}}}function I(a, +b,c,d,f){if(a.left+b+c.width>d.width)return f.style.left=d.width-c.width-a.left+"px",!1;f.style.left=b+"px";return!0}function R(a,b,c,d){if(0>a.left+a.width-b-c.width)return d.style.left=-a.left+"px",!1;d.style.right=b+"px";return!0}function Q(a,b,c){var d=this._options.positionPrecedence.slice(),f=H(),e=u(b).height+10;b=u(b).width+20;a=u(a);var g="floating";a.left+b>f.width||0>a.left+a.width/2-b?(t(d,"bottom"),t(d,"top")):(a.height+a.top+e>f.height&&t(d,"bottom"),0>a.top-e&&t(d,"top"));a.width+a.left+ +b>f.width&&t(d,"right");0>a.left-b&&t(d,"left");0a.bottom-(a.bottom-a.top)||b.element.clientHeight>c?window.scrollBy(0,a.top-(c/2-a.height/2)-this._options.scrollPadding):window.scrollBy(0,a.top-(c/2-a.height/2)+this._options.scrollPadding)))}function P(){for(var a=document.querySelectorAll(".introjs-showElement"),b=0,c=a.length;bc||"none"!==d&&void 0!==d)b.className+=" introjs-fixParent";b=b.parentNode}}function K(a,b){if(a instanceof SVGElement){var c=a.getAttribute("class")||"";a.setAttribute("class",c+" "+b)}else a.className+=" "+b}function m(a,b){var c="";a.currentStyle?c=a.currentStyle[b]:document.defaultView&& +document.defaultView.getComputedStyle&&(c=document.defaultView.getComputedStyle(a,null).getPropertyValue(b));return c&&c.toLowerCase?c.toLowerCase():c}function J(a){var b=a.parentNode;return b&&"HTML"!==b.nodeName?"fixed"==m(a,"position")?!0:J(b):!1}function H(){if(void 0!=window.innerWidth)return{width:window.innerWidth,height:window.innerHeight};var a=document.documentElement;return{width:a.clientWidth,height:a.clientHeight}}function aa(a){var b=document.createElement("div"),c="",d=this;b.className= +"introjs-overlay";if(a.tagName&&"body"!==a.tagName.toLowerCase()){var f=u(a);f&&(c+="width: "+f.width+"px; height:"+f.height+"px; top:"+f.top+"px;left: "+f.left+"px;",b.setAttribute("style",c))}else c+="top: 0;bottom: 0; left: 0;right: 0;position: fixed;",b.setAttribute("style",c);a.appendChild(b);b.onclick=function(){1==d._options.exitOnOverlayClick&&z.call(d,a)};setTimeout(function(){c+="opacity: "+d._options.overlayOpacity.toString()+";";b.setAttribute("style",c)},10);return!0}function v(){var a= +this._targetElement.querySelector(".introjs-hintReference");if(a){var b=a.getAttribute("data-step");a.parentNode.removeChild(a);return b}}function U(a){this._introItems=[];if(this._options.hints){a=0;for(var b=this._options.hints.length;ac.length)return!1;a=0;for(b=c.length;a td, -tr.introjs-showElement > th { - z-index: 9999999 !important; -} - -.introjs-disableInteraction { - z-index: 99999999 !important; - position: absolute; - background-color: white; - opacity: 0; - filter: alpha(opacity=0); -} - -.introjs-relativePosition, -tr.introjs-showElement > td, -tr.introjs-showElement > th { - position: relative; -} - -.introjs-helperLayer { - box-sizing: content-box; - position: absolute; - z-index: 9999998; - background-color: #FFF; - background-color: rgba(255,255,255,.9); - border: 1px solid #777; - border: 1px solid rgba(0,0,0,.5); - border-radius: 4px; - box-shadow: 0 2px 15px rgba(0,0,0,.4); - -webkit-transition: all 0.3s ease-out; - -moz-transition: all 0.3s ease-out; - -ms-transition: all 0.3s ease-out; - -o-transition: all 0.3s ease-out; - transition: all 0.3s ease-out; -} - -.introjs-tooltipReferenceLayer { - box-sizing: content-box; - position: absolute; - visibility: hidden; - z-index: 10000000; - background-color: transparent; - -webkit-transition: all 0.3s ease-out; - -moz-transition: all 0.3s ease-out; - -ms-transition: all 0.3s ease-out; - -o-transition: all 0.3s ease-out; - transition: all 0.3s ease-out; -} - -.introjs-helperLayer *, -.introjs-helperLayer *:before, -.introjs-helperLayer *:after { - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - -ms-box-sizing: content-box; - -o-box-sizing: content-box; - box-sizing: content-box; -} - -.introjs-helperNumberLayer { - box-sizing: content-box; - position: absolute; - visibility: visible; - top: -16px; - left: -16px; - z-index: 9999999999 !important; - padding: 2px; - font-family: Arial, verdana, tahoma; - font-size: 13px; - font-weight: bold; - color: white; - text-align: center; - text-shadow: 1px 1px 1px rgba(0,0,0,.3); - background: #ff3019; /* Old browsers */ - background: -webkit-linear-gradient(top, #ff3019 0%, #cf0404 100%); /* Chrome10+,Safari5.1+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ff3019), color-stop(100%, #cf0404)); /* Chrome,Safari4+ */ - background: -moz-linear-gradient(top, #ff3019 0%, #cf0404 100%); /* FF3.6+ */ - background: -ms-linear-gradient(top, #ff3019 0%, #cf0404 100%); /* IE10+ */ - background: -o-linear-gradient(top, #ff3019 0%, #cf0404 100%); /* Opera 11.10+ */ - background: linear-gradient(to bottom, #ff3019 0%, #cf0404 100%); /* W3C */ - width: 20px; - height:20px; - line-height: 20px; - border: 3px solid white; - border-radius: 50%; - filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3019', endColorstr='#cf0404', GradientType=0)"; /* IE6-9 */ - filter: "progid:DXImageTransform.Microsoft.Shadow(direction=135, strength=2, color=ff0000)"; /* IE10 text shadows */ - box-shadow: 0 2px 5px rgba(0,0,0,.4); -} - -.introjs-arrow { - border: 5px solid white; - content:''; - position: absolute; -} -.introjs-arrow.top { - top: -10px; - border-top-color:transparent; - border-right-color:transparent; - border-bottom-color:white; - border-left-color:transparent; -} -.introjs-arrow.top-right { - top: -10px; - right: 10px; - border-top-color:transparent; - border-right-color:transparent; - border-bottom-color:white; - border-left-color:transparent; -} -.introjs-arrow.top-middle { - top: -10px; - left: 50%; - margin-left: -5px; - border-top-color:transparent; - border-right-color:transparent; - border-bottom-color:white; - border-left-color:transparent; -} -.introjs-arrow.right { - right: -10px; - top: 10px; - border-top-color:transparent; - border-right-color:transparent; - border-bottom-color:transparent; - border-left-color:white; -} -.introjs-arrow.right-bottom { - bottom:10px; - right: -10px; - border-top-color:transparent; - border-right-color:transparent; - border-bottom-color:transparent; - border-left-color:white; -} -.introjs-arrow.bottom { - bottom: -10px; - border-top-color:white; - border-right-color:transparent; - border-bottom-color:transparent; - border-left-color:transparent; -} -.introjs-arrow.left { - left: -10px; - top: 10px; - border-top-color:transparent; - border-right-color:white; - border-bottom-color:transparent; - border-left-color:transparent; -} -.introjs-arrow.left-bottom { - left: -10px; - bottom:10px; - border-top-color:transparent; - border-right-color:white; - border-bottom-color:transparent; - border-left-color:transparent; -} - -.introjs-tooltip { - box-sizing: content-box; - position: absolute; - visibility: visible; - padding: 10px; - background-color: white; - min-width: 200px; - max-width: 300px; - border-radius: 3px; - box-shadow: 0 1px 10px rgba(0,0,0,.4); - -webkit-transition: opacity 0.1s ease-out; - -moz-transition: opacity 0.1s ease-out; - -ms-transition: opacity 0.1s ease-out; - -o-transition: opacity 0.1s ease-out; - transition: opacity 0.1s ease-out; -} - -.introjs-tooltipbuttons { - text-align: right; - white-space: nowrap; -} - -/* - Buttons style by http://nicolasgallagher.com/lab/css3-github-buttons/ - Changed by Afshin Mehrabani -*/ -.introjs-button { - box-sizing: content-box; - position: relative; - overflow: visible; - display: inline-block; - padding: 0.3em 0.8em; - border: 1px solid #d4d4d4; - margin: 0; - text-decoration: none; - text-shadow: 1px 1px 0 #fff; - font: 11px/normal sans-serif; - color: #333; - white-space: nowrap; - cursor: pointer; - outline: none; - background-color: #ececec; - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f4f4f4), to(#ececec)); - background-image: -moz-linear-gradient(#f4f4f4, #ececec); - background-image: -o-linear-gradient(#f4f4f4, #ececec); - background-image: linear-gradient(#f4f4f4, #ececec); - -webkit-background-clip: padding; - -moz-background-clip: padding; - -o-background-clip: padding-box; - /*background-clip: padding-box;*/ /* commented out due to Opera 11.10 bug */ - -webkit-border-radius: 0.2em; - -moz-border-radius: 0.2em; - border-radius: 0.2em; - /* IE hacks */ - zoom: 1; - *display: inline; - margin-top: 10px; -} - -.introjs-button:hover { - border-color: #bcbcbc; - text-decoration: none; - box-shadow: 0px 1px 1px #e3e3e3; -} - -.introjs-button:focus, -.introjs-button:active { - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ececec), to(#f4f4f4)); - background-image: -moz-linear-gradient(#ececec, #f4f4f4); - background-image: -o-linear-gradient(#ececec, #f4f4f4); - background-image: linear-gradient(#ececec, #f4f4f4); -} - -/* overrides extra padding on button elements in Firefox */ -.introjs-button::-moz-focus-inner { - padding: 0; - border: 0; -} - -.introjs-skipbutton { - box-sizing: content-box; - margin-right: 5px; - color: #7a7a7a; -} - -.introjs-prevbutton { - -webkit-border-radius: 0.2em 0 0 0.2em; - -moz-border-radius: 0.2em 0 0 0.2em; - border-radius: 0.2em 0 0 0.2em; - border-right: none; -} - -.introjs-prevbutton.introjs-fullbutton { - border: 1px solid #d4d4d4; - -webkit-border-radius: 0.2em; - -moz-border-radius: 0.2em; - border-radius: 0.2em; -} - -.introjs-nextbutton { - -webkit-border-radius: 0 0.2em 0.2em 0; - -moz-border-radius: 0 0.2em 0.2em 0; - border-radius: 0 0.2em 0.2em 0; -} - -.introjs-nextbutton.introjs-fullbutton { - -webkit-border-radius: 0.2em; - -moz-border-radius: 0.2em; - border-radius: 0.2em; -} - -.introjs-disabled, .introjs-disabled:hover, .introjs-disabled:focus { - color: #9a9a9a; - border-color: #d4d4d4; - box-shadow: none; - cursor: default; - background-color: #f4f4f4; - background-image: none; - text-decoration: none; -} - -.introjs-hidden { - display: none; -} - -.introjs-bullets { - text-align: center; -} -.introjs-bullets ul { - box-sizing: content-box; - clear: both; - margin: 15px auto 0; - padding: 0; - display: inline-block; -} -.introjs-bullets ul li { - box-sizing: content-box; - list-style: none; - float: left; - margin: 0 2px; -} -.introjs-bullets ul li a { - box-sizing: content-box; - display: block; - width: 6px; - height: 6px; - background: #ccc; - border-radius: 10px; - -moz-border-radius: 10px; - -webkit-border-radius: 10px; - text-decoration: none; - cursor: pointer; -} -.introjs-bullets ul li a:hover { - background: #999; -} -.introjs-bullets ul li a.active { - background: #999; -} - -.introjs-progress { - box-sizing: content-box; - overflow: hidden; - height: 10px; - margin: 10px 0 5px 0; - border-radius: 4px; - background-color: #ecf0f1 -} -.introjs-progressbar { - box-sizing: content-box; - float: left; - width: 0%; - height: 100%; - font-size: 10px; - line-height: 10px; - text-align: center; - background-color: #08c; -} - -.introjsFloatingElement { - position: absolute; - height: 0; - width: 0; - left: 50%; - top: 50%; -} - -.introjs-fixedTooltip { - position: fixed; -} - -.introjs-hint { - box-sizing: content-box; - position: absolute; - background: transparent; - width: 20px; - height: 15px; - cursor: pointer; -} -.introjs-hint:focus { - border: 0; - outline: 0; -} -.introjs-hidehint { - display: none; -} - -.introjs-fixedhint { - position: fixed; -} - -.introjs-hint:hover > .introjs-hint-pulse { - border: 5px solid rgba(60, 60, 60, 0.57); -} - -.introjs-hint-pulse { - box-sizing: content-box; - width: 10px; - height: 10px; - border: 5px solid rgba(60, 60, 60, 0.27); - -webkit-border-radius: 30px; - -moz-border-radius: 30px; - border-radius: 30px; - background-color: rgba(136, 136, 136, 0.24); - z-index: 10; - position: absolute; - -webkit-transition: all 0.2s ease-out; - -moz-transition: all 0.2s ease-out; - -ms-transition: all 0.2s ease-out; - -o-transition: all 0.2s ease-out; - transition: all 0.2s ease-out; -} -.introjs-hint-no-anim .introjs-hint-dot { - -webkit-animation: none; - -moz-animation: none; - animation: none; -} -.introjs-hint-dot { - box-sizing: content-box; - border: 10px solid rgba(146, 146, 146, 0.36); - background: transparent; - -webkit-border-radius: 60px; - -moz-border-radius: 60px; - border-radius: 60px; - height: 50px; - width: 50px; - -webkit-animation: introjspulse 3s ease-out; - -moz-animation: introjspulse 3s ease-out; - animation: introjspulse 3s ease-out; - -webkit-animation-iteration-count: infinite; - -moz-animation-iteration-count: infinite; - animation-iteration-count: infinite; - position: absolute; - top: -25px; - left: -25px; - z-index: 1; - opacity: 0; -} - -@-webkit-keyframes introjspulse { - 0% { - -webkit-transform: scale(0); - opacity: 0.0; - } - 25% { - -webkit-transform: scale(0); - opacity: 0.1; - } - 50% { - -webkit-transform: scale(0.1); - opacity: 0.3; - } - 75% { - -webkit-transform: scale(0.5); - opacity: 0.5; - } - 100% { - -webkit-transform: scale(1); - opacity: 0.0; - } -} - -@-moz-keyframes introjspulse { - 0% { - -moz-transform: scale(0); - opacity: 0.0; - } - 25% { - -moz-transform: scale(0); - opacity: 0.1; - } - 50% { - -moz-transform: scale(0.1); - opacity: 0.3; - } - 75% { - -moz-transform: scale(0.5); - opacity: 0.5; - } - 100% { - -moz-transform: scale(1); - opacity: 0.0; - } -} - -@keyframes introjspulse { - 0% { - transform: scale(0); - opacity: 0.0; - } - 25% { - transform: scale(0); - opacity: 0.1; - } - 50% { - transform: scale(0.1); - opacity: 0.3; - } - 75% { - transform: scale(0.5); - opacity: 0.5; - } - 100% { - transform: scale(1); - opacity: 0.0; - } -} +.introjs-overlay{position:absolute;box-sizing:content-box;z-index:999999;background-color:#000;opacity:0;background:-moz-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);background:-webkit-gradient(radial,center center,0px,center center,100%,color-stop(0%,rgba(0,0,0,0.4)),color-stop(100%,rgba(0,0,0,0.9)));background:-webkit-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);background:-o-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);background:-ms-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);background:radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr='#66000000',endColorstr='#e6000000',GradientType=1)";-ms-filter:"alpha(opacity=50)";filter:alpha(opacity=50);-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-ms-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}.introjs-fixParent{z-index:auto!important;opacity:1.0!important;-webkit-transform:none!important;-moz-transform:none!important;-ms-transform:none!important;-o-transform:none!important;transform:none!important}.introjs-showElement,tr.introjs-showElement>td,tr.introjs-showElement>th{z-index:9999999!important}.introjs-disableInteraction{z-index:99999999!important;position:absolute;background-color:white;opacity:0;filter:alpha(opacity=0)}.introjs-relativePosition,tr.introjs-showElement>td,tr.introjs-showElement>th{position:relative}.introjs-helperLayer{box-sizing:content-box;position:absolute;z-index:9999998;background-color:#FFF;background-color:rgba(255,255,255,.9);border:1px solid #777;border:1px solid rgba(0,0,0,.5);border-radius:4px;box-shadow:0 2px 15px rgba(0,0,0,.4);-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-ms-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}.introjs-tooltipReferenceLayer{box-sizing:content-box;position:absolute;visibility:hidden;z-index:10000000;background-color:transparent;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-ms-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}.introjs-helperLayer *,.introjs-helperLayer *:before,.introjs-helperLayer *:after{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;-ms-box-sizing:content-box;-o-box-sizing:content-box;box-sizing:content-box}.introjs-helperNumberLayer{box-sizing:content-box;position:absolute;visibility:visible;top:-16px;left:-16px;z-index:9999999999!important;padding:2px;font-family:Arial,verdana,tahoma;font-size:13px;font-weight:bold;color:white;text-align:center;text-shadow:1px 1px 1px rgba(0,0,0,.3);background:#ff3019;background:-webkit-linear-gradient(top,#ff3019 0,#cf0404 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#ff3019),color-stop(100%,#cf0404));background:-moz-linear-gradient(top,#ff3019 0,#cf0404 100%);background:-ms-linear-gradient(top,#ff3019 0,#cf0404 100%);background:-o-linear-gradient(top,#ff3019 0,#cf0404 100%);background:linear-gradient(to bottom,#ff3019 0,#cf0404 100%);width:20px;height:20px;line-height:20px;border:3px solid white;border-radius:50%;filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3019', endColorstr='#cf0404', GradientType=0)";filter:"progid:DXImageTransform.Microsoft.Shadow(direction=135, strength=2, color=ff0000)";box-shadow:0 2px 5px rgba(0,0,0,.4)}.introjs-arrow{border:5px solid white;content:'';position:absolute}.introjs-arrow.top{top:-10px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:white;border-left-color:transparent}.introjs-arrow.top-right{top:-10px;right:10px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:white;border-left-color:transparent}.introjs-arrow.top-middle{top:-10px;left:50%;margin-left:-5px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:white;border-left-color:transparent}.introjs-arrow.right{right:-10px;top:10px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:transparent;border-left-color:white}.introjs-arrow.right-bottom{bottom:10px;right:-10px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:transparent;border-left-color:white}.introjs-arrow.bottom{bottom:-10px;border-top-color:white;border-right-color:transparent;border-bottom-color:transparent;border-left-color:transparent}.introjs-arrow.left{left:-10px;top:10px;border-top-color:transparent;border-right-color:white;border-bottom-color:transparent;border-left-color:transparent}.introjs-arrow.left-bottom{left:-10px;bottom:10px;border-top-color:transparent;border-right-color:white;border-bottom-color:transparent;border-left-color:transparent}.introjs-tooltip{box-sizing:content-box;position:absolute;visibility:visible;padding:10px;background-color:white;min-width:200px;max-width:300px;border-radius:3px;box-shadow:0 1px 10px rgba(0,0,0,.4);-webkit-transition:opacity .1s ease-out;-moz-transition:opacity .1s ease-out;-ms-transition:opacity .1s ease-out;-o-transition:opacity .1s ease-out;transition:opacity .1s ease-out}.introjs-tooltipbuttons{text-align:right;white-space:nowrap}.introjs-button{box-sizing:content-box;position:relative;overflow:visible;display:inline-block;padding:.3em .8em;border:1px solid #d4d4d4;margin:0;text-decoration:none;text-shadow:1px 1px 0 #fff;font:11px/normal sans-serif;color:#333;white-space:nowrap;cursor:pointer;outline:0;background-color:#ececec;background-image:-webkit-gradient(linear,0 0,0 100%,from(#f4f4f4),to(#ececec));background-image:-moz-linear-gradient(#f4f4f4,#ececec);background-image:-o-linear-gradient(#f4f4f4,#ececec);background-image:linear-gradient(#f4f4f4,#ececec);-webkit-background-clip:padding;-moz-background-clip:padding;-o-background-clip:padding-box;-webkit-border-radius:.2em;-moz-border-radius:.2em;border-radius:.2em;zoom:1;*display:inline;margin-top:10px}.introjs-button:hover{border-color:#bcbcbc;text-decoration:none;box-shadow:0 1px 1px #e3e3e3}.introjs-button:focus,.introjs-button:active{background-image:-webkit-gradient(linear,0 0,0 100%,from(#ececec),to(#f4f4f4));background-image:-moz-linear-gradient(#ececec,#f4f4f4);background-image:-o-linear-gradient(#ececec,#f4f4f4);background-image:linear-gradient(#ececec,#f4f4f4)}.introjs-button::-moz-focus-inner{padding:0;border:0}.introjs-skipbutton{box-sizing:content-box;margin-right:5px;color:#7a7a7a}.introjs-prevbutton{-webkit-border-radius:.2em 0 0 .2em;-moz-border-radius:.2em 0 0 .2em;border-radius:.2em 0 0 .2em;border-right:0}.introjs-prevbutton.introjs-fullbutton{border:1px solid #d4d4d4;-webkit-border-radius:.2em;-moz-border-radius:.2em;border-radius:.2em}.introjs-nextbutton{-webkit-border-radius:0 .2em .2em 0;-moz-border-radius:0 .2em .2em 0;border-radius:0 .2em .2em 0}.introjs-nextbutton.introjs-fullbutton{-webkit-border-radius:.2em;-moz-border-radius:.2em;border-radius:.2em}.introjs-disabled,.introjs-disabled:hover,.introjs-disabled:focus{color:#9a9a9a;border-color:#d4d4d4;box-shadow:none;cursor:default;background-color:#f4f4f4;background-image:none;text-decoration:none}.introjs-hidden{display:none}.introjs-bullets{text-align:center}.introjs-bullets ul{box-sizing:content-box;clear:both;margin:15px auto 0;padding:0;display:inline-block}.introjs-bullets ul li{box-sizing:content-box;list-style:none;float:left;margin:0 2px}.introjs-bullets ul li a{box-sizing:content-box;display:block;width:6px;height:6px;background:#ccc;border-radius:10px;-moz-border-radius:10px;-webkit-border-radius:10px;text-decoration:none;cursor:pointer}.introjs-bullets ul li a:hover{background:#999}.introjs-bullets ul li a.active{background:#999}.introjs-progress{box-sizing:content-box;overflow:hidden;height:10px;margin:10px 0 5px 0;border-radius:4px;background-color:#ecf0f1}.introjs-progressbar{box-sizing:content-box;float:left;width:0;height:100%;font-size:10px;line-height:10px;text-align:center;background-color:#08c}.introjsFloatingElement{position:absolute;height:0;width:0;left:50%;top:50%}.introjs-fixedTooltip{position:fixed}.introjs-hint{box-sizing:content-box;position:absolute;background:transparent;width:20px;height:15px;cursor:pointer}.introjs-hint:focus{border:0;outline:0}.introjs-hidehint{display:none}.introjs-fixedhint{position:fixed}.introjs-hint:hover>.introjs-hint-pulse{border:5px solid rgba(60,60,60,0.57)}.introjs-hint-pulse{box-sizing:content-box;width:10px;height:10px;border:5px solid rgba(60,60,60,0.27);-webkit-border-radius:30px;-moz-border-radius:30px;border-radius:30px;background-color:rgba(136,136,136,0.24);z-index:10;position:absolute;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-ms-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out}.introjs-hint-no-anim .introjs-hint-dot{-webkit-animation:none;-moz-animation:none;animation:none}.introjs-hint-dot{box-sizing:content-box;border:10px solid rgba(146,146,146,0.36);background:transparent;-webkit-border-radius:60px;-moz-border-radius:60px;border-radius:60px;height:50px;width:50px;-webkit-animation:introjspulse 3s ease-out;-moz-animation:introjspulse 3s ease-out;animation:introjspulse 3s ease-out;-webkit-animation-iteration-count:infinite;-moz-animation-iteration-count:infinite;animation-iteration-count:infinite;position:absolute;top:-25px;left:-25px;z-index:1;opacity:0}@-webkit-keyframes introjspulse{0%{-webkit-transform:scale(0);opacity:.0}25%{-webkit-transform:scale(0);opacity:.1}50%{-webkit-transform:scale(0.1);opacity:.3}75%{-webkit-transform:scale(0.5);opacity:.5}100%{-webkit-transform:scale(1);opacity:.0}}@-moz-keyframes introjspulse{0%{-moz-transform:scale(0);opacity:.0}25%{-moz-transform:scale(0);opacity:.1}50%{-moz-transform:scale(0.1);opacity:.3}75%{-moz-transform:scale(0.5);opacity:.5}100%{-moz-transform:scale(1);opacity:.0}}@keyframes introjspulse{0%{transform:scale(0);opacity:.0}25%{transform:scale(0);opacity:.1}50%{transform:scale(0.1);opacity:.3}75%{transform:scale(0.5);opacity:.5}100%{transform:scale(1);opacity:.0}} \ No newline at end of file From ed072944262d7adb379853519e73c4fedb1e3ccf Mon Sep 17 00:00:00 2001 From: Miguel Angel Arenas Correa Date: Mon, 4 Dec 2017 21:46:48 -0500 Subject: [PATCH 3/3] Delete introjs-rtl.min.css --- app/assets/stylesheets/introjs-rtl.min.css | 1 - 1 file changed, 1 deletion(-) delete mode 100755 app/assets/stylesheets/introjs-rtl.min.css diff --git a/app/assets/stylesheets/introjs-rtl.min.css b/app/assets/stylesheets/introjs-rtl.min.css deleted file mode 100755 index 755b2f7..0000000 --- a/app/assets/stylesheets/introjs-rtl.min.css +++ /dev/null @@ -1 +0,0 @@ -.introjs-tooltipbuttons{text-align:left}.introjs-skipbutton{margin-left:5px}.introjs-tooltip{direction:rtl}.introjs-prevbutton{border:1px solid #d4d4d4;border-left:none;-webkit-border-radius:0 .2em .2em 0;-moz-border-radius:0 .2em .2em 0;border-radius:0 .2em .2em 0}.introjs-nextbutton{border:1px solid #d4d4d4;-webkit-border-radius:.2em 0 0 .2em;-moz-border-radius:.2em 0 0 .2em;border-radius:.2em 0 0 .2em}.introjs-bullets ul li{float:right} \ No newline at end of file