bootstrap-tour.js (27961B)
1 /* ======================================================================== 2 * bootstrap-tour - v0.10.1 3 * http://bootstraptour.com 4 * ======================================================================== 5 * Copyright 2012-2013 Ulrich Sossou 6 * 7 * ======================================================================== 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 * ======================================================================== 20 */ 21 22 (function($, window) { 23 var Tour, document; 24 document = window.document; 25 Tour = (function() { 26 function Tour(options) { 27 var storage; 28 try { 29 storage = window.localStorage; 30 } catch (_error) { 31 storage = false; 32 } 33 this._options = $.extend({ 34 name: 'tour', 35 steps: [], 36 container: 'body', 37 autoscroll: true, 38 keyboard: true, 39 storage: storage, 40 debug: false, 41 backdrop: false, 42 backdropPadding: 0, 43 redirect: true, 44 orphan: false, 45 duration: false, 46 delay: false, 47 basePath: '', 48 template: '<div class="popover" role="tooltip"> <div class="arrow"></div> <h3 class="popover-title"></h3> <div class="popover-content"></div> <div class="popover-navigation"> <div class="btn-group"> <button class="btn btn-sm btn-default" data-role="prev">« Prev</button> <button class="btn btn-sm btn-default" data-role="next">Next »</button> <button class="btn btn-sm btn-default" data-role="pause-resume" data-pause-text="Pause" data-resume-text="Resume">Pause</button> </div> <button class="btn btn-sm btn-default" data-role="end">End tour</button> </div> </div>', 49 afterSetState: function(key, value) {}, 50 afterGetState: function(key, value) {}, 51 afterRemoveState: function(key) {}, 52 onStart: function(tour) {}, 53 onEnd: function(tour) {}, 54 onShow: function(tour) {}, 55 onShown: function(tour) {}, 56 onHide: function(tour) {}, 57 onHidden: function(tour) {}, 58 onNext: function(tour) {}, 59 onPrev: function(tour) {}, 60 onPause: function(tour, duration) {}, 61 onResume: function(tour, duration) {} 62 }, options); 63 this._force = false; 64 this._inited = false; 65 this.backdrop = { 66 overlay: null, 67 $element: null, 68 $background: null, 69 backgroundShown: false, 70 overlayElementShown: false 71 }; 72 this; 73 } 74 75 Tour.prototype.addSteps = function(steps) { 76 var step, _i, _len; 77 for (_i = 0, _len = steps.length; _i < _len; _i++) { 78 step = steps[_i]; 79 this.addStep(step); 80 } 81 return this; 82 }; 83 84 Tour.prototype.addStep = function(step) { 85 this._options.steps.push(step); 86 return this; 87 }; 88 89 Tour.prototype.getStep = function(i) { 90 if (this._options.steps[i] != null) { 91 return $.extend({ 92 id: "step-" + i, 93 path: '', 94 placement: 'right', 95 title: '', 96 content: '<p></p>', 97 next: i === this._options.steps.length - 1 ? -1 : i + 1, 98 prev: i - 1, 99 animation: true, 100 container: this._options.container, 101 autoscroll: this._options.autoscroll, 102 backdrop: this._options.backdrop, 103 backdropPadding: this._options.backdropPadding, 104 redirect: this._options.redirect, 105 orphan: this._options.orphan, 106 duration: this._options.duration, 107 delay: this._options.delay, 108 template: this._options.template, 109 onShow: this._options.onShow, 110 onShown: this._options.onShown, 111 onHide: this._options.onHide, 112 onHidden: this._options.onHidden, 113 onNext: this._options.onNext, 114 onPrev: this._options.onPrev, 115 onPause: this._options.onPause, 116 onResume: this._options.onResume 117 }, this._options.steps[i]); 118 } 119 }; 120 121 Tour.prototype.init = function(force) { 122 this._force = force; 123 if (this.ended()) { 124 this._debug('Tour ended, init prevented.'); 125 return this; 126 } 127 this.setCurrentStep(); 128 this._initMouseNavigation(); 129 this._initKeyboardNavigation(); 130 this._onResize((function(_this) { 131 return function() { 132 return _this.showStep(_this._current); 133 }; 134 })(this)); 135 if (this._current !== null) { 136 this.showStep(this._current); 137 } 138 this._inited = true; 139 return this; 140 }; 141 142 Tour.prototype.start = function(force) { 143 var promise; 144 if (force == null) { 145 force = false; 146 } 147 if (!this._inited) { 148 this.init(force); 149 } 150 if (this._current === null) { 151 promise = this._makePromise(this._options.onStart != null ? this._options.onStart(this) : void 0); 152 this._callOnPromiseDone(promise, this.showStep, 0); 153 } 154 return this; 155 }; 156 157 Tour.prototype.next = function() { 158 var promise; 159 promise = this.hideStep(this._current); 160 return this._callOnPromiseDone(promise, this._showNextStep); 161 }; 162 163 Tour.prototype.prev = function() { 164 var promise; 165 promise = this.hideStep(this._current); 166 return this._callOnPromiseDone(promise, this._showPrevStep); 167 }; 168 169 Tour.prototype.goTo = function(i) { 170 var promise; 171 promise = this.hideStep(this._current); 172 return this._callOnPromiseDone(promise, this.showStep, i); 173 }; 174 175 Tour.prototype.end = function() { 176 var endHelper, promise; 177 endHelper = (function(_this) { 178 return function(e) { 179 $(document).off("click.tour-" + _this._options.name); 180 $(document).off("keyup.tour-" + _this._options.name); 181 $(window).off("resize.tour-" + _this._options.name); 182 _this._setState('end', 'yes'); 183 _this._inited = false; 184 _this._force = false; 185 _this._clearTimer(); 186 if (_this._options.onEnd != null) { 187 return _this._options.onEnd(_this); 188 } 189 }; 190 })(this); 191 promise = this.hideStep(this._current); 192 return this._callOnPromiseDone(promise, endHelper); 193 }; 194 195 Tour.prototype.ended = function() { 196 return !this._force && !!this._getState('end'); 197 }; 198 199 Tour.prototype.restart = function() { 200 this._removeState('current_step'); 201 this._removeState('end'); 202 return this.start(); 203 }; 204 205 Tour.prototype.pause = function() { 206 var step; 207 step = this.getStep(this._current); 208 if (!(step && step.duration)) { 209 return this; 210 } 211 this._paused = true; 212 this._duration -= new Date().getTime() - this._start; 213 window.clearTimeout(this._timer); 214 this._debug("Paused/Stopped step " + (this._current + 1) + " timer (" + this._duration + " remaining)."); 215 if (step.onPause != null) { 216 return step.onPause(this, this._duration); 217 } 218 }; 219 220 Tour.prototype.resume = function() { 221 var step; 222 step = this.getStep(this._current); 223 if (!(step && step.duration)) { 224 return this; 225 } 226 this._paused = false; 227 this._start = new Date().getTime(); 228 this._duration = this._duration || step.duration; 229 this._timer = window.setTimeout((function(_this) { 230 return function() { 231 if (_this._isLast()) { 232 return _this.next(); 233 } else { 234 return _this.end(); 235 } 236 }; 237 })(this), this._duration); 238 this._debug("Started step " + (this._current + 1) + " timer with duration " + this._duration); 239 if ((step.onResume != null) && this._duration !== step.duration) { 240 return step.onResume(this, this._duration); 241 } 242 }; 243 244 Tour.prototype.hideStep = function(i) { 245 var hideStepHelper, promise, step; 246 step = this.getStep(i); 247 if (!step) { 248 return; 249 } 250 this._clearTimer(); 251 promise = this._makePromise(step.onHide != null ? step.onHide(this, i) : void 0); 252 hideStepHelper = (function(_this) { 253 return function(e) { 254 var $element; 255 $element = $(step.element); 256 if (!($element.data('bs.popover') || $element.data('popover'))) { 257 $element = $('body'); 258 } 259 $element.popover('destroy').removeClass("tour-" + _this._options.name + "-element tour-" + _this._options.name + "-" + i + "-element"); 260 if (step.reflex) { 261 $element.removeClass('tour-step-element-reflex').off("" + (_this._reflexEvent(step.reflex)) + ".tour-" + _this._options.name); 262 } 263 if (step.backdrop) { 264 _this._hideBackdrop(); 265 } 266 if (step.onHidden != null) { 267 return step.onHidden(_this); 268 } 269 }; 270 })(this); 271 this._callOnPromiseDone(promise, hideStepHelper); 272 return promise; 273 }; 274 275 Tour.prototype.showStep = function(i) { 276 var promise, showStepHelper, skipToPrevious, step; 277 if (this.ended()) { 278 this._debug('Tour ended, showStep prevented.'); 279 return this; 280 } 281 step = this.getStep(i); 282 if (!step) { 283 return; 284 } 285 skipToPrevious = i < this._current; 286 promise = this._makePromise(step.onShow != null ? step.onShow(this, i) : void 0); 287 showStepHelper = (function(_this) { 288 return function(e) { 289 var current_path, path, showPopoverAndOverlay; 290 _this.setCurrentStep(i); 291 path = (function() { 292 switch ({}.toString.call(step.path)) { 293 case '[object Function]': 294 return step.path(); 295 case '[object String]': 296 return this._options.basePath + step.path; 297 default: 298 return step.path; 299 } 300 }).call(_this); 301 current_path = [document.location.pathname, document.location.hash].join(''); 302 if (_this._isRedirect(path, current_path)) { 303 _this._redirect(step, path); 304 return; 305 } 306 if (_this._isOrphan(step)) { 307 if (!step.orphan) { 308 _this._debug("Skip the orphan step " + (_this._current + 1) + ".\nOrphan option is false and the element does not exist or is hidden."); 309 if (skipToPrevious) { 310 _this._showPrevStep(); 311 } else { 312 _this._showNextStep(); 313 } 314 return; 315 } 316 _this._debug("Show the orphan step " + (_this._current + 1) + ". Orphans option is true."); 317 } 318 if (step.backdrop) { 319 _this._showBackdrop(!_this._isOrphan(step) ? step.element : void 0); 320 } 321 showPopoverAndOverlay = function() { 322 if (_this.getCurrentStep() !== i) { 323 return; 324 } 325 if ((step.element != null) && step.backdrop) { 326 _this._showOverlayElement(step); 327 } 328 _this._showPopover(step, i); 329 if (step.onShown != null) { 330 step.onShown(_this); 331 } 332 return _this._debug("Step " + (_this._current + 1) + " of " + _this._options.steps.length); 333 }; 334 if (step.autoscroll) { 335 _this._scrollIntoView(step.element, showPopoverAndOverlay); 336 } else { 337 showPopoverAndOverlay(); 338 } 339 if (step.duration) { 340 return _this.resume(); 341 } 342 }; 343 })(this); 344 if (step.delay) { 345 this._debug("Wait " + step.delay + " milliseconds to show the step " + (this._current + 1)); 346 window.setTimeout((function(_this) { 347 return function() { 348 return _this._callOnPromiseDone(promise, showStepHelper); 349 }; 350 })(this), step.delay); 351 } else { 352 this._callOnPromiseDone(promise, showStepHelper); 353 } 354 return promise; 355 }; 356 357 Tour.prototype.getCurrentStep = function() { 358 return this._current; 359 }; 360 361 Tour.prototype.setCurrentStep = function(value) { 362 if (value != null) { 363 this._current = value; 364 this._setState('current_step', value); 365 } else { 366 this._current = this._getState('current_step'); 367 this._current = this._current === null ? null : parseInt(this._current, 10); 368 } 369 return this; 370 }; 371 372 Tour.prototype._setState = function(key, value) { 373 var e, keyName; 374 if (this._options.storage) { 375 keyName = "" + this._options.name + "_" + key; 376 try { 377 this._options.storage.setItem(keyName, value); 378 } catch (_error) { 379 e = _error; 380 if (e.code === DOMException.QUOTA_EXCEEDED_ERR) { 381 this._debug('LocalStorage quota exceeded. State storage failed.'); 382 } 383 } 384 return this._options.afterSetState(keyName, value); 385 } else { 386 if (this._state == null) { 387 this._state = {}; 388 } 389 return this._state[key] = value; 390 } 391 }; 392 393 Tour.prototype._removeState = function(key) { 394 var keyName; 395 if (this._options.storage) { 396 keyName = "" + this._options.name + "_" + key; 397 this._options.storage.removeItem(keyName); 398 return this._options.afterRemoveState(keyName); 399 } else { 400 if (this._state != null) { 401 return delete this._state[key]; 402 } 403 } 404 }; 405 406 Tour.prototype._getState = function(key) { 407 var keyName, value; 408 if (this._options.storage) { 409 keyName = "" + this._options.name + "_" + key; 410 value = this._options.storage.getItem(keyName); 411 } else { 412 if (this._state != null) { 413 value = this._state[key]; 414 } 415 } 416 if (value === void 0 || value === 'null') { 417 value = null; 418 } 419 this._options.afterGetState(key, value); 420 return value; 421 }; 422 423 Tour.prototype._showNextStep = function() { 424 var promise, showNextStepHelper, step; 425 step = this.getStep(this._current); 426 showNextStepHelper = (function(_this) { 427 return function(e) { 428 return _this.showStep(step.next); 429 }; 430 })(this); 431 promise = this._makePromise(step.onNext != null ? step.onNext(this) : void 0); 432 return this._callOnPromiseDone(promise, showNextStepHelper); 433 }; 434 435 Tour.prototype._showPrevStep = function() { 436 var promise, showPrevStepHelper, step; 437 step = this.getStep(this._current); 438 showPrevStepHelper = (function(_this) { 439 return function(e) { 440 return _this.showStep(step.prev); 441 }; 442 })(this); 443 promise = this._makePromise(step.onPrev != null ? step.onPrev(this) : void 0); 444 return this._callOnPromiseDone(promise, showPrevStepHelper); 445 }; 446 447 Tour.prototype._debug = function(text) { 448 if (this._options.debug) { 449 return window.console.log("Bootstrap Tour '" + this._options.name + "' | " + text); 450 } 451 }; 452 453 Tour.prototype._isRedirect = function(path, currentPath) { 454 return (path != null) && path !== '' && (({}.toString.call(path) === '[object RegExp]' && !path.test(currentPath)) || ({}.toString.call(path) === '[object String]' && path.replace(/\?.*$/, '').replace(/\/?$/, '') !== currentPath.replace(/\/?$/, ''))); 455 }; 456 457 Tour.prototype._redirect = function(step, path) { 458 if ($.isFunction(step.redirect)) { 459 return step.redirect.call(this, path); 460 } else if (step.redirect === true) { 461 this._debug("Redirect to " + path); 462 return document.location.href = path; 463 } 464 }; 465 466 Tour.prototype._isOrphan = function(step) { 467 return (step.element == null) || !$(step.element).length || $(step.element).is(':hidden') && ($(step.element)[0].namespaceURI !== 'http://www.w3.org/2000/svg'); 468 }; 469 470 Tour.prototype._isLast = function() { 471 return this._current < this._options.steps.length - 1; 472 }; 473 474 Tour.prototype._showPopover = function(step, i) { 475 var $element, $tip, isOrphan, options; 476 $(".tour-" + this._options.name).remove(); 477 options = $.extend({}, this._options); 478 isOrphan = this._isOrphan(step); 479 step.template = this._template(step, i); 480 if (isOrphan) { 481 step.element = 'body'; 482 step.placement = 'top'; 483 } 484 $element = $(step.element); 485 $element.addClass("tour-" + this._options.name + "-element tour-" + this._options.name + "-" + i + "-element"); 486 if (step.options) { 487 $.extend(options, step.options); 488 } 489 if (step.reflex && !isOrphan) { 490 $element.addClass('tour-step-element-reflex'); 491 $element.off("" + (this._reflexEvent(step.reflex)) + ".tour-" + this._options.name); 492 $element.on("" + (this._reflexEvent(step.reflex)) + ".tour-" + this._options.name, (function(_this) { 493 return function() { 494 if (_this._isLast()) { 495 return _this.next(); 496 } else { 497 return _this.end(); 498 } 499 }; 500 })(this)); 501 } 502 $element.popover({ 503 placement: step.placement, 504 trigger: 'manual', 505 title: step.title, 506 content: step.content, 507 html: true, 508 animation: step.animation, 509 container: step.container, 510 template: step.template, 511 selector: step.element 512 }).popover('show'); 513 $tip = $element.data('bs.popover') ? $element.data('bs.popover').tip() : $element.data('popover').tip(); 514 $tip.attr('id', step.id); 515 this._reposition($tip, step); 516 if (isOrphan) { 517 return this._center($tip); 518 } 519 }; 520 521 Tour.prototype._template = function(step, i) { 522 var $navigation, $next, $prev, $resume, $template; 523 $template = $.isFunction(step.template) ? $(step.template(i, step)) : $(step.template); 524 $navigation = $template.find('.popover-navigation'); 525 $prev = $navigation.find('[data-role="prev"]'); 526 $next = $navigation.find('[data-role="next"]'); 527 $resume = $navigation.find('[data-role="pause-resume"]'); 528 if (this._isOrphan(step)) { 529 $template.addClass('orphan'); 530 } 531 $template.addClass("tour-" + this._options.name + " tour-" + this._options.name + "-" + i); 532 if (step.prev < 0) { 533 $prev.addClass('disabled'); 534 } 535 if (step.next < 0) { 536 $next.addClass('disabled'); 537 } 538 if (!step.duration) { 539 $resume.remove(); 540 } 541 return $template.clone().wrap('<div>').parent().html(); 542 }; 543 544 Tour.prototype._reflexEvent = function(reflex) { 545 if ({}.toString.call(reflex) === '[object Boolean]') { 546 return 'click'; 547 } else { 548 return reflex; 549 } 550 }; 551 552 Tour.prototype._reposition = function($tip, step) { 553 var offsetBottom, offsetHeight, offsetRight, offsetWidth, originalLeft, originalTop, tipOffset; 554 offsetWidth = $tip[0].offsetWidth; 555 offsetHeight = $tip[0].offsetHeight; 556 tipOffset = $tip.offset(); 557 originalLeft = tipOffset.left; 558 originalTop = tipOffset.top; 559 offsetBottom = $(document).outerHeight() - tipOffset.top - $tip.outerHeight(); 560 if (offsetBottom < 0) { 561 tipOffset.top = tipOffset.top + offsetBottom; 562 } 563 offsetRight = $('html').outerWidth() - tipOffset.left - $tip.outerWidth(); 564 if (offsetRight < 0) { 565 tipOffset.left = tipOffset.left + offsetRight; 566 } 567 if (tipOffset.top < 0) { 568 tipOffset.top = 0; 569 } 570 if (tipOffset.left < 0) { 571 tipOffset.left = 0; 572 } 573 $tip.offset(tipOffset); 574 if (step.placement === 'bottom' || step.placement === 'top') { 575 if (originalLeft !== tipOffset.left) { 576 return this._replaceArrow($tip, (tipOffset.left - originalLeft) * 2, offsetWidth, 'left'); 577 } 578 } else { 579 if (originalTop !== tipOffset.top) { 580 return this._replaceArrow($tip, (tipOffset.top - originalTop) * 2, offsetHeight, 'top'); 581 } 582 } 583 }; 584 585 Tour.prototype._center = function($tip) { 586 return $tip.css('top', $(window).outerHeight() / 2 - $tip.outerHeight() / 2); 587 }; 588 589 Tour.prototype._replaceArrow = function($tip, delta, dimension, position) { 590 return $tip.find('.arrow').css(position, delta ? 50 * (1 - delta / dimension) + '%' : ''); 591 }; 592 593 Tour.prototype._scrollIntoView = function(element, callback) { 594 var $element, $window, counter, offsetTop, scrollTop, windowHeight; 595 $element = $(element); 596 if (!$element.length) { 597 return callback(); 598 } 599 $window = $(window); 600 offsetTop = $element.offset().top; 601 windowHeight = $window.height(); 602 scrollTop = Math.max(0, offsetTop - (windowHeight / 2)); 603 this._debug("Scroll into view. ScrollTop: " + scrollTop + ". Element offset: " + offsetTop + ". Window height: " + windowHeight + "."); 604 counter = 0; 605 return $('body, html').stop(true, true).animate({ 606 scrollTop: Math.ceil(scrollTop) 607 }, (function(_this) { 608 return function() { 609 if (++counter === 2) { 610 callback(); 611 return _this._debug("Scroll into view.\nAnimation end element offset: " + ($element.offset().top) + ".\nWindow height: " + ($window.height()) + "."); 612 } 613 }; 614 })(this)); 615 }; 616 617 Tour.prototype._onResize = function(callback, timeout) { 618 return $(window).on("resize.tour-" + this._options.name, function() { 619 clearTimeout(timeout); 620 return timeout = setTimeout(callback, 100); 621 }); 622 }; 623 624 Tour.prototype._initMouseNavigation = function() { 625 var _this; 626 _this = this; 627 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) { 628 return function(e) { 629 e.preventDefault(); 630 return _this.next(); 631 }; 632 })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='prev']", (function(_this) { 633 return function(e) { 634 e.preventDefault(); 635 return _this.prev(); 636 }; 637 })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='end']", (function(_this) { 638 return function(e) { 639 e.preventDefault(); 640 return _this.end(); 641 }; 642 })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='pause-resume']", function(e) { 643 var $this; 644 e.preventDefault(); 645 $this = $(this); 646 $this.text(_this._paused ? $this.data('pause-text') : $this.data('resume-text')); 647 if (_this._paused) { 648 return _this.resume(); 649 } else { 650 return _this.pause(); 651 } 652 }); 653 }; 654 655 Tour.prototype._initKeyboardNavigation = function() { 656 if (!this._options.keyboard) { 657 return; 658 } 659 return $(document).on("keyup.tour-" + this._options.name, (function(_this) { 660 return function(e) { 661 if (!e.which) { 662 return; 663 } 664 switch (e.which) { 665 case 39: 666 e.preventDefault(); 667 if (_this._isLast()) { 668 return _this.next(); 669 } else { 670 return _this.end(); 671 } 672 break; 673 case 37: 674 e.preventDefault(); 675 if (_this._current > 0) { 676 return _this.prev(); 677 } 678 break; 679 case 27: 680 e.preventDefault(); 681 return _this.end(); 682 } 683 }; 684 })(this)); 685 }; 686 687 Tour.prototype._makePromise = function(result) { 688 if (result && $.isFunction(result.then)) { 689 return result; 690 } else { 691 return null; 692 } 693 }; 694 695 Tour.prototype._callOnPromiseDone = function(promise, cb, arg) { 696 if (promise) { 697 return promise.then((function(_this) { 698 return function(e) { 699 return cb.call(_this, arg); 700 }; 701 })(this)); 702 } else { 703 return cb.call(this, arg); 704 } 705 }; 706 707 Tour.prototype._showBackdrop = function(element) { 708 if (this.backdrop.backgroundShown) { 709 return; 710 } 711 this.backdrop = $('<div>', { 712 "class": 'tour-backdrop' 713 }); 714 this.backdrop.backgroundShown = true; 715 return $('body').append(this.backdrop); 716 }; 717 718 Tour.prototype._hideBackdrop = function() { 719 this._hideOverlayElement(); 720 return this._hideBackground(); 721 }; 722 723 Tour.prototype._hideBackground = function() { 724 if (this.backdrop) { 725 this.backdrop.remove(); 726 this.backdrop.overlay = null; 727 return this.backdrop.backgroundShown = false; 728 } 729 }; 730 731 Tour.prototype._showOverlayElement = function(step) { 732 var $element, elementData; 733 $element = $(step.element); 734 if (!$element || $element.length === 0 || this.backdrop.overlayElementShown) { 735 return; 736 } 737 this.backdrop.overlayElementShown = true; 738 this.backdrop.$element = $element.addClass('tour-step-backdrop'); 739 this.backdrop.$background = $('<div>', { 740 "class": 'tour-step-background' 741 }); 742 elementData = { 743 width: $element.innerWidth(), 744 height: $element.innerHeight(), 745 offset: $element.offset() 746 }; 747 this.backdrop.$background.appendTo('body'); 748 if (step.backdropPadding) { 749 elementData = this._applyBackdropPadding(step.backdropPadding, elementData); 750 } 751 return this.backdrop.$background.width(elementData.width).height(elementData.height).offset(elementData.offset); 752 }; 753 754 Tour.prototype._hideOverlayElement = function() { 755 if (!this.backdrop.overlayElementShown) { 756 return; 757 } 758 this.backdrop.$element.removeClass('tour-step-backdrop'); 759 this.backdrop.$background.remove(); 760 this.backdrop.$element = null; 761 this.backdrop.$background = null; 762 return this.backdrop.overlayElementShown = false; 763 }; 764 765 Tour.prototype._applyBackdropPadding = function(padding, data) { 766 if (typeof padding === 'object') { 767 if (padding.top == null) { 768 padding.top = 0; 769 } 770 if (padding.right == null) { 771 padding.right = 0; 772 } 773 if (padding.bottom == null) { 774 padding.bottom = 0; 775 } 776 if (padding.left == null) { 777 padding.left = 0; 778 } 779 data.offset.top = data.offset.top - padding.top; 780 data.offset.left = data.offset.left - padding.left; 781 data.width = data.width + padding.left + padding.right; 782 data.height = data.height + padding.top + padding.bottom; 783 } else { 784 data.offset.top = data.offset.top - padding; 785 data.offset.left = data.offset.left - padding; 786 data.width = data.width + (padding * 2); 787 data.height = data.height + (padding * 2); 788 } 789 return data; 790 }; 791 792 Tour.prototype._clearTimer = function() { 793 window.clearTimeout(this._timer); 794 this._timer = null; 795 return this._duration = null; 796 }; 797 798 return Tour; 799 800 })(); 801 return window.Tour = Tour; 802 })(jQuery, window);