Вход Регистрация
Файл: concrete5.7.5.6/concrete/js/build/vendor/tourist/tourist.js
Строк: 1212
<?php
(function() {
  var 
_ref, _ref1, _ref2, _ref3,
    
__hasProp = {}.hasOwnProperty,
    
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

  
window.Tourist = window.Tourist || {};

  
/*
  A model for the Tour. We'll only use the 'current_step' property.
  */


  
Tourist.Model = (function(_super) {
    
__extends(Model, _super);

    function 
Model() {
      
_ref = Model.__super__.constructor.apply(this, arguments);
      return 
_ref;
    }

    
Model.prototype._module = 'Tourist';

    return 
Model;

  })(
Backbone.Model);

  
window.Tourist.Tip = window.Tourist.Tip || {};

  
/*
  The flyout showing the content of each step.
  
  This is the base class containing most of the logic. Can extend for different
  tooltip implementations.
  */


  
Tourist.Tip.Base = (function() {
    
Base.prototype._module = 'Tourist';

    
_.extend(Base.prototype, Backbone.Events);
/* concrete5 */
    /*
    Base.prototype.skipButtonTemplate = '<button class="btn btn-default btn-sm pull-right tour-next">Skip this step →</button>';

    Base.prototype.nextButtonTemplate = '<button class="btn btn-primary btn-sm pull-right tour-next">Next step →</button>';

    Base.prototype.finalButtonTemplate = '<button class="btn btn-primary btn-sm pull-right tour-next">Finish up</button>';

    Base.prototype.closeButtonTemplate = '<a class="btn btn-close tour-close" href="#"><i class="icon icon-remove"></i></a>';

    Base.prototype.okButtonTemplate = '<button class="btn btn-sm tour-close btn-primary">Okay</button>';
  */
    
Base.prototype.skipButtonTemplate = ccmi18n_tourist.skipButton;

    
Base.prototype.nextButtonTemplate = ccmi18n_tourist.nextButton;

    
Base.prototype.finalButtonTemplate = ccmi18n_tourist.finalButton;

    
Base.prototype.closeButtonTemplate = ccmi18n_tourist.closeButton;

    
Base.prototype.okButtonTemplate = ccmi18n_tourist.okButton;
/* end concrete5 */

    
Base.prototype.actionLabelTemplate = _.template('<h4 class="action-label"><%= label %></h4>');

/* concrete5 */
    //Base.prototype.actionLabels = ['Do this:', 'Then this:', 'Next this:'];
    
Base.prototype.actionLabels = [ccmi18n_tourist.doThis, ccmi18n_tourist.thenThis, ccmi18n_tourist.nextThis];
/* end concrete5 */

    
Base.prototype.highlightClass = 'tour-highlight';

    
Base.prototype.template = _.template('<div>n  <div class="tour-container">n    <%= close_button %>n    <%= content %>n    <p class="tour-counter <%= counter_class %>"><%= counter%></p>n  </div>n  <div class="tour-buttons">n    <%= buttons %>n  </div>n</div>');

    function 
Base(options) {
      
this.options = options != null ? options : {};
      
this.onClickNext = __bind(this.onClickNext, this);
      
this.onClickClose = __bind(this.onClickClose, this);
      
this.el = $('<div/>');
      
this.initialize(options);
      
this._bindClickEvents();
      
Tourist.Tip.Base._cacheTip(this);
    }

    
Base.prototype.destroy = function() {
      return 
this.el.remove();
    };

    
Base.prototype.render = function(step) {
      
this.hide();
      if (
step) {
        
this._setTarget(step.target || false, step);
        
this._setZIndex('');
        
this._renderContent(step, this._buildContentElement(step));
        if (
step.target) {
          
this.show();
        }
        if (
step.zIndex) {
          
this._setZIndex(step.zIndex, step);
        }
      }
      return 
this;
    };

    
Base.prototype.show = function() {};

    
Base.prototype.hide = function() {};

    
Base.prototype.setTarget = function(targetElement, step) {
      return 
this._setTarget(targetElement, step);
    };

    
Base.prototype.cleanupCurrentTarget = function() {
      if (
this.target && this.target.removeClass) {
        
this.target.removeClass(this.highlightClass);
      }
      return 
this.target = null;
    };

    
/*
    Event Handlers
    */


    
Base.prototype.onClickClose = function(event) {
      
this.trigger('click:close', this, event);
      return 
false;
    };

    
Base.prototype.onClickNext = function(event) {
      
this.trigger('click:next', this, event);
      return 
false;
    };

    
/*
    Private
    */


    
Base.prototype._getTipElement = function() {};

    
Base.prototype._renderContent = function(step, contentElement) {};

    
Base.prototype._bindClickEvents = function() {
      var 
el;
      
el = this._getTipElement();
      
el.delegate('.tour-close', 'click', this.onClickClose);
      return 
el.delegate('.tour-next', 'click', this.onClickNext);
    };

    
Base.prototype._setTarget = function(target, step) {
      
this.cleanupCurrentTarget();
      if (
target && step && step.highlightTarget) {
        
target.addClass(this.highlightClass);
      }
      return 
this.target = target;
    };

    
Base.prototype._setZIndex = function(zIndex) {
      var 
el;
      
el = this._getTipElement();
      return 
el.css('z-index', zIndex || '');
    };

    
Base.prototype._buildContentElement = function(step) {
      var 
buttons, content;
      
buttons = this._buildButtons(step);
      
content = $($.parseHTML(this.template({
        
content: step.content,
        
buttons: buttons,
        
close_button: this._buildCloseButton(step),
/* concrete5 */
        //counter: step.final ? '' : "step " + (step.index + 1) + " of " + step.total,
        
counter: step.final ? '' : ccmi18n_tourist.stepXofY.replace(/%1$d/g, step.index + 1).replace(/%2$d/g, step.total),
/* end concrete5 */
        
counter_class: step.final ? 'final' : ''
      
})));
      if (!
buttons) {
        
content.find('.tour-buttons').addClass('no-buttons');
      }
      
this._renderActionLabels(content);
      return 
content;
    };

    
Base.prototype._buildButtons = function(step) {
      var 
buttons;
      
buttons = '';
      if (
step.okButton) {
        
buttons += this.okButtonTemplate;
      }
      if (
step.skipButton) {
        
buttons += this.skipButtonTemplate;
      }
      if (
step.nextButton) {
        
buttons += step.final ? this.finalButtonTemplate : this.nextButtonTemplate;
      }
      return 
buttons;
    };

    
Base.prototype._buildCloseButton = function(step) {
      if (
step.closeButton) {
        return 
this.closeButtonTemplate;
      } else {
        return 
'';
      }
    };

    
Base.prototype._renderActionLabels = function(el) {
      var 
action, actionIndex, actions, label, _i, _len, _results;
      
actions = el.find('.action');
      
actionIndex = 0;
      
_results = [];
      for (
_i = 0, _len = actions.length; _i < _len; _i++) {
        
action = actions[_i];
        
label = $($.parseHTML(this.actionLabelTemplate({
          
label: this.actionLabels[actionIndex]
        })));
        
label.insertBefore(action);
        
_results.push(actionIndex++);
      }
      return 
_results;
    };

    
Base._cacheTip = function(tip) {
      if (!
Tourist.Tip.Base._cachedTips) {
        
Tourist.Tip.Base._cachedTips = [];
      }
      return 
Tourist.Tip.Base._cachedTips.push(tip);
    };

    
Base.destroy = function() {
      var 
tip, _i, _len, _ref1;
      if (!
Tourist.Tip.Base._cachedTips) {
        return;
      }
      
_ref1 = Tourist.Tip.Base._cachedTips;
      for (
_i = 0, _len = _ref1.length; _i < _len; _i++) {
        
tip = _ref1[_i];
        
tip.destroy();
      }
      return 
Tourist.Tip.Base._cachedTips = null;
    };

    return 
Base;

  })();

  
/*
  Bootstrap based tip implementation
  */


  
Tourist.Tip.Bootstrap = (function(_super) {
    
__extends(Bootstrap, _super);

    function 
Bootstrap() {
      
_ref1 = Bootstrap.__super__.constructor.apply(this, arguments);
      return 
_ref1;
    }

    
Bootstrap.prototype.initialize = function(options) {
      var 
defs;
      
defs = {
        
showEffect: null,
        
hideEffect: null
      
};
      
this.options = _.extend(defs, options);
      return 
this.tip = new Tourist.Tip.BootstrapTip(this.options);
    };

    
Bootstrap.prototype.destroy = function() {
      
this.tip.destroy();
      return 
Bootstrap.__super__.destroy.call(this);
    };

    
Bootstrap.prototype.show = function() {
      var 
fn;
      if (
this.options.showEffect) {
        
fn = Tourist.Tip.Bootstrap.effects[this.options.showEffect];
        return 
fn.call(this, this.tip, this.tip.el);
      } else {
        return 
this.tip.show();
      }
    };

    
Bootstrap.prototype.hide = function() {
      var 
fn;
      if (
this.options.hideEffect) {
        
fn = Tourist.Tip.Bootstrap.effects[this.options.hideEffect];
        return 
fn.call(this, this.tip, this.tip.el);
      } else {
        return 
this.tip.hide();
      }
    };

    
/*
    Private
    */


    
Bootstrap.prototype._getTipElement = function() {
      return 
this.tip.el;
    };

    
Bootstrap.prototype._setTarget = function(target, step) {
      
Bootstrap.__super__._setTarget.call(this, target, step);
      return 
this.tip.setTarget(target);
    };

    
Bootstrap.prototype._renderContent = function(step, contentElement) {
      var 
at, my;
      
my = step.my || 'left center';
      
at = step.at || 'right center';
      
/* concrete5 */
      //this.tip.setContainer(step.container || $('body'));
      
this.tip.setContainer(step.container || $('#ccm-tooltip-holder'));
      
/* end concrete5 */
      
this.tip.setContent(contentElement);
      return 
this.tip.setPosition(step.target || false, my, at);
    };

    return 
Bootstrap;

  })(
Tourist.Tip.Base);

  
Tourist.Tip.Bootstrap.effects = {
    
slidein: function(tip, element) {
      var 
OFFSETS, css, easing, easings, offset, side, value, _i, _len;
      
OFFSETS = {
        
top: 80,
        
left: 80,
        
right: -80,
        
bottom: -80
      
};
      
side = tip.my.split(' ')[0];
      
side = side || 'top';
      
offset = OFFSETS[side];
      if (
side === 'bottom') {
        
side = 'top';
      }
      if (
side === 'right') {
        
side = 'left';
      }
      
value = parseInt(element.css(side));
      
element.stop();
      
css = {};
      
css[side] = value + offset;
      
element.css(css);
      
element.show();
      
css[side] = value;
      
easings = ['easeOutCubic', 'swing', 'linear'];
      for (
_i = 0, _len = easings.length; _i < _len; _i++) {
        
easing = easings[_i];
        if ($.
easing[easing]) {
          break;
        }
      }
      
element.animate(css, 300, easing);
      return 
null;
    }
  };

  
/*
  Simple implementation of tooltip with bootstrap markup.
  
  Almost entirely deals with positioning. Uses the similar method for
  positioning as qtip2:
  
    my: 'top center'
    at: 'bottom center'
  */


  
Tourist.Tip.BootstrapTip = (function() {
    
BootstrapTip.prototype.template = '<div class="popover tourist-popover">n  <div class="arrow"></div>n  <div class="popover-content"></div>n</div>';

    
BootstrapTip.prototype.FLIP_POSITION = {
      
bottom: 'top',
      
top: 'bottom',
      
left: 'right',
      
right: 'left'
    
};

    function 
BootstrapTip(options) {
      var 
defs;
      
defs = {
        
offset: 10,
        
tipOffset: 10
      
};
      
this.options = _.extend(defs, options);
      
this.el = $($.parseHTML(this.template));
      
this.hide();
    }

    
BootstrapTip.prototype.destroy = function() {
      return 
this.el.remove();
    };

    
BootstrapTip.prototype.show = function() {
      return 
this.el.show().addClass('visible');
    };

    
BootstrapTip.prototype.hide = function() {
      return 
this.el.hide().removeClass('visible');
    };

    
BootstrapTip.prototype.setTarget = function(target) {
      
this.target = target;
      return 
this._setPosition(this.target, this.my, this.at);
    };

    
BootstrapTip.prototype.setPosition = function(target, my, at) {
      
this.target = target;
      
this.my = my;
      
this.at = at;
      return 
this._setPosition(this.target, this.my, this.at);
    };

    
BootstrapTip.prototype.setContainer = function(container) {
      return 
container.append(this.el);
    };

    
BootstrapTip.prototype.setContent = function(content) {
      return 
this._getContentElement().html(content);
    };

    
/*
    Private
    */


    
BootstrapTip.prototype._getContentElement = function() {
      return 
this.el.find('.popover-content');
    };

    
BootstrapTip.prototype._getTipElement = function() {
      return 
this.el.find('.arrow');
    };

    
BootstrapTip.prototype._setPosition = function(target, my, at) {
      var 
clas, css, originalDisplay, position, shift, targetPosition, tip, tipOffset, tipPosition, _ref2;
      if (
my == null) {
        
my = 'left center';
      }
      if (
at == null) {
        
at = 'right center';
      }
      if (!
target) {
        return;
      }
      
_ref2 = my.split(' '), clas = _ref2[0], shift = _ref2[1];
      
originalDisplay = this.el.css('display');
      
this.el.css({
        
top: 0,
        
left: 0,
        
margin: 0,
        
display: 'block'
      
}).removeClass('top').removeClass('bottom').removeClass('left').removeClass('right').addClass(this.FLIP_POSITION[clas]);
      if (!
target) {
        return;
      }
      
tip = this._getTipElement().css({
        
left: '',
        
right: '',
        
top: '',
        
bottom: ''
      
});
      if (
shift !== 'center') {
        
tipOffset = {
          
left: tip[0].offsetWidth / 2,
          
right: 0,
          
top: tip[0].offsetHeight / 2,
          
bottom: 0
        
};
        
css = {};
        
css[shift] = tipOffset[shift] + this.options.tipOffset;
        
css[this.FLIP_POSITION[shift]] = 'auto';
        
tip.css(css);
      }
      
targetPosition = this._caculateTargetPosition(at, target);
      
tipPosition = this._caculateTipPosition(my, targetPosition);
      
position = this._adjustForArrow(my, tipPosition);
      
this.el.css(position);
      return 
this.el.css({
        
display: originalDisplay
      
});
    };

    
BootstrapTip.prototype._caculateTargetPosition = function(atPosition, target) {
      var 
bounds, pos;
      if (
Object.prototype.toString.call(target) === '[object Array]') {
        return {
          
left: target[0],
          
top: target[1]
        };
      }
      
bounds = this._getTargetBounds(target);
      
pos = this._lookupPosition(atPosition, bounds.width, bounds.height);
      return {
        
left: bounds.left + pos[0],
        
top: bounds.top + pos[1]
      };
    };

    
BootstrapTip.prototype._caculateTipPosition = function(myPosition, targetPosition) {
      var 
height, pos, width;
      
width = this.el[0].offsetWidth;
      
height = this.el[0].offsetHeight;
      
pos = this._lookupPosition(myPosition, width, height);
      return {
        
left: targetPosition.left - pos[0],
        
top: targetPosition.top - pos[1]
      };
    };

    
BootstrapTip.prototype._adjustForArrow = function(myPosition, tipPosition) {
      var 
clas, height, position, shift, tip, width, _ref2;
      
_ref2 = myPosition.split(' '), clas = _ref2[0], shift = _ref2[1];
      
tip = this._getTipElement();
      
width = tip[0].offsetWidth;
      
height = tip[0].offsetHeight;
      
position = {
        
top: tipPosition.top,
        
left: tipPosition.left
      
};
      switch (
clas) {
        case 
'top':
          
position.top += height + this.options.offset;
          break;
        case 
'bottom':
          
position.top -= height + this.options.offset;
          break;
        case 
'left':
          
position.left += width + this.options.offset;
          break;
        case 
'right':
          
position.left -= width + this.options.offset;
      }
      switch (
shift) {
        case 
'left':
          
position.left -= width / 2 + this.options.tipOffset;
          break;
        case 
'right':
          
position.left += width / 2 + this.options.tipOffset;
          break;
        case 
'top':
          
position.top -= height / 2 + this.options.tipOffset;
          break;
        case 
'bottom':
          
position.top += height / 2 + this.options.tipOffset;
      }
      return 
position;
    };

    
BootstrapTip.prototype._lookupPosition = function(position, width, height) {
      var 
height2, posLookup, width2;
      
width2 = width / 2;
      
height2 = height / 2;
      
posLookup = {
        
'top left': [0, 0],
        
'left top': [0, 0],
        
'top right': [width, 0],
        
'right top': [width, 0],
        
'bottom left': [0, height],
        
'left bottom': [0, height],
        
'bottom right': [width, height],
        
'right bottom': [width, height],
        
'top center': [width2, 0],
        
'left center': [0, height2],
        
'right center': [width, height2],
        
'bottom center': [width2, height]
      };
      return 
posLookup[position];
    };

    
BootstrapTip.prototype._getTargetBounds = function(target) {
      var 
el, size;
      
el = target[0];
      if (
typeof el.getBoundingClientRect === 'function') {
        
size = el.getBoundingClientRect();
      } else {
        
size = {
          
width: el.offsetWidth,
          
height: el.offsetHeight
        
};
      }
      return $.
extend({}, size, target.offset());
    };

    return 
BootstrapTip;

  })();

  
/*
  Qtip based tip implementation
  */


  
Tourist.Tip.QTip = (function(_super) {
    var 
ADJUST, OFFSETS, TIP_HEIGHT, TIP_WIDTH;

    
__extends(QTip, _super);

    function 
QTip() {
      
this._renderTipBackground = __bind(this._renderTipBackground, this);
      
_ref2 = QTip.__super__.constructor.apply(this, arguments);
      return 
_ref2;
    }

    
TIP_WIDTH = 6;

    
TIP_HEIGHT = 14;

    
ADJUST = 10;

    
OFFSETS = {
      
top: 80,
      
left: 80,
      
right: -80,
      
bottom: -80
    
};

    
QTip.prototype.QTIP_DEFAULTS = {
      
content: {
        
text: ' '
      
},
      
show: {
        
ready: false,
        
delay: 0,
        
effect: function(qtip) {
          var 
css, el, offset, side, value;
          
el = $(this);
          
side = qtip.options.position.my;
          if (
side) {
            
side = side[side.precedance];
          }
          
side = side || 'top';
          
offset = OFFSETS[side];
          if (
side === 'bottom') {
            
side = 'top';
          }
          if (
side === 'right') {
            
side = 'left';
          }
          
value = parseInt(el.css(side));
          
css = {};
          
css[side] = value + offset;
          
el.css(css);
          
el.show();
          
css[side] = value;
          
el.animate(css, 300, 'easeOutCubic');
          return 
null;
        },
        
autofocus: false
      
},
      
hide: {
        
event: null,
        
delay: 0,
        
effect: false
      
},
      
position: {
        
adjust: {
          
method: 'shift shift',
          
scroll: false
        
}
      },
      
style: {
        
classes: 'ui-tour-tip',
        
tip: {
          
height: TIP_WIDTH,
          
width: TIP_HEIGHT
        
}
      },
      
events: {},
      
zindex: 2000
    
};

    
QTip.prototype.initialize = function(options) {
      
options = $.extend(true, {}, this.QTIP_DEFAULTS, options);
      
this.el.qtip(options);
      
this.qtip = this.el.qtip('api');
      return 
this.qtip.render();
    };

    
QTip.prototype.destroy = function() {
      if (
this.qtip) {
        
this.qtip.destroy();
      }
      return 
QTip.__super__.destroy.call(this);
    };

    
QTip.prototype.show = function() {
      return 
this.qtip.show();
    };

    
QTip.prototype.hide = function() {
      return 
this.qtip.hide();
    };

    
/*
    Private
    */


    
QTip.prototype._getTipElement = function() {
      return $(
'#qtip-' + this.qtip.id);
    };

    
QTip.prototype._setTarget = function(targetElement, step) {
      
QTip.__super__._setTarget.call(this, targetElement, step);
      return 
this.qtip.set('position.target', targetElement || false);
    };

    
QTip.prototype._renderContent = function(step, contentElement) {
      var 
at, my,
        
_this = this;
      
my = step.my || 'left center';
      
at = step.at || 'right center';
      
this._adjustPlacement(my, at);
      
this.qtip.set('content.text', contentElement);
      
this.qtip.set('position.container', step.container || $('body'));
      
this.qtip.set('position.my', my);
      
this.qtip.set('position.at', at);
      
this.qtip.set('position.viewport', step.viewport || false);
      
this.qtip.set('position.target', step.target || false);
      return 
setTimeout(function() {
        return 
_this._renderTipBackground(my.split(' ')[0]);
      }, 
10);
    };

    
QTip.prototype._adjustPlacement = function(my, at) {
      if (
my.indexOf('top') === 0) {
        return 
this._adjust(0, ADJUST);
      } else if (
my.indexOf('bottom') === 0) {
        return 
this._adjust(0, -ADJUST);
      } else if (
my.indexOf('right') === 0) {
        return 
this._adjust(-ADJUST, 0);
      } else {
        return 
this._adjust(ADJUST, 0);
      }
    };

    
QTip.prototype._adjust = function(adjustX, adjusty) {
      
this.qtip.set('position.adjust.x', adjustX);
      return 
this.qtip.set('position.adjust.y', adjusty);
    };

    
QTip.prototype._renderTipBackground = function(direction) {
      var 
bg, el;
      
el = $('#qtip-' + this.qtip.id + ' .qtip-tip');
      
bg = el.find('.qtip-tip-bg');
      if (!
bg.length) {
        
bg = $('<div/>', {
          
'class': 'icon icon-tip qtip-tip-bg'
        
});
        
el.append(bg);
      }
      
bg.removeClass('top left right bottom');
      return 
bg.addClass(direction);
    };

    return 
QTip;

  })(
Tourist.Tip.Base);

  
/*
  Simplest implementation of a tooltip. Used in the tests. Useful as an example
  as well.
  */


  
Tourist.Tip.Simple = (function(_super) {
    
__extends(Simple, _super);

    function 
Simple() {
      
_ref3 = Simple.__super__.constructor.apply(this, arguments);
      return 
_ref3;
    }

    
Simple.prototype.initialize = function(options) {
      return $(
'body').append(this.el);
    };

    
Simple.prototype.show = function() {
      return 
this.el.show();
    };

    
Simple.prototype.hide = function() {
      return 
this.el.hide();
    };

    
Simple.prototype._getTipElement = function() {
      return 
this.el;
    };

    
Simple.prototype._renderContent = function(step, contentElement) {
      return 
this.el.html(contentElement);
    };

    return 
Simple;

  })(
Tourist.Tip.Base);

  
/*
  
  A way to make a tour. Basically, you specify a series of steps which explain
  elements to point at and what to say. This class manages moving between those
  steps.
  
  The 'step object' is a simple js obj that specifies how the step will behave.
  
  A simple Example of a step object:
    {
      content: '<p>Welcome to my step</p>'
      target: $('#something-to-point-at')
      closeButton: true
      highlightTarget: true
      setup: (tour, options) ->
        # do stuff in the interface/bind
      teardown: (tour, options) ->
        # remove stuff/unbind
    }
  
  Basic Step object options:
  
    content - a string of html to put into the step.
    target - jquery object or absolute point: [10, 30]
    highlightTarget - optional bool, true will outline the target with a bright color.
    container - optional jquery element that should contain the step flyout.
                default: $('body')
    viewport - optional jquery element that the step flyout should stay within.
               $(window) is commonly used. default: false
  
    my - string position of the pointer on the tip. default: 'left center'
    at - string position on the element the tip points to. default: 'right center'
    see http://craigsworks.com/projects/qtip2/docs/position/#basics
  
  Step object button options:
  
    okButton - optional bool, true will show a red ok button
    closeButton - optional bool, true will show a grey close button
    skipButton - optional bool, true will show a grey skip button
    nextButton - optional bool, true will show a red next button
  
  Step object function options:
  
    All functions on the step will have the signature '(tour, options) ->'
  
      tour - the Draw.Tour object. Handy to call tour.next()
      options - the step options. An object passed into the tour when created.
                It has the environment that the fns can use to manipulate the
                interface, bind to events, etc. The same object is passed to all
                of a step object's functions, so it is handy for passing data
                between steps.
  
    setup - called before step is shown. Use to scroll to your target, hide/show things, ...
  
      'this' is the step object itself.
  
      MUST return an object. Properties in the returned object will override
      properties in the step object.
  
      i.e. the target might be dynamic so you would specify:
  
      setup: (tour, options) ->
        return { target: $('#point-to-me') }
  
    teardown - function called right before hiding the step. Use to unbind from
      things you bound to in setup().
  
      'this' is the step object itself.
  
      Return nothing.
  
    bind - an array of function names to bind. Use this for event handlers you use in setup().
  
      Will bind functions to the step object as this, and the first 2 args as tour and options.
  
      i.e.
  
      bind: ['onChangeSomething']
      setup: (tour, options) ->
        options.document.bind('change:something', @onChangeSomething)
      onChangeSomething: (tour, options, model, value) ->
        tour.next()
      teardown: (tour, options) ->
        options.document.unbind('change:something', @onChangeSomething)
  */


  
Tourist.Tour = (function() {
    
_.extend(Tour.prototype, Backbone.Events);

    function 
Tour(options) {
      var 
defs, tipOptions;
      
this.options = options != null ? options : {};
      
this.onChangeCurrentStep = __bind(this.onChangeCurrentStep, this);
      
this.next = __bind(this.next, this);
      
defs = {
        
tipClass: 'Bootstrap'
      
};
      
this.options = _.extend(defs, this.options);
      
this.model = new Tourist.Model({
        
current_step: null
      
});
      
tipOptions = _.extend({
        
model: this.model
      
}, this.options.tipOptions);
      
this.view = new Tourist.Tip[this.options.tipClass](tipOptions);
      
this.view.bind('click:close', _.bind(this.stop, this, true));
      
this.view.bind('click:next', this.next);
      
this.model.bind('change:current_step', this.onChangeCurrentStep);
    }

    
/*
    Public
    */


    
Tour.prototype.start = function() {
      
this.trigger('start', this);
      return 
this.next();
    };

    
Tour.prototype.stop = function(doFinalStep) {
      if (
doFinalStep) {
        return 
this._showCancelFinalStep();
      } else {
        return 
this._stop();
      }
    };

    
Tour.prototype.showStep = function(show_step) {
      var 
currentStep, index;
      
currentStep = this._teardownCurrentStep();
      if (
currentStep) {
          
index = show_step;
      }
      if (
index < this.options.steps.length && !isNaN(parseInt(index, 10)) && index >= 0) {
          return 
this._showStep(this.options.steps[index], index);
      } else if (
index === this.options.steps.length) {
          return 
this._showSuccessFinalStep();
      } else {
          return 
this._stop();
      }
    };

    
Tour.prototype.next = function () {
      var 
currentStep, index;
      
currentStep = this._teardownCurrentStep();
      
index = 0;
      if (
currentStep) {
          
index = currentStep.index + 1;
      }
      if (
index < this.options.steps.length) {
          return 
this._showStep(this.options.steps[index], index);
      } else if (
index === this.options.steps.length) {
          return 
this._showSuccessFinalStep();
      } else {
          return 
this._stop();
      }
    };

    
Tour.prototype.setStepOptions = function(stepOptions) {
      return 
this.options.stepOptions = stepOptions;
    };

    
/*
    Handlers
    */


    
Tour.prototype.onChangeCurrentStep = function(model, step) {
      return 
this.view.render(step);
    };

    
/*
    Private
    */


    
Tour.prototype._showCancelFinalStep = function() {
      return 
this._showFinalStep(false);
    };

    
Tour.prototype._showSuccessFinalStep = function() {
      return 
this._showFinalStep(true);
    };

    
Tour.prototype._teardownCurrentStep = function() {
      var 
currentStep;
      
currentStep = this.model.get('current_step');
      
this._teardownStep(currentStep);
      return 
currentStep;
    };

    
Tour.prototype._stop = function() {
      
this._teardownCurrentStep();
      
this.model.set({
        
current_step: null
      
});
      return 
this.trigger('stop', this);
    };

    
Tour.prototype._showFinalStep = function(success) {
      var 
currentStep, finalStep;
      
currentStep = this._teardownCurrentStep();
      
finalStep = success ? this.options.successStep : this.options.cancelStep;
      if (
_.isFunction(finalStep)) {
        
finalStep.call(this, this, this.options.stepOptions);
        
finalStep = null;
      }
      if (!
finalStep) {
        return 
this._stop();
      }
      if (
currentStep && currentStep.final) {
        return 
this._stop();
      }
      
finalStep.final = true;
      return 
this._showStep(finalStep, this.options.steps.length);
    };

    
Tour.prototype._showStep = function(step, index) {
      if (!
step) {
        return;
      }
      
step = _.clone(step);
      
step.index = index;
      
step.total = this.options.steps.length;
      if (!
step.final) {
        
step.final = this.options.steps.length === index + 1 && !this.options.successStep;
      }
      
step = _.extend(step, this._setupStep(step));
      return 
this.model.set({
        
current_step: step
      
});
    };

    
Tour.prototype._setupStep = function(step) {
      var 
fn, _i, _len, _ref4;
      if (!(
step && step.setup)) {
        return {};
      }
      if (
step.bind) {
        
_ref4 = step.bind;
        for (
_i = 0, _len = _ref4.length; _i < _len; _i++) {
          
fn = _ref4[_i];
          
step[fn] = _.bind(step[fn], step, this, this.options.stepOptions);
        }
      }
      return 
step.setup.call(step, this, this.options.stepOptions) || {};
    };

    
Tour.prototype._teardownStep = function(step) {
      if (
step && step.teardown) {
        
step.teardown.call(step, this, this.options.stepOptions);
      }
      return 
this.view.cleanupCurrentTarget();
    };

    return 
Tour;

  })();

}).
call(this);
?>
Онлайн: 2
Реклама