source: extensions/TakeATour/js/custom-bootstrap-tour-standalone.js @ 29154

Last change on this file since 29154 was 28097, checked in by flop25, 10 years ago

every steps move to lang file
script debugged/enhanced

File size: 40.9 KB
Line 
1/* ===========================================================
2# bootstrap-tour - v0.9.0
3# http://bootstraptour.com
4# ==============================================================
5# Copyright 2012-2013 Ulrich Sossou
6#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11#     http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18*/
19/* ========================================================================
20 * Bootstrap: tooltip.js v3.1.0
21 * http://getbootstrap.com/javascript/#tooltip
22 * Inspired by the original jQuery.tipsy by Jason Frame
23 * ========================================================================
24 * Copyright 2011-2014 Twitter, Inc.
25 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
26 * ======================================================================== */
27
28
29+function ($) {
30  'use strict';
31
32  // TOOLTIP PUBLIC CLASS DEFINITION
33  // ===============================
34
35  var Tooltip = function (element, options) {
36    this.type       =
37    this.options    =
38    this.enabled    =
39    this.timeout    =
40    this.hoverState =
41    this.$element   = null
42
43    this.init('tooltip', element, options)
44  }
45
46  Tooltip.DEFAULTS = {
47    animation: true,
48    placement: 'top',
49    selector: false,
50    template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
51    trigger: 'hover focus',
52    title: '',
53    delay: 0,
54    html: false,
55    container: false
56  }
57
58  Tooltip.prototype.init = function (type, element, options) {
59    this.enabled  = true
60    this.type     = type
61    this.$element = $(element)
62    this.options  = this.getOptions(options)
63
64    var triggers = this.options.trigger.split(' ')
65
66    for (var i = triggers.length; i--;) {
67      var trigger = triggers[i]
68
69      if (trigger == 'click') {
70        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
71      } else if (trigger != 'manual') {
72        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
73        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
74
75        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
76        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
77      }
78    }
79
80    this.options.selector ?
81      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
82      this.fixTitle()
83  }
84
85  Tooltip.prototype.getDefaults = function () {
86    return Tooltip.DEFAULTS
87  }
88
89  Tooltip.prototype.getOptions = function (options) {
90    options = $.extend({}, this.getDefaults(), this.$element.data(), options)
91
92    if (options.delay && typeof options.delay == 'number') {
93      options.delay = {
94        show: options.delay,
95        hide: options.delay
96      }
97    }
98
99    return options
100  }
101
102  Tooltip.prototype.getDelegateOptions = function () {
103    var options  = {}
104    var defaults = this.getDefaults()
105
106    this._options && $.each(this._options, function (key, value) {
107      if (defaults[key] != value) options[key] = value
108    })
109
110    return options
111  }
112
113  Tooltip.prototype.enter = function (obj) {
114    var self = obj instanceof this.constructor ?
115      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
116
117    clearTimeout(self.timeout)
118
119    self.hoverState = 'in'
120
121    if (!self.options.delay || !self.options.delay.show) return self.show()
122
123    self.timeout = setTimeout(function () {
124      if (self.hoverState == 'in') self.show()
125    }, self.options.delay.show)
126  }
127
128  Tooltip.prototype.leave = function (obj) {
129    var self = obj instanceof this.constructor ?
130      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
131
132    clearTimeout(self.timeout)
133
134    self.hoverState = 'out'
135
136    if (!self.options.delay || !self.options.delay.hide) return self.hide()
137
138    self.timeout = setTimeout(function () {
139      if (self.hoverState == 'out') self.hide()
140    }, self.options.delay.hide)
141  }
142
143  Tooltip.prototype.show = function () {
144    var e = $.Event('show.bs.' + this.type)
145
146    if (this.hasContent() && this.enabled) {
147      this.$element.trigger(e)
148
149      if (e.isDefaultPrevented()) return
150      var that = this;
151
152      var $tip = this.tip()
153
154      this.setContent()
155
156      if (this.options.animation) $tip.addClass('fade')
157
158      var placement = typeof this.options.placement == 'function' ?
159        this.options.placement.call(this, $tip[0], this.$element[0]) :
160        this.options.placement
161
162      var autoToken = /\s?auto?\s?/i
163      var autoPlace = autoToken.test(placement)
164      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
165
166      $tip
167        .detach()
168        .css({ top: 0, left: 0, display: 'block' })
169        .addClass(placement)
170
171      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
172
173      var pos          = this.getPosition()
174      var actualWidth  = $tip[0].offsetWidth
175      var actualHeight = $tip[0].offsetHeight
176
177      if (autoPlace) {
178        var $parent = this.$element.parent()
179
180        var orgPlacement = placement
181        var docScroll    = document.documentElement.scrollTop || document.body.scrollTop
182        var parentWidth  = this.options.container == 'body' ? window.innerWidth  : $parent.outerWidth()
183        var parentHeight = this.options.container == 'body' ? window.innerHeight : $parent.outerHeight()
184        var parentLeft   = this.options.container == 'body' ? 0 : $parent.offset().left
185
186        placement = placement == 'bottom' && pos.top   + pos.height  + actualHeight - docScroll > parentHeight  ? 'top'    :
187                    placement == 'top'    && pos.top   - docScroll   - actualHeight < 0                         ? 'bottom' :
188                    placement == 'right'  && pos.right + actualWidth > parentWidth                              ? 'left'   :
189                    placement == 'left'   && pos.left  - actualWidth < parentLeft                               ? 'right'  :
190                    placement
191
192        $tip
193          .removeClass(orgPlacement)
194          .addClass(placement)
195      }
196
197      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
198
199      this.applyPlacement(calculatedOffset, placement)
200      this.hoverState = null
201
202      var complete = function() {
203        that.$element.trigger('shown.bs.' + that.type)
204      }
205
206      $.support.transition && this.$tip.hasClass('fade') ?
207        $tip
208          .one($.support.transition.end, complete)
209          .emulateTransitionEnd(150) :
210        complete()
211    }
212  }
213
214  Tooltip.prototype.applyPlacement = function (offset, placement) {
215    var replace
216    var $tip   = this.tip()
217    var width  = $tip[0].offsetWidth
218    var height = $tip[0].offsetHeight
219
220    // manually read margins because getBoundingClientRect includes difference
221    var marginTop = parseInt($tip.css('margin-top'), 10)
222    var marginLeft = parseInt($tip.css('margin-left'), 10)
223
224    // we must check for NaN for ie 8/9
225    if (isNaN(marginTop))  marginTop  = 0
226    if (isNaN(marginLeft)) marginLeft = 0
227
228    offset.top  = offset.top  + marginTop
229    offset.left = offset.left + marginLeft
230
231    // $.fn.offset doesn't round pixel values
232    // so we use setOffset directly with our own function B-0
233    $.offset.setOffset($tip[0], $.extend({
234      using: function (props) {
235        $tip.css({
236          top: Math.round(props.top),
237          left: Math.round(props.left)
238        })
239      }
240    }, offset), 0)
241
242    $tip.addClass('in')
243
244    // check to see if placing tip in new offset caused the tip to resize itself
245    var actualWidth  = $tip[0].offsetWidth
246    var actualHeight = $tip[0].offsetHeight
247
248    if (placement == 'top' && actualHeight != height) {
249      replace = true
250      offset.top = offset.top + height - actualHeight
251    }
252
253    if (/bottom|top/.test(placement)) {
254      var delta = 0
255
256      if (offset.left < 0) {
257        delta       = offset.left * -2
258        offset.left = 0
259
260        $tip.offset(offset)
261
262        actualWidth  = $tip[0].offsetWidth
263        actualHeight = $tip[0].offsetHeight
264      }
265
266      this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
267    } else {
268      this.replaceArrow(actualHeight - height, actualHeight, 'top')
269    }
270
271    if (replace) $tip.offset(offset)
272  }
273
274  Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
275    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
276  }
277
278  Tooltip.prototype.setContent = function () {
279    var $tip  = this.tip()
280    var title = this.getTitle()
281
282    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
283    $tip.removeClass('fade in top bottom left right')
284  }
285
286  Tooltip.prototype.hide = function () {
287    var that = this
288    var $tip = this.tip()
289    var e    = $.Event('hide.bs.' + this.type)
290
291    function complete() {
292      if (that.hoverState != 'in') $tip.detach()
293      that.$element.trigger('hidden.bs.' + that.type)
294    }
295
296    this.$element.trigger(e)
297
298    if (e.isDefaultPrevented()) return
299
300    $tip.removeClass('in')
301
302    $.support.transition && this.$tip.hasClass('fade') ?
303      $tip
304        .one($.support.transition.end, complete)
305        .emulateTransitionEnd(150) :
306      complete()
307
308    this.hoverState = null
309
310    return this
311  }
312
313  Tooltip.prototype.fixTitle = function () {
314    var $e = this.$element
315    if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
316      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
317    }
318  }
319
320  Tooltip.prototype.hasContent = function () {
321    return this.getTitle()
322  }
323
324  Tooltip.prototype.getPosition = function () {
325    var el = this.$element[0]
326    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
327      width: el.offsetWidth,
328      height: el.offsetHeight
329    }, this.$element.offset())
330  }
331
332  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
333    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :
334           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :
335           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
336        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }
337  }
338
339  Tooltip.prototype.getTitle = function () {
340    var title
341    var $e = this.$element
342    var o  = this.options
343
344    title = $e.attr('data-original-title')
345      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
346
347    return title
348  }
349
350  Tooltip.prototype.tip = function () {
351    return this.$tip = this.$tip || $(this.options.template)
352  }
353
354  Tooltip.prototype.arrow = function () {
355    return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
356  }
357
358  Tooltip.prototype.validate = function () {
359    if (!this.$element[0].parentNode) {
360      this.hide()
361      this.$element = null
362      this.options  = null
363    }
364  }
365
366  Tooltip.prototype.enable = function () {
367    this.enabled = true
368  }
369
370  Tooltip.prototype.disable = function () {
371    this.enabled = false
372  }
373
374  Tooltip.prototype.toggleEnabled = function () {
375    this.enabled = !this.enabled
376  }
377
378  Tooltip.prototype.toggle = function (e) {
379    var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this
380    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
381  }
382
383  Tooltip.prototype.destroy = function () {
384    clearTimeout(this.timeout)
385    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
386  }
387
388
389  // TOOLTIP PLUGIN DEFINITION
390  // =========================
391
392  var old = $.fn.tooltip
393
394  $.fn.tooltip = function (option) {
395    return this.each(function () {
396      var $this   = $(this)
397      var data    = $this.data('bs.tooltip')
398      var options = typeof option == 'object' && option
399
400      if (!data && option == 'destroy') return
401      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
402      if (typeof option == 'string') data[option]()
403    })
404  }
405
406  $.fn.tooltip.Constructor = Tooltip
407
408
409  // TOOLTIP NO CONFLICT
410  // ===================
411
412  $.fn.tooltip.noConflict = function () {
413    $.fn.tooltip = old
414    return this
415  }
416
417}(jQuery);
418
419/* ========================================================================
420 * Bootstrap: popover.js v3.1.0
421 * http://getbootstrap.com/javascript/#popovers
422 * ========================================================================
423 * Copyright 2011-2014 Twitter, Inc.
424 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
425 * ======================================================================== */
426
427
428+function ($) {
429  'use strict';
430
431  // POPOVER PUBLIC CLASS DEFINITION
432  // ===============================
433
434  var Popover = function (element, options) {
435    this.init('popover', element, options)
436  }
437
438  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
439
440  Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
441    placement: 'right',
442    trigger: 'click',
443    content: '',
444    template: '<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
445  })
446
447
448  // NOTE: POPOVER EXTENDS tooltip.js
449  // ================================
450
451  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
452
453  Popover.prototype.constructor = Popover
454
455  Popover.prototype.getDefaults = function () {
456    return Popover.DEFAULTS
457  }
458
459  Popover.prototype.setContent = function () {
460    var $tip    = this.tip()
461    var title   = this.getTitle()
462    var content = this.getContent()
463
464    $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
465    $tip.find('.popover-content')[ // we use append for html objects to maintain js events
466      this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
467    ](content)
468
469    $tip.removeClass('fade top bottom left right in')
470
471    // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
472    // this manually by checking the contents.
473    if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
474  }
475
476  Popover.prototype.hasContent = function () {
477    return this.getTitle() || this.getContent()
478  }
479
480  Popover.prototype.getContent = function () {
481    var $e = this.$element
482    var o  = this.options
483
484    return $e.attr('data-content')
485      || (typeof o.content == 'function' ?
486            o.content.call($e[0]) :
487            o.content)
488  }
489
490  Popover.prototype.arrow = function () {
491    return this.$arrow = this.$arrow || this.tip().find('.arrow')
492  }
493
494  Popover.prototype.tip = function () {
495    if (!this.$tip) this.$tip = $(this.options.template)
496    return this.$tip
497  }
498
499
500  // POPOVER PLUGIN DEFINITION
501  // =========================
502
503  var old = $.fn.popover
504
505  $.fn.popover = function (option) {
506    return this.each(function () {
507      var $this   = $(this)
508      var data    = $this.data('bs.popover')
509      var options = typeof option == 'object' && option
510
511      if (!data && option == 'destroy') return
512      if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
513      if (typeof option == 'string') data[option]()
514    })
515  }
516
517  $.fn.popover.Constructor = Popover
518
519
520  // POPOVER NO CONFLICT
521  // ===================
522
523  $.fn.popover.noConflict = function () {
524    $.fn.popover = old
525    return this
526  }
527
528}(jQuery);
529
530(function($, window) {
531  var Tour, document;
532  document = window.document;
533  Tour = (function() {
534    function Tour(options) {
535      this._options = $.extend({
536        name: "tour",
537        steps: [],
538        container: "body",
539        keyboard: true,
540        storage: window.localStorage,
541        debug: false,
542        backdrop: false,
543        redirect: true,
544        orphan: false,
545        duration: false,
546        basePath: "",
547        template: "<div class='popover'>          <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'>&laquo; Prev</button>              <button class='btn btn-sm btn-default' data-role='next'>Next &raquo;</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>",
548        afterSetState: function(key, value) {},
549        afterGetState: function(key, value) {},
550        afterRemoveState: function(key) {},
551        onStart: function(tour) {},
552        onEnd: function(tour) {},
553        onShow: function(tour) {},
554        onShown: function(tour) {},
555        onHide: function(tour) {},
556        onHidden: function(tour) {},
557        onNext: function(tour) {},
558        onPrev: function(tour) {},
559        onPause: function(tour, duration) {},
560        onResume: function(tour, duration) {}
561      }, options);
562      this._force = false;
563      this._inited = false;
564      this.backdrop = {
565        overlay: null,
566        $element: null,
567        $background: null,
568        backgroundShown: false,
569        overlayElementShown: false
570      };
571      this;
572    }
573
574    Tour.prototype.addSteps = function(steps) {
575      var step, _i, _len;
576      for (_i = 0, _len = steps.length; _i < _len; _i++) {
577        step = steps[_i];
578        this.addStep(step);
579      }
580      return this;
581    };
582
583    Tour.prototype.addStep = function(step) {
584      this._options.steps.push(step);
585      return this;
586    };
587
588    Tour.prototype.getStep = function(i) {
589      if (this._options.steps[i] != null) {
590        return $.extend({
591          id: "step-" + i,
592          path: "",
593          placement: "right",
594          title: "",
595          content: "<p></p>",
596          next: i === this._options.steps.length - 1 ? -1 : i + 1,
597          prev: i - 1,
598          animation: true,
599          container: this._options.container,
600          backdrop: this._options.backdrop,
601          redirect: this._options.redirect,
602          orphan: this._options.orphan,
603          duration: this._options.duration,
604          template: this._options.template,
605          onShow: this._options.onShow,
606          onShown: this._options.onShown,
607          onHide: this._options.onHide,
608          onHidden: this._options.onHidden,
609          onNext: this._options.onNext,
610          onPrev: this._options.onPrev,
611          onPause: this._options.onPause,
612          onResume: this._options.onResume
613        }, this._options.steps[i]);
614      }
615    };
616
617    Tour.prototype.init = function(force) {
618      this._force = force;
619      if (this.ended()) {
620        this._debug("Tour ended, init prevented.");
621        return this;
622      }
623      this.setCurrentStep();
624      this._initMouseNavigation();
625      this._initKeyboardNavigation();
626      this._onResize((function(_this) {
627        return function() {
628        return _this.showStep(_this._current);
629        };
630      })(this));
631      if (this._current !== null) {
632        this.showStep(this._current);
633      }
634      this._inited = true;
635      return this;
636    };
637
638    Tour.prototype.start = function(force) {
639      var promise;
640      if (force == null) {
641        force = false;
642      }
643      if (!this._inited) {
644        this.init(force);
645      }
646      if (this._current === null) {
647        promise = this._makePromise(this._options.onStart != null ? this._options.onStart(this) : void 0);
648        this._callOnPromiseDone(promise, this.showStep, 0);
649      }
650      return this;
651    };
652
653    Tour.prototype.next = function() {
654      var promise;
655      promise = this.hideStep(this._current);
656      return this._callOnPromiseDone(promise, this._showNextStep);
657    };
658
659    Tour.prototype.prev = function() {
660      var promise;
661      promise = this.hideStep(this._current);
662      return this._callOnPromiseDone(promise, this._showPrevStep);
663    };
664
665    Tour.prototype.goTo = function(i) {
666      var promise;
667      promise = this.hideStep(this._current);
668      return this._callOnPromiseDone(promise, this.showStep, i);
669    };
670
671    Tour.prototype.end = function() {
672      var endHelper, promise;
673      endHelper = (function(_this) {
674        return function(e) {
675        $(document).off("click.tour-" + _this._options.name);
676        $(document).off("keyup.tour-" + _this._options.name);
677        $(window).off("resize.tour-" + _this._options.name);
678        _this._setState("end", "yes");
679        _this._inited = false;
680        _this._force = false;
681        _this._clearTimer();
682        if (_this._options.onEnd != null) {
683          return _this._options.onEnd(_this);
684        }
685      };
686      })(this);
687      promise = this.hideStep(this._current);
688      return this._callOnPromiseDone(promise, endHelper);
689    };
690
691    Tour.prototype.ended = function() {
692      return !this._force && !!this._getState("end");
693    };
694
695    Tour.prototype.restart = function() {
696      this._removeState("current_step");
697      this._removeState("end");
698      this.setCurrentStep(0);
699      return this.start();
700    };
701
702    Tour.prototype.pause = function() {
703      var step;
704      step = this.getStep(this._current);
705      if (!(step && step.duration)) {
706        return this;
707      }
708      this._paused = true;
709      this._duration -= new Date().getTime() - this._start;
710      window.clearTimeout(this._timer);
711      this._debug("Paused/Stopped step " + (this._current + 1) + " timer (" + this._duration + " remaining).");
712      if (step.onPause != null) {
713        return step.onPause(this, this._duration);
714      }
715    };
716
717    Tour.prototype.resume = function() {
718      var step;
719      step = this.getStep(this._current);
720      if (!(step && step.duration)) {
721        return this;
722      }
723      this._paused = false;
724      this._start = new Date().getTime();
725      this._duration = this._duration || step.duration;
726      this._timer = window.setTimeout((function(_this) {
727        return function() {
728        if (_this._isLast()) {
729          return _this.next();
730        } else {
731          return _this.end();
732        }
733        };
734      })(this), this._duration);
735      this._debug("Started step " + (this._current + 1) + " timer with duration " + this._duration);
736      if ((step.onResume != null) && this._duration !== step.duration) {
737        return step.onResume(this, this._duration);
738      }
739    };
740
741    Tour.prototype.hideStep = function(i) {
742      var hideStepHelper, promise, step;
743      step = this.getStep(i);
744      if (!step) {
745        return;
746      }
747      this._clearTimer();
748      promise = this._makePromise(step.onHide != null ? step.onHide(this, i) : void 0);
749      hideStepHelper = (function(_this) {
750        return function(e) {
751        var $element;
752        $element = $(step.element);
753        if (!($element.data("bs.popover") || $element.data("popover"))) {
754          $element = $("body");
755        }
756          $element.popover("destroy").removeClass("tour-" + _this._options.name + "-element tour-" + _this._options.name + "-" + i + "-element");
757        if (step.reflex) {
758          $element.css("cursor", "").off("click.tour-" + _this._options.name);
759        }
760        if (step.backdrop) {
761          _this._hideBackdrop();
762        }
763        if (step.onHidden != null) {
764          return step.onHidden(_this);
765        }
766      };
767      })(this);
768      this._callOnPromiseDone(promise, hideStepHelper);
769      return promise;
770    };
771
772    Tour.prototype.showStep = function(i) {
773      var promise, showStepHelper, skipToPrevious, step;
774      if (this.ended()) {
775        this._debug("Tour ended, showStep prevented.");
776        return this;
777      }
778      step = this.getStep(i);
779      if (!step) {
780        return;
781      }
782      skipToPrevious = i < this._current;
783      promise = this._makePromise(step.onShow != null ? step.onShow(this, i) : void 0);
784      showStepHelper = (function(_this) {
785        return function(e) {
786        var current_path, path;
787        _this.setCurrentStep(i);
788        path = (function() {
789            switch ({}.toString.call(step.path)) {
790            case "[object Function]":
791              return step.path();
792            case "[object String]":
793              return this._options.basePath + step.path;
794            default:
795              return step.path;
796          }
797        }).call(_this);
798        current_path = document.location.href;
799        if (_this._isRedirect(path, current_path)) {
800          if (toString.call(path) === "[object RegExp]") {
801            _this._redirect(step, path);
802          }
803          else {
804            path = document.location.protocol+'//'+path;
805            _this._redirect(step, path);
806          }
807          return;
808        }
809        if (_this._isOrphan(step)) {
810          if (!step.orphan) {
811            _this._debug("Skip the orphan step " + (_this._current + 1) + ". Orphan option is false and the element doesn't exist or is hidden.");
812            if (skipToPrevious) {
813              _this._showPrevStep();
814            } else {
815              _this._showNextStep();
816            }
817            return;
818          }
819          _this._debug("Show the orphan step " + (_this._current + 1) + ". Orphans option is true.");
820        }
821        if (step.title  === "" & step.content  === "") {
822            if (skipToPrevious) {
823              _this._showPrevStep();
824            } else {
825              _this._showNextStep();
826            }
827            return;
828        }
829        if (step.backdrop) {
830          _this._showBackdrop(!_this._isOrphan(step) ? step.element : void 0);
831        }
832        _this._scrollIntoView(step.element, function() {
833          if ((step.element != null) && step.backdrop) {
834            _this._showOverlayElement(step.element);
835          }
836          _this._showPopover(step, i);
837          if (step.onShown != null) {
838            step.onShown(_this);
839          }
840          return _this._debug("Step " + (_this._current + 1) + " of " + _this._options.steps.length);
841        });
842        if (step.duration) {
843          return _this.resume();
844        }
845      };
846      })(this);
847      this._callOnPromiseDone(promise, showStepHelper);
848      return promise;
849    };
850
851    Tour.prototype.getCurrentStep = function() {
852      return this._current;
853    };
854
855    Tour.prototype.setCurrentStep = function(value) {
856      if (value != null) {
857        this._current = value;
858        this._setState("current_step", value);
859      } else {
860        this._current = this._getState("current_step");
861        this._current = this._current === null ? null : parseInt(this._current, 10);
862      }
863      return this;
864    };
865
866    Tour.prototype._setState = function(key, value) {
867      var e, keyName;
868      if (this._options.storage) {
869        keyName = "" + this._options.name + "_" + key;
870        try {
871          this._options.storage.setItem(keyName, value);
872        } catch (_error) {
873          e = _error;
874          if (e.code === DOMException.QUOTA_EXCEEDED_ERR) {
875            this.debug("LocalStorage quota exceeded. State storage failed.");
876          }
877        }
878        return this._options.afterSetState(keyName, value);
879      } else {
880        if (this._state == null) {
881          this._state = {};
882        }
883        return this._state[key] = value;
884      }
885    };
886
887    Tour.prototype._removeState = function(key) {
888      var keyName;
889      if (this._options.storage) {
890        keyName = "" + this._options.name + "_" + key;
891        this._options.storage.removeItem(keyName);
892        return this._options.afterRemoveState(keyName);
893      } else {
894        if (this._state != null) {
895          return delete this._state[key];
896        }
897      }
898    };
899
900    Tour.prototype._getState = function(key) {
901      var keyName, value;
902      if (this._options.storage) {
903        keyName = "" + this._options.name + "_" + key;
904        value = this._options.storage.getItem(keyName);
905      } else {
906        if (this._state != null) {
907          value = this._state[key];
908        }
909      }
910      if (value === void 0 || value === "null") {
911        value = null;
912      }
913      this._options.afterGetState(key, value);
914      return value;
915    };
916
917    Tour.prototype._showNextStep = function() {
918      var promise, showNextStepHelper, step;
919      step = this.getStep(this._current);
920      showNextStepHelper = (function(_this) {
921        return function(e) {
922        return _this.showStep(step.next);
923      };
924      })(this);
925      promise = this._makePromise(step.onNext != null ? step.onNext(this) : void 0);
926      return this._callOnPromiseDone(promise, showNextStepHelper);
927    };
928
929    Tour.prototype._showPrevStep = function() {
930      var promise, showPrevStepHelper, step;
931      step = this.getStep(this._current);
932      showPrevStepHelper = (function(_this) {
933        return function(e) {
934        return _this.showStep(step.prev);
935      };
936      })(this);
937      promise = this._makePromise(step.onPrev != null ? step.onPrev(this) : void 0);
938      return this._callOnPromiseDone(promise, showPrevStepHelper);
939    };
940
941    Tour.prototype._debug = function(text) {
942      if (this._options.debug) {
943        return window.console.log("Bootstrap Tour '" + this._options.name + "' | " + text);
944      }
945    };
946
947    Tour.prototype._isRedirect = function(path, currentPath) {
948      return (path != null) && path !== "" && ((toString.call(path) === "[object RegExp]" && !path.test(currentPath)) || (toString.call(path) === "[object String]" && path !== currentPath.replace("http://", "").replace("https://", "")));
949    };
950
951    Tour.prototype._redirect = function(step, path) {
952      if ($.isFunction(step.redirect)) {
953        return step.redirect.call(this, path);
954      } else if (step.redirect === true) {
955        this._debug("Redirect to " + path);
956        return document.location.href = path;
957      }
958    };
959
960    Tour.prototype._isOrphan = function(step) {
961      return (step.element == null) || !$(step.element).length || $(step.element).is(":hidden") && ($(step.element)[0].namespaceURI !== "http://www.w3.org/2000/svg");
962    };
963
964    Tour.prototype._isLast = function() {
965      return this._current < this._options.steps.length - 1;
966    };
967
968    Tour.prototype._showPopover = function(step, i) {
969      var $element, $navigation, $template, $tip, isOrphan, options;
970      options = $.extend({}, this._options);
971      $template = $.isFunction(step.template) ? $(step.template(i, step)) : $(step.template);
972      $navigation = $template.find(".popover-navigation");
973      isOrphan = this._isOrphan(step);
974      if (isOrphan) {
975        step.element = "body";
976        step.placement = "top";
977        $template = $template.addClass("orphan");
978      }
979      $element = $(step.element);
980      $template.addClass("tour-" + this._options.name + " tour-" + this._options.name + "-" + i);
981      $element.addClass("tour-" + this._options.name + "-element tour-" + this._options.name + "-" + i + "-element");
982      if (step.options) {
983        $.extend(options, step.options);
984      }
985      if (step.reflex & !isOrphan) {
986        $element.css("cursor", "pointer").on("click.tour-" + this._options.name, (function(_this) {
987          return function() {
988          if (_this._isLast()) {
989            return _this.next();
990          } else {
991            return _this.end();
992          }
993          };
994        })(this));
995      }
996      if (step.prev < 0) {
997        $navigation.find("[data-role='prev']").addClass("disabled");
998      }
999      if (step.next < 0) {
1000        $navigation.find("[data-role='next']").addClass("disabled");
1001      }
1002      if (!step.duration) {
1003        $navigation.find("[data-role='pause-resume']").remove();
1004      }
1005      step.template = $template.clone().wrap("<div>").parent().html();
1006      $element.popover({
1007        placement: step.placement,
1008        trigger: "manual",
1009        title: step.title,
1010        content: step.content,
1011        html: true,
1012        animation: step.animation,
1013        container: step.container,
1014        template: step.template,
1015        selector: step.element
1016      }).popover("show");
1017      $tip = $element.data("bs.popover") ? $element.data("bs.popover").tip() : $element.data("popover").tip();
1018      $tip.attr("id", step.id);
1019      this._reposition($tip, step);
1020      if (isOrphan) {
1021        return this._center($tip);
1022      }
1023    };
1024
1025    Tour.prototype._reposition = function($tip, step) {
1026      var offsetBottom, offsetHeight, offsetRight, offsetWidth, originalLeft, originalTop, tipOffset;
1027      offsetWidth = $tip[0].offsetWidth;
1028      offsetHeight = $tip[0].offsetHeight;
1029      tipOffset = $tip.offset();
1030      originalLeft = tipOffset.left;
1031      originalTop = tipOffset.top;
1032      offsetBottom = $(document).outerHeight() - tipOffset.top - $tip.outerHeight();
1033      if (offsetBottom < 0) {
1034        tipOffset.top = tipOffset.top + offsetBottom;
1035      }
1036      offsetRight = $("html").outerWidth() - tipOffset.left - $tip.outerWidth();
1037      if (offsetRight < 0) {
1038        tipOffset.left = tipOffset.left + offsetRight;
1039      }
1040      if (tipOffset.top < 0) {
1041        tipOffset.top = 0;
1042      }
1043      if (tipOffset.left < 0) {
1044        tipOffset.left = 0;
1045      }
1046      $tip.offset(tipOffset);
1047      if (step.placement === "bottom" || step.placement === "top") {
1048        if (originalLeft !== tipOffset.left) {
1049          return this._replaceArrow($tip, (tipOffset.left - originalLeft) * 2, offsetWidth, "left");
1050        }
1051      } else {
1052        if (originalTop !== tipOffset.top) {
1053          return this._replaceArrow($tip, (tipOffset.top - originalTop) * 2, offsetHeight, "top");
1054        }
1055      }
1056    };
1057
1058    Tour.prototype._center = function($tip) {
1059      return $tip.css("top", $(window).outerHeight() / 2 - $tip.outerHeight() / 2);
1060    };
1061
1062    Tour.prototype._replaceArrow = function($tip, delta, dimension, position) {
1063      return $tip.find(".arrow").css(position, delta ? 50 * (1 - delta / dimension) + "%" : "");
1064    };
1065
1066    Tour.prototype._scrollIntoView = function(element, callback) {
1067      var $element, $window, counter, offsetTop, scrollTop, windowHeight;
1068      $element = $(element);
1069      if (!$element.length) {
1070        return callback();
1071      }
1072      $window = $(window);
1073      offsetTop = $element.offset().top;
1074      windowHeight = $window.height();
1075      scrollTop = Math.max(0, offsetTop - (windowHeight / 2));
1076      this._debug("Scroll into view. ScrollTop: " + scrollTop + ". Element offset: " + offsetTop + ". Window height: " + windowHeight + ".");
1077      counter = 0;
1078      return $("body,html").stop(true, true).animate({
1079        scrollTop: Math.ceil(scrollTop)
1080      }, (function(_this) {
1081        return function() {
1082        if (++counter === 2) {
1083          callback();
1084          return _this._debug("Scroll into view. Animation end element offset: " + ($element.offset().top) + ". Window height: " + ($window.height()) + ".");
1085        }
1086        };
1087      })(this));
1088    };
1089
1090    Tour.prototype._onResize = function(callback, timeout) {
1091      return $(window).on("resize.tour-" + this._options.name, function() {
1092        clearTimeout(timeout);
1093        return timeout = setTimeout(callback, 100);
1094      });
1095    };
1096
1097    Tour.prototype._initMouseNavigation = function() {
1098      var _this;
1099      _this = this;
1100      return $(document).off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='prev']:not(.disabled)").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='next']:not(.disabled)").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']:not(.disabled)", (function(_this) {
1101        return function(e) {
1102        e.preventDefault();
1103        return _this.next();
1104        };
1105      })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='prev']:not(.disabled)", (function(_this) {
1106        return function(e) {
1107        e.preventDefault();
1108        return _this.prev();
1109        };
1110      })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='end']", (function(_this) {
1111        return function(e) {
1112        e.preventDefault();
1113        return _this.end();
1114        };
1115      })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='pause-resume']", function(e) {
1116        var $this;
1117        e.preventDefault();
1118        $this = $(this);
1119        $this.text(_this._paused ? $this.data("pause-text") : $this.data("resume-text"));
1120        if (_this._paused) {
1121          return _this.resume();
1122        } else {
1123          return _this.pause();
1124        }
1125      });
1126    };
1127
1128    Tour.prototype._initKeyboardNavigation = function() {
1129      if (!this._options.keyboard) {
1130        return;
1131      }
1132      return $(document).on("keyup.tour-" + this._options.name, (function(_this) {
1133        return function(e) {
1134        if (!e.which) {
1135          return;
1136        }
1137        switch (e.which) {
1138          case 39:
1139            e.preventDefault();
1140            if (_this._isLast()) {
1141              return _this.next();
1142            } else {
1143              return _this.end();
1144            }
1145            break;
1146          case 37:
1147            e.preventDefault();
1148            if (_this._current > 0) {
1149              return _this.prev();
1150            }
1151            break;
1152          case 27:
1153            e.preventDefault();
1154            return _this.end();
1155        }
1156        };
1157      })(this));
1158    };
1159
1160    Tour.prototype._makePromise = function(result) {
1161      if (result && $.isFunction(result.then)) {
1162        return result;
1163      } else {
1164        return null;
1165      }
1166    };
1167
1168    Tour.prototype._callOnPromiseDone = function(promise, cb, arg) {
1169      if (promise) {
1170        return promise.then((function(_this) {
1171          return function(e) {
1172          return cb.call(_this, arg);
1173          };
1174        })(this));
1175      } else {
1176        return cb.call(this, arg);
1177      }
1178    };
1179
1180    Tour.prototype._showBackdrop = function(element) {
1181      if (this.backdrop.backgroundShown) {
1182        return;
1183      }
1184      this.backdrop = $("<div/>", {
1185        "class": "tour-backdrop"
1186      });
1187      this.backdrop.backgroundShown = true;
1188      return $("body").append(this.backdrop);
1189    };
1190
1191    Tour.prototype._hideBackdrop = function() {
1192      this._hideOverlayElement();
1193      return this._hideBackground();
1194    };
1195
1196    Tour.prototype._hideBackground = function() {
1197      this.backdrop.remove();
1198      this.backdrop.overlay = null;
1199      return this.backdrop.backgroundShown = false;
1200    };
1201
1202    Tour.prototype._showOverlayElement = function(element) {
1203      var $background, $element, offset;
1204      $element = $(element);
1205      if (!$element || $element.length === 0 || this.backdrop.overlayElementShown) {
1206        return;
1207      }
1208      this.backdrop.overlayElementShown = true;
1209      $background = $("<div/>");
1210      offset = $element.offset();
1211      offset.top = offset.top;
1212      offset.left = offset.left;
1213      $background.width($element.innerWidth()).height($element.innerHeight()).addClass("tour-step-background").offset(offset);
1214      $element.addClass("tour-step-backdrop");
1215      $("body").append($background);
1216      this.backdrop.$element = $element;
1217      return this.backdrop.$background = $background;
1218    };
1219
1220    Tour.prototype._hideOverlayElement = function() {
1221      if (!this.backdrop.overlayElementShown) {
1222        return;
1223      }
1224      this.backdrop.$element.removeClass("tour-step-backdrop");
1225      this.backdrop.$background.remove();
1226      this.backdrop.$element = null;
1227      this.backdrop.$background = null;
1228      return this.backdrop.overlayElementShown = false;
1229    };
1230
1231    Tour.prototype._clearTimer = function() {
1232      window.clearTimeout(this._timer);
1233      this._timer = null;
1234      return this._duration = null;
1235    };
1236
1237    return Tour;
1238
1239  })();
1240  return window.Tour = Tour;
1241})(jQuery, window);
Note: See TracBrowser for help on using the repository browser.