|
/* ======================================================================== |
|
* bootstrap-tour - v0.11.0 |
|
* http://bootstraptour.com |
|
* ======================================================================== |
|
* Copyright 2012-2015 Ulrich Sossou |
|
* |
|
* ======================================================================== |
|
* Licensed under the MIT License (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* https://opensource.org/licenses/MIT |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
* ======================================================================== |
|
*/ |
|
|
|
(function(window, factory) { |
|
if (typeof define === 'function' && define.amd) { |
|
return define(['jquery'], function(jQuery) { |
|
return window.Tour = factory(jQuery); |
|
}); |
|
} else if (typeof exports === 'object') { |
|
return module.exports = factory(require('jquery')); |
|
} else { |
|
return window.Tour = factory(window.jQuery); |
|
} |
|
})(window, function($) { |
|
var Tour, document; |
|
document = window.document; |
|
Tour = (function() { |
|
function Tour(options) { |
|
var storage; |
|
try { |
|
storage = window.localStorage; |
|
} catch (_error) { |
|
storage = false; |
|
} |
|
this._options = $.extend({ |
|
name: 'tour', |
|
steps: [], |
|
container: 'body', |
|
autoscroll: true, |
|
keyboard: true, |
|
storage: storage, |
|
debug: false, |
|
backdrop: false, |
|
backdropContainer: 'body', |
|
backdropPadding: 0, |
|
redirect: true, |
|
orphan: false, |
|
duration: false, |
|
delay: false, |
|
basePath: '', |
|
template: '<div class="popover" role="tooltip"> <div class="arrow"></div> <h3 class="popover-header"></h3> <div class="popover-body"></div> <div class="popover-navigation"> <div class="btn-group"> <button class="btn btn-sm btn-secondary" data-role="prev">« Prev</button> <button class="btn btn-sm btn-secondary" data-role="next">Next »</button> <button class="btn btn-sm btn-secondary" data-role="pause-resume" data-pause-text="Pause" data-resume-text="Resume">Pause</button> </div> <button class="btn btn-sm btn-secondary" data-role="end">End tour</button> </div> </div>', |
|
afterSetState: function(key, value) {}, |
|
afterGetState: function(key, value) {}, |
|
afterRemoveState: function(key) {}, |
|
onStart: function(tour) {}, |
|
onEnd: function(tour) {}, |
|
onShow: function(tour) {}, |
|
onShown: function(tour) {}, |
|
onHide: function(tour) {}, |
|
onHidden: function(tour) {}, |
|
onNext: function(tour) {}, |
|
onPrev: function(tour) {}, |
|
onPause: function(tour, duration) {}, |
|
onResume: function(tour, duration) {}, |
|
onRedirectError: function(tour) {} |
|
}, options); |
|
this._force = false; |
|
this._inited = false; |
|
this._current = null; |
|
this.backdrops = []; |
|
this; |
|
} |
|
|
|
Tour.prototype.addSteps = function(steps) { |
|
var step, _i, _len; |
|
for (_i = 0, _len = steps.length; _i < _len; _i++) { |
|
step = steps[_i]; |
|
this.addStep(step); |
|
} |
|
return this; |
|
}; |
|
|
|
Tour.prototype.addStep = function(step) { |
|
this._options.steps.push(step); |
|
return this; |
|
}; |
|
|
|
Tour.prototype.getStep = function(i) { |
|
if (this._options.steps[i] != null) { |
|
return $.extend({ |
|
id: "step-" + i, |
|
path: '', |
|
host: '', |
|
placement: 'right', |
|
title: '', |
|
content: '<p></p>', |
|
next: i === this._options.steps.length - 1 ? -1 : i + 1, |
|
prev: i - 1, |
|
animation: true, |
|
container: this._options.container, |
|
autoscroll: this._options.autoscroll, |
|
backdrop: this._options.backdrop, |
|
backdropContainer: this._options.backdropContainer, |
|
backdropPadding: this._options.backdropPadding, |
|
redirect: this._options.redirect, |
|
reflexElement: this._options.steps[i].element, |
|
backdropElement: this._options.steps[i].element, |
|
orphan: this._options.orphan, |
|
duration: this._options.duration, |
|
delay: this._options.delay, |
|
template: this._options.template, |
|
onShow: this._options.onShow, |
|
onShown: this._options.onShown, |
|
onHide: this._options.onHide, |
|
onHidden: this._options.onHidden, |
|
onNext: this._options.onNext, |
|
onPrev: this._options.onPrev, |
|
onPause: this._options.onPause, |
|
onResume: this._options.onResume, |
|
onRedirectError: this._options.onRedirectError |
|
}, this._options.steps[i]); |
|
} |
|
}; |
|
|
|
Tour.prototype.init = function(force) { |
|
this._force = force; |
|
if (this.ended()) { |
|
this._debug('Tour ended, init prevented.'); |
|
return this; |
|
} |
|
this.setCurrentStep(); |
|
this._initMouseNavigation(); |
|
this._initKeyboardNavigation(); |
|
this._onResize((function(_this) { |
|
return function() { |
|
return _this.showStep(_this._current); |
|
}; |
|
})(this)); |
|
if (this._current !== null) { |
|
this.showStep(this._current); |
|
} |
|
this._inited = true; |
|
return this; |
|
}; |
|
|
|
Tour.prototype.start = function(force) { |
|
var promise; |
|
if (force == null) { |
|
force = false; |
|
} |
|
if (!this._inited) { |
|
this.init(force); |
|
} |
|
if (this._current === null) { |
|
promise = this._makePromise(this._options.onStart != null ? this._options.onStart(this) : void 0); |
|
this._callOnPromiseDone(promise, this.showStep, 0); |
|
} |
|
return this; |
|
}; |
|
|
|
Tour.prototype.next = function() { |
|
var promise; |
|
promise = this.hideStep(this._current, this._current + 1); |
|
return this._callOnPromiseDone(promise, this._showNextStep); |
|
}; |
|
|
|
Tour.prototype.prev = function() { |
|
var promise; |
|
promise = this.hideStep(this._current, this._current - 1); |
|
return this._callOnPromiseDone(promise, this._showPrevStep); |
|
}; |
|
|
|
Tour.prototype.goTo = function(i) { |
|
var promise; |
|
promise = this.hideStep(this._current, i); |
|
return this._callOnPromiseDone(promise, this.showStep, i); |
|
}; |
|
|
|
Tour.prototype.end = function() { |
|
var endHelper, promise; |
|
endHelper = (function(_this) { |
|
return function(e) { |
|
$(document).off("click.tour-" + _this._options.name); |
|
$(document).off("keyup.tour-" + _this._options.name); |
|
$(window).off("resize.tour-" + _this._options.name); |
|
_this._setState('end', 'yes'); |
|
_this._inited = false; |
|
_this._force = false; |
|
_this._clearTimer(); |
|
if (_this._options.onEnd != null) { |
|
return _this._options.onEnd(_this); |
|
} |
|
}; |
|
})(this); |
|
promise = this.hideStep(this._current); |
|
return this._callOnPromiseDone(promise, endHelper); |
|
}; |
|
|
|
Tour.prototype.ended = function() { |
|
return !this._force && !!this._getState('end'); |
|
}; |
|
|
|
Tour.prototype.restart = function() { |
|
this._removeState('current_step'); |
|
this._removeState('end'); |
|
this._removeState('redirect_to'); |
|
return this.start(); |
|
}; |
|
|
|
Tour.prototype.pause = function() { |
|
var step; |
|
step = this.getStep(this._current); |
|
if (!(step && step.duration)) { |
|
return this; |
|
} |
|
this._paused = true; |
|
this._duration -= new Date().getTime() - this._start; |
|
window.clearTimeout(this._timer); |
|
this._debug("Paused/Stopped step " + (this._current + 1) + " timer (" + this._duration + " remaining)."); |
|
if (step.onPause != null) { |
|
return step.onPause(this, this._duration); |
|
} |
|
}; |
|
|
|
Tour.prototype.resume = function() { |
|
var step; |
|
step = this.getStep(this._current); |
|
if (!(step && step.duration)) { |
|
return this; |
|
} |
|
this._paused = false; |
|
this._start = new Date().getTime(); |
|
this._duration = this._duration || step.duration; |
|
this._timer = window.setTimeout((function(_this) { |
|
return function() { |
|
if (_this._isLast()) { |
|
return _this.next(); |
|
} else { |
|
return _this.end(); |
|
} |
|
}; |
|
})(this), this._duration); |
|
this._debug("Started step " + (this._current + 1) + " timer with duration " + this._duration); |
|
if ((step.onResume != null) && this._duration !== step.duration) { |
|
return step.onResume(this, this._duration); |
|
} |
|
}; |
|
|
|
Tour.prototype.hideStep = function(i, iNext) { |
|
var hideDelay, hideStepHelper, promise, step; |
|
step = this.getStep(i); |
|
if (!step) { |
|
return; |
|
} |
|
this._clearTimer(); |
|
promise = this._makePromise(step.onHide != null ? step.onHide(this, i) : void 0); |
|
hideStepHelper = (function(_this) { |
|
return function(e) { |
|
var $element, next_step; |
|
$element = $(step.element); |
|
if (!($element.data('bs.popover') || $element.data('popover'))) { |
|
$element = $('body'); |
|
} |
|
$element.popover('dispose').removeClass("tour-" + _this._options.name + "-element tour-" + _this._options.name + "-" + i + "-element").removeData('bs.popover').focus(); |
|
if (step.reflex) { |
|
$(step.reflexElement).removeClass('tour-step-element-reflex').off("" + (_this._reflexEvent(step.reflex)) + ".tour-" + _this._options.name); |
|
} |
|
if (step.backdrop) { |
|
next_step = (iNext != null) && _this.getStep(iNext); |
|
if (!next_step || !next_step.backdrop || next_step.backdropElement !== step.backdropElement) { |
|
_this._hideOverlayElement(step); |
|
} |
|
} |
|
if (step.onHidden != null) { |
|
return step.onHidden(_this); |
|
} |
|
}; |
|
})(this); |
|
hideDelay = step.delay.hide || step.delay; |
|
if ({}.toString.call(hideDelay) === '[object Number]' && hideDelay > 0) { |
|
this._debug("Wait " + hideDelay + " milliseconds to hide the step " + (this._current + 1)); |
|
window.setTimeout((function(_this) { |
|
return function() { |
|
return _this._callOnPromiseDone(promise, hideStepHelper); |
|
}; |
|
})(this), hideDelay); |
|
} else { |
|
this._callOnPromiseDone(promise, hideStepHelper); |
|
} |
|
return promise; |
|
}; |
|
|
|
Tour.prototype.showStep = function(i) { |
|
var path, promise, showDelay, showStepHelper, skipToPrevious, step; |
|
if (this.ended()) { |
|
this._debug('Tour ended, showStep prevented.'); |
|
return this; |
|
} |
|
step = this.getStep(i); |
|
if (!step) { |
|
return; |
|
} |
|
skipToPrevious = i < this._current; |
|
promise = this._makePromise(step.onShow != null ? step.onShow(this, i) : void 0); |
|
this.setCurrentStep(i); |
|
path = (function() { |
|
switch ({}.toString.call(step.path)) { |
|
case '[object Function]': |
|
return step.path(); |
|
case '[object String]': |
|
return this._options.basePath + step.path; |
|
default: |
|
return step.path; |
|
} |
|
}).call(this); |
|
if (step.redirect && this._isRedirect(step.host, path, document.location)) { |
|
this._redirect(step, i, path); |
|
if (!this._isJustPathHashDifferent(step.host, path, document.location)) { |
|
return; |
|
} |
|
} |
|
showStepHelper = (function(_this) { |
|
return function(e) { |
|
var showPopoverAndOverlay; |
|
if (_this._isOrphan(step)) { |
|
if (step.orphan === false) { |
|
_this._debug("Skip the orphan step " + (_this._current + 1) + ".\nOrphan option is false and the element does not exist or is hidden."); |
|
if (skipToPrevious) { |
|
_this._showPrevStep(); |
|
} else { |
|
_this._showNextStep(); |
|
} |
|
return; |
|
} |
|
_this._debug("Show the orphan step " + (_this._current + 1) + ". Orphans option is true."); |
|
} |
|
showPopoverAndOverlay = function() { |
|
if (_this.getCurrentStep() !== i || _this.ended()) { |
|
return; |
|
} |
|
if (step.backdrop) { |
|
_this._showOverlayElement(step); |
|
} |
|
_this._showPopover(step, i); |
|
if (step.onShown != null) { |
|
step.onShown(_this); |
|
} |
|
return _this._debug("Step " + (_this._current + 1) + " of " + _this._options.steps.length); |
|
}; |
|
if (step.autoscroll) { |
|
_this._scrollIntoView(step, showPopoverAndOverlay); |
|
} else { |
|
showPopoverAndOverlay(); |
|
} |
|
if (step.duration) { |
|
return _this.resume(); |
|
} |
|
}; |
|
})(this); |
|
showDelay = step.delay.show || step.delay; |
|
if ({}.toString.call(showDelay) === '[object Number]' && showDelay > 0) { |
|
this._debug("Wait " + showDelay + " milliseconds to show the step " + (this._current + 1)); |
|
window.setTimeout((function(_this) { |
|
return function() { |
|
return _this._callOnPromiseDone(promise, showStepHelper); |
|
}; |
|
})(this), showDelay); |
|
} else { |
|
this._callOnPromiseDone(promise, showStepHelper); |
|
} |
|
return promise; |
|
}; |
|
|
|
Tour.prototype.getCurrentStep = function() { |
|
return this._current; |
|
}; |
|
|
|
Tour.prototype.setCurrentStep = function(value) { |
|
if (value != null) { |
|
this._current = value; |
|
this._setState('current_step', value); |
|
} else { |
|
this._current = this._getState('current_step'); |
|
this._current = this._current === null ? null : parseInt(this._current, 10); |
|
} |
|
return this; |
|
}; |
|
|
|
Tour.prototype.redraw = function() { |
|
return this._showOverlayElement(this.getStep(this.getCurrentStep())); |
|
}; |
|
|
|
Tour.prototype._setState = function(key, value) { |
|
var e, keyName; |
|
if (this._options.storage) { |
|
keyName = "" + this._options.name + "_" + key; |
|
try { |
|
this._options.storage.setItem(keyName, value); |
|
} catch (_error) { |
|
e = _error; |
|
if (e.code === DOMException.QUOTA_EXCEEDED_ERR) { |
|
this._debug('LocalStorage quota exceeded. State storage failed.'); |
|
} |
|
} |
|
return this._options.afterSetState(keyName, value); |
|
} else { |
|
if (this._state == null) { |
|
this._state = {}; |
|
} |
|
return this._state[key] = value; |
|
} |
|
}; |
|
|
|
Tour.prototype._removeState = function(key) { |
|
var keyName; |
|
if (this._options.storage) { |
|
keyName = "" + this._options.name + "_" + key; |
|
this._options.storage.removeItem(keyName); |
|
return this._options.afterRemoveState(keyName); |
|
} else { |
|
if (this._state != null) { |
|
return delete this._state[key]; |
|
} |
|
} |
|
}; |
|
|
|
Tour.prototype._getState = function(key) { |
|
var keyName, value; |
|
if (this._options.storage) { |
|
keyName = "" + this._options.name + "_" + key; |
|
value = this._options.storage.getItem(keyName); |
|
} else { |
|
if (this._state != null) { |
|
value = this._state[key]; |
|
} |
|
} |
|
if (value === void 0 || value === 'null') { |
|
value = null; |
|
} |
|
this._options.afterGetState(key, value); |
|
return value; |
|
}; |
|
|
|
Tour.prototype._showNextStep = function() { |
|
var promise, showNextStepHelper, step; |
|
step = this.getStep(this._current); |
|
showNextStepHelper = (function(_this) { |
|
return function(e) { |
|
return _this.showStep(step.next); |
|
}; |
|
})(this); |
|
promise = this._makePromise(step.onNext != null ? step.onNext(this) : void 0); |
|
return this._callOnPromiseDone(promise, showNextStepHelper); |
|
}; |
|
|
|
Tour.prototype._showPrevStep = function() { |
|
var promise, showPrevStepHelper, step; |
|
step = this.getStep(this._current); |
|
showPrevStepHelper = (function(_this) { |
|
return function(e) { |
|
return _this.showStep(step.prev); |
|
}; |
|
})(this); |
|
promise = this._makePromise(step.onPrev != null ? step.onPrev(this) : void 0); |
|
return this._callOnPromiseDone(promise, showPrevStepHelper); |
|
}; |
|
|
|
Tour.prototype._debug = function(text) { |
|
if (this._options.debug) { |
|
return window.console.log("Bootstrap Tour '" + this._options.name + "' | " + text); |
|
} |
|
}; |
|
|
|
Tour.prototype._isRedirect = function(host, path, location) { |
|
var currentPath; |
|
if ((host != null) && host !== '' && (({}.toString.call(host) === '[object RegExp]' && !host.test(location.origin)) || ({}.toString.call(host) === '[object String]' && this._isHostDifferent(host, location)))) { |
|
return true; |
|
} |
|
currentPath = [location.pathname, location.search, location.hash].join(''); |
|
return (path != null) && path !== '' && (({}.toString.call(path) === '[object RegExp]' && !path.test(currentPath)) || ({}.toString.call(path) === '[object String]' && this._isPathDifferent(path, currentPath))); |
|
}; |
|
|
|
Tour.prototype._isHostDifferent = function(host, location) { |
|
switch ({}.toString.call(host)) { |
|
case '[object RegExp]': |
|
return !host.test(location.origin); |
|
case '[object String]': |
|
return this._getProtocol(host) !== this._getProtocol(location.href) || this._getHost(host) !== this._getHost(location.href); |
|
default: |
|
return true; |
|
} |
|
}; |
|
|
|
Tour.prototype._isPathDifferent = function(path, currentPath) { |
|
return this._getPath(path) !== this._getPath(currentPath) || !this._equal(this._getQuery(path), this._getQuery(currentPath)) || !this._equal(this._getHash(path), this._getHash(currentPath)); |
|
}; |
|
|
|
Tour.prototype._isJustPathHashDifferent = function(host, path, location) { |
|
var currentPath; |
|
if ((host != null) && host !== '') { |
|
if (this._isHostDifferent(host, location)) { |
|
return false; |
|
} |
|
} |
|
currentPath = [location.pathname, location.search, location.hash].join(''); |
|
if ({}.toString.call(path) === '[object String]') { |
|
return this._getPath(path) === this._getPath(currentPath) && this._equal(this._getQuery(path), this._getQuery(currentPath)) && !this._equal(this._getHash(path), this._getHash(currentPath)); |
|
} |
|
return false; |
|
}; |
|
|
|
Tour.prototype._redirect = function(step, i, path) { |
|
var href; |
|
if ($.isFunction(step.redirect)) { |
|
return step.redirect.call(this, path); |
|
} else { |
|
href = {}.toString.call(step.host) === '[object String]' ? "" + step.host + path : path; |
|
this._debug("Redirect to " + href); |
|
if (this._getState('redirect_to') === ("" + i)) { |
|
this._debug("Error redirection loop to " + path); |
|
this._removeState('redirect_to'); |
|
if (step.onRedirectError != null) { |
|
return step.onRedirectError(this); |
|
} |
|
} else { |
|
this._setState('redirect_to', "" + i); |
|
return document.location.href = href; |
|
} |
|
} |
|
}; |
|
|
|
Tour.prototype._isOrphan = function(step) { |
|
return (step.element == null) || !$(step.element).length || $(step.element).is(':hidden') && ($(step.element)[0].namespaceURI !== 'http://www.w3.org/2000/svg'); |
|
}; |
|
|
|
Tour.prototype._isLast = function() { |
|
return this._current < this._options.steps.length - 1; |
|
}; |
|
|
|
Tour.prototype._showPopover = function(step, i) { |
|
var $element, $tip, isOrphan, options, shouldAddSmart; |
|
$(".tour-" + this._options.name).remove(); |
|
options = $.extend({}, this._options); |
|
isOrphan = this._isOrphan(step); |
|
step.template = this._template(step, i); |
|
if (isOrphan) { |
|
step.element = 'body'; |
|
step.placement = 'top'; |
|
} |
|
$element = $(step.element); |
|
$element.addClass("tour-" + this._options.name + "-element tour-" + this._options.name + "-" + i + "-element"); |
|
if (step.options) { |
|
$.extend(options, step.options); |
|
} |
|
if (step.reflex && !isOrphan) { |
|
$(step.reflexElement).addClass('tour-step-element-reflex').off("" + (this._reflexEvent(step.reflex)) + ".tour-" + this._options.name).on("" + (this._reflexEvent(step.reflex)) + ".tour-" + this._options.name, (function(_this) { |
|
return function() { |
|
if (_this._isLast()) { |
|
return _this.next(); |
|
} else { |
|
return _this.end(); |
|
} |
|
}; |
|
})(this)); |
|
} |
|
shouldAddSmart = step.smartPlacement === true && step.placement.search(/auto/i) === -1; |
|
$element.popover({ |
|
placement: shouldAddSmart ? "auto " + step.placement : step.placement, |
|
trigger: 'manual', |
|
title: step.title, |
|
content: step.content, |
|
html: true, |
|
animation: step.animation, |
|
container: step.container, |
|
template: step.template, |
|
selector: step.element |
|
}).popover('show'); |
|
$tip = $element.data('bs.popover').getTipElement(); |
|
$($tip).attr('id', step.id); |
|
this._focus($($tip), $element, step.next < 0); |
|
this._reposition($($tip), step); |
|
if (isOrphan) { |
|
return this._center($($tip)); |
|
} |
|
}; |
|
|
|
Tour.prototype._template = function(step, i) { |
|
var $navigation, $next, $prev, $resume, $template, template; |
|
template = step.template; |
|
if (this._isOrphan(step) && {}.toString.call(step.orphan) !== '[object Boolean]') { |
|
template = step.orphan; |
|
} |
|
$template = $.isFunction(template) ? $(template(i, step)) : $(template); |
|
$navigation = $template.find('.popover-navigation'); |
|
$prev = $navigation.find('[data-role="prev"]'); |
|
$next = $navigation.find('[data-role="next"]'); |
|
$resume = $navigation.find('[data-role="pause-resume"]'); |
|
if (this._isOrphan(step)) { |
|
$template.addClass('orphan'); |
|
} |
|
$template.addClass("tour-" + this._options.name + " tour-" + this._options.name + "-" + i); |
|
if (step.reflex) { |
|
$template.addClass("tour-" + this._options.name + "-reflex"); |
|
} |
|
if (step.prev < 0) { |
|
$prev.addClass('disabled').prop('disabled', true).prop('tabindex', -1); |
|
} |
|
if (step.next < 0) { |
|
$next.addClass('disabled').prop('disabled', true).prop('tabindex', -1); |
|
} |
|
if (!step.duration) { |
|
$resume.remove(); |
|
} |
|
return $template.clone().wrap('<div>').parent().html(); |
|
}; |
|
|
|
Tour.prototype._reflexEvent = function(reflex) { |
|
if ({}.toString.call(reflex) === '[object Boolean]') { |
|
return 'click'; |
|
} else { |
|
return reflex; |
|
} |
|
}; |
|
|
|
Tour.prototype._focus = function($tip, $element, end) { |
|
var $next, role; |
|
role = end ? 'end' : 'next'; |
|
$next = $($tip).find("[data-role='" + role + "']"); |
|
return $element.on('shown.bs.popover', function() { |
|
return $next.focus(); |
|
}); |
|
}; |
|
|
|
Tour.prototype._reposition = function($tip, step) { |
|
var offsetBottom, offsetHeight, offsetRight, offsetWidth, originalLeft, originalTop, tipOffset; |
|
offsetWidth = $($tip)[0].offsetWidth; |
|
offsetHeight = $($tip)[0].offsetHeight; |
|
tipOffset = $($tip).offset(); |
|
originalLeft = tipOffset.left; |
|
originalTop = tipOffset.top; |
|
offsetBottom = $(document).outerHeight() - tipOffset.top - $($tip).outerHeight(); |
|
if (offsetBottom < 0) { |
|
tipOffset.top = tipOffset.top + offsetBottom; |
|
} |
|
offsetRight = $('html').outerWidth() - tipOffset.left - $($tip).outerWidth(); |
|
if (offsetRight < 0) { |
|
tipOffset.left = tipOffset.left + offsetRight; |
|
} |
|
if (tipOffset.top < 0) { |
|
tipOffset.top = 0; |
|
} |
|
if (tipOffset.left < 0) { |
|
tipOffset.left = 0; |
|
} |
|
$($tip).offset(tipOffset); |
|
if (step.placement === 'bottom' || step.placement === 'top') { |
|
if (originalLeft !== tipOffset.left) { |
|
return this._replaceArrow($($tip), (tipOffset.left - originalLeft) * 2, offsetWidth, 'left'); |
|
} |
|
} else { |
|
if (originalTop !== tipOffset.top) { |
|
return this._replaceArrow($($tip), (tipOffset.top - originalTop) * 2, offsetHeight, 'top'); |
|
} |
|
} |
|
}; |
|
|
|
Tour.prototype._center = function($tip) { |
|
return $($tip).css('top', $(window).outerHeight() / 2 - $($tip).outerHeight() / 2); |
|
}; |
|
|
|
Tour.prototype._replaceArrow = function($tip, delta, dimension, position) { |
|
return $($tip).find('.arrow').css(position, delta ? 50 * (1 - delta / dimension) + '%' : ''); |
|
}; |
|
|
|
Tour.prototype._scrollIntoView = function(step, callback) { |
|
var $element, $window, counter, height, offsetTop, scrollTop, windowHeight; |
|
$element = $(step.element); |
|
if (!$element.length) { |
|
return callback(); |
|
} |
|
$window = $(window); |
|
offsetTop = $element.offset().top; |
|
height = $element.outerHeight(); |
|
windowHeight = $window.height(); |
|
scrollTop = 0; |
|
switch (step.placement) { |
|
case 'top': |
|
scrollTop = Math.max(0, offsetTop - (windowHeight / 2)); |
|
break; |
|
case 'left': |
|
case 'right': |
|
scrollTop = Math.max(0, (offsetTop + height / 2) - (windowHeight / 2)); |
|
break; |
|
case 'bottom': |
|
scrollTop = Math.max(0, (offsetTop + height) - (windowHeight / 2)); |
|
} |
|
this._debug("Scroll into view. ScrollTop: " + scrollTop + ". Element offset: " + offsetTop + ". Window height: " + windowHeight + "."); |
|
counter = 0; |
|
return $('body, html').stop(true, true).animate({ |
|
scrollTop: Math.ceil(scrollTop) |
|
}, (function(_this) { |
|
return function() { |
|
if (++counter === 2) { |
|
callback(); |
|
return _this._debug("Scroll into view.\nAnimation end element offset: " + ($element.offset().top) + ".\nWindow height: " + ($window.height()) + "."); |
|
} |
|
}; |
|
})(this)); |
|
}; |
|
|
|
Tour.prototype._onResize = function(callback, timeout) { |
|
return $(window).on("resize.tour-" + this._options.name, function() { |
|
clearTimeout(timeout); |
|
return timeout = setTimeout(callback, 100); |
|
}); |
|
}; |
|
|
|
Tour.prototype._initMouseNavigation = function() { |
|
var _this; |
|
_this = this; |
|
return $(document).off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='prev']").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='next']").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='end']").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='pause-resume']").on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='next']", (function(_this) { |
|
return function(e) { |
|
e.preventDefault(); |
|
return _this.next(); |
|
}; |
|
})(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='prev']", (function(_this) { |
|
return function(e) { |
|
e.preventDefault(); |
|
if (_this._current > 0) { |
|
return _this.prev(); |
|
} |
|
}; |
|
})(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='end']", (function(_this) { |
|
return function(e) { |
|
e.preventDefault(); |
|
return _this.end(); |
|
}; |
|
})(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='pause-resume']", function(e) { |
|
var $this; |
|
e.preventDefault(); |
|
$this = $(this); |
|
$this.text(_this._paused ? $this.data('pause-text') : $this.data('resume-text')); |
|
if (_this._paused) { |
|
return _this.resume(); |
|
} else { |
|
return _this.pause(); |
|
} |
|
}); |
|
}; |
|
|
|
Tour.prototype._initKeyboardNavigation = function() { |
|
if (!this._options.keyboard) { |
|
return; |
|
} |
|
return $(document).on("keyup.tour-" + this._options.name, (function(_this) { |
|
return function(e) { |
|
if (!e.which) { |
|
return; |
|
} |
|
switch (e.which) { |
|
case 39: |
|
e.preventDefault(); |
|
if (_this._isLast()) { |
|
return _this.next(); |
|
} else { |
|
return _this.end(); |
|
} |
|
break; |
|
case 37: |
|
e.preventDefault(); |
|
if (_this._current > 0) { |
|
return _this.prev(); |
|
} |
|
} |
|
}; |
|
})(this)); |
|
}; |
|
|
|
Tour.prototype._makePromise = function(result) { |
|
if (result && $.isFunction(result.then)) { |
|
return result; |
|
} else { |
|
return null; |
|
} |
|
}; |
|
|
|
Tour.prototype._callOnPromiseDone = function(promise, cb, arg) { |
|
if (promise) { |
|
return promise.then((function(_this) { |
|
return function(e) { |
|
return cb.call(_this, arg); |
|
}; |
|
})(this)); |
|
} else { |
|
return cb.call(this, arg); |
|
} |
|
}; |
|
|
|
Tour.prototype._showBackground = function(step, data) { |
|
var $backdrop, height, pos, width, _base, _i, _len, _ref, _results; |
|
height = $(document).height(); |
|
width = $(document).width(); |
|
_ref = ['top', 'bottom', 'left', 'right']; |
|
_results = []; |
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) { |
|
pos = _ref[_i]; |
|
$backdrop = (_base = this.backdrops)[pos] != null ? _base[pos] : _base[pos] = $('<div>', { |
|
"class": "tour-backdrop " + pos |
|
}); |
|
$(step.backdropContainer).append($backdrop); |
|
switch (pos) { |
|
case 'top': |
|
_results.push($backdrop.height(data.offset.top > 0 ? data.offset.top : 0).width(width).offset({ |
|
top: 0, |
|
left: 0 |
|
})); |
|
break; |
|
case 'bottom': |
|
_results.push($backdrop.offset({ |
|
top: data.offset.top + data.height, |
|
left: 0 |
|
}).height(height - (data.offset.top + data.height)).width(width)); |
|
break; |
|
case 'left': |
|
_results.push($backdrop.offset({ |
|
top: data.offset.top, |
|
left: 0 |
|
}).height(data.height).width(data.offset.left > 0 ? data.offset.left : 0)); |
|
break; |
|
case 'right': |
|
_results.push($backdrop.offset({ |
|
top: data.offset.top, |
|
left: data.offset.left + data.width |
|
}).height(data.height).width(width - (data.offset.left + data.width))); |
|
break; |
|
default: |
|
_results.push(void 0); |
|
} |
|
} |
|
return _results; |
|
}; |
|
|
|
Tour.prototype._showOverlayElement = function(step) { |
|
var $backdropElement, elementData; |
|
$backdropElement = $(step.backdropElement); |
|
if ($backdropElement.length === 0) { |
|
elementData = { |
|
width: 0, |
|
height: 0, |
|
offset: { |
|
top: 0, |
|
left: 0 |
|
} |
|
}; |
|
} else { |
|
elementData = { |
|
width: $backdropElement.innerWidth(), |
|
height: $backdropElement.innerHeight(), |
|
offset: $backdropElement.offset() |
|
}; |
|
$backdropElement.addClass('tour-step-backdrop'); |
|
if (step.backdropPadding) { |
|
elementData = this._applyBackdropPadding(step.backdropPadding, elementData); |
|
} |
|
} |
|
return this._showBackground(step, elementData); |
|
}; |
|
|
|
Tour.prototype._hideOverlayElement = function(step) { |
|
var $backdrop, pos, _ref; |
|
$(step.backdropElement).removeClass('tour-step-backdrop'); |
|
_ref = this.backdrops; |
|
for (pos in _ref) { |
|
$backdrop = _ref[pos]; |
|
if ($backdrop && $backdrop.remove !== void 0) { |
|
$backdrop.remove(); |
|
} |
|
} |
|
return this.backdrops = []; |
|
}; |
|
|
|
Tour.prototype._applyBackdropPadding = function(padding, data) { |
|
if (typeof padding === 'object') { |
|
if (padding.top == null) { |
|
padding.top = 0; |
|
} |
|
if (padding.right == null) { |
|
padding.right = 0; |
|
} |
|
if (padding.bottom == null) { |
|
padding.bottom = 0; |
|
} |
|
if (padding.left == null) { |
|
padding.left = 0; |
|
} |
|
data.offset.top = data.offset.top - padding.top; |
|
data.offset.left = data.offset.left - padding.left; |
|
data.width = data.width + padding.left + padding.right; |
|
data.height = data.height + padding.top + padding.bottom; |
|
} else { |
|
data.offset.top = data.offset.top - padding; |
|
data.offset.left = data.offset.left - padding; |
|
data.width = data.width + (padding * 2); |
|
data.height = data.height + (padding * 2); |
|
} |
|
return data; |
|
}; |
|
|
|
Tour.prototype._clearTimer = function() { |
|
window.clearTimeout(this._timer); |
|
this._timer = null; |
|
return this._duration = null; |
|
}; |
|
|
|
Tour.prototype._getProtocol = function(url) { |
|
url = url.split('://'); |
|
if (url.length > 1) { |
|
return url[0]; |
|
} else { |
|
return 'http'; |
|
} |
|
}; |
|
|
|
Tour.prototype._getHost = function(url) { |
|
url = url.split('//'); |
|
url = url.length > 1 ? url[1] : url[0]; |
|
return url.split('/')[0]; |
|
}; |
|
|
|
Tour.prototype._getPath = function(path) { |
|
return path.replace(/\/?$/, '').split('?')[0].split('#')[0]; |
|
}; |
|
|
|
Tour.prototype._getQuery = function(path) { |
|
return this._getParams(path, '?'); |
|
}; |
|
|
|
Tour.prototype._getHash = function(path) { |
|
return this._getParams(path, '#'); |
|
}; |
|
|
|
Tour.prototype._getParams = function(path, start) { |
|
var param, params, paramsObject, _i, _len; |
|
params = path.split(start); |
|
if (params.length === 1) { |
|
return {}; |
|
} |
|
params = params[1].split('&'); |
|
paramsObject = {}; |
|
for (_i = 0, _len = params.length; _i < _len; _i++) { |
|
param = params[_i]; |
|
param = param.split('='); |
|
paramsObject[param[0]] = param[1] || ''; |
|
} |
|
return paramsObject; |
|
}; |
|
|
|
Tour.prototype._equal = function(obj1, obj2) { |
|
var k, obj1Keys, obj2Keys, v, _i, _len; |
|
if ({}.toString.call(obj1) === '[object Object]' && {}.toString.call(obj2) === '[object Object]') { |
|
obj1Keys = Object.keys(obj1); |
|
obj2Keys = Object.keys(obj2); |
|
if (obj1Keys.length !== obj2Keys.length) { |
|
return false; |
|
} |
|
for (k in obj1) { |
|
v = obj1[k]; |
|
if (!this._equal(obj2[k], v)) { |
|
return false; |
|
} |
|
} |
|
return true; |
|
} else if ({}.toString.call(obj1) === '[object Array]' && {}.toString.call(obj2) === '[object Array]') { |
|
if (obj1.length !== obj2.length) { |
|
return false; |
|
} |
|
for (k = _i = 0, _len = obj1.length; _i < _len; k = ++_i) { |
|
v = obj1[k]; |
|
if (!this._equal(v, obj2[k])) { |
|
return false; |
|
} |
|
} |
|
return true; |
|
} else { |
|
return obj1 === obj2; |
|
} |
|
}; |
|
|
|
return Tour; |
|
|
|
})(); |
|
return Tour; |
|
}); |