/** * Tour Class for handling guided tooltip tours * * @param {Array} steps Group of step objects to go through for tour * @param {Function} callback (optional) Funciton to call on completion * @constructor * */ var Tour = function (steps, callback) { this.steps = steps; this.step = 0; this.callback = callback; return this; }; /** * Starts a tour * Will reset current tour if it is in progress */ Tour.prototype.start = function () { this.step = 0; this.showStep(this.step); }; /** * Finish a tour * Cleans up elements for now, maybe more cool stuff in the future */ Tour.prototype.finish = function () { $('.walkthrough-overlay').remove(); $('.walkthrough-tip').remove(); if (this.callback) { this.callback.apply(this); } }; /** * Goes to next step on the tour * Will end tour if this is the last step * @return {bool} Whether we had a next step */ Tour.prototype.next = function () { if (this.step >= (this.steps.length - 1)) { this.finish(); return false; } this.step++; this.showStep(this.step); }; /** * Shows a step from the tour * @param {int} step The index of the step to show */ Tour.prototype.showStep = function (step) { this.showOverlay(); $('.walkthrough-target').removeClass('walkthrough-target'); $('.walkthrough-tip').remove(); var stepInfo = this.steps[step]; var self = this; // If there's no target element, skip this step var target = $(stepInfo.element); if (!target.length) { this.next(); return; } // Setup HTML var tip = $('
') .append($('
')) .append($('

')) .append($('

')) .append($('

')); var nextButton = $('') .text('Next Step') .click(function () { self.next(); }); if (this.step >= (this.steps.length -1)) { nextButton.text('Finish Tour'); } tip.find('.walkthrough-tip-actions').append(nextButton.wrap('')); tip.find('.walkthrough-tip-title').text(stepInfo.title); tip.find('.walkthrough-tip-text').text(stepInfo.description); tip.appendTo('body'); // Position on page var pos = target.position(); target.addClass('walkthrough-target'); switch (stepInfo.position) { case 'top': tip.css('top', pos.top - tip.outerHeight() - 10); tip.css('left', pos.left + (target.outerWidth() / 2) - (tip.outerWidth() / 2)); tip.addClass('walkthrough-tip-top'); tip.addClass(stepInfo.element.replace('#', '')); break; case 'left': tip.css('top', pos.top + (target.outerHeight() / 2) - (tip.outerHeight() / 2)); tip.css('left', pos.left - tip.outerWidth() - 10); tip.addClass('walkthrough-tip-left'); tip.addClass(stepInfo.element.replace('#', '')); break; case 'right': tip.css('top', pos.top + (target.outerHeight() / 2) - (tip.outerHeight() / 2)); tip.css('left', pos.left + target.outerWidth() + 10); tip.addClass('walkthrough-tip-right'); tip.addClass(stepInfo.element.replace('#', '')); break; default: tip.css('top', pos.top + target.outerHeight() + 10); tip.css('left', pos.left + (target.outerWidth() / 2) - (tip.outerWidth() / 2)); tip.addClass('walkthrough-tip-bottom'); tip.addClass(stepInfo.element.replace('#', '')); } }; /** * Shows overlay. * If it isn't already added to the page it creates one */ Tour.prototype.showOverlay = function () { var overlay = $('.walkthrough-overlay'); if (!overlay.length) { $('
').appendTo('body'); } };