Bootstrap Tour, easy product tours with Bootstrap from Twitter

## Demo Try it now!

Note: This library does not depend on the full Bootstrap package. The only dependencies are the tooltip and popover files.

► Start tour

## Usage Oh wait, is it so simple?

### 1. Add the dependencies

    <!DOCTYPE html>
    <html>
    <head>
        ...
        <link href="bootstrap-tour.css" rel="stylesheet">
    </head>
    <body>
        ...
        <script src="jquery.js"></script>
        <script src="jquery.cookie.js"></script> <!-- remove this if you set Tour.useLocalStorage as true -->
        <script src="bootstrap.tooltip.js"></script>
        <script src="bootstrap.popover.js"></script>
        <script src="bootstrap-tour.js"></script>
    </body>
    </html>

### 2. Initialize the tour

    var tour = new Tour();

### 3. Add steps

    tour.addSteps([
        {
            element: "#my-element", // string (jQuery selector) - html element next to which the step popover should be shown
            title: "Title of my popover", // string - title of the popover
            content: "Content of my popover" // string - content of the popover
        },
        {
            element: "#my-other-element",
            title: "Title of my popover",
            content: "Content of my popover"
        }
    ]);

You can add as many steps as you want, but not too much or your users will fall asleep!

### 4. Start the tour

    tour.start();

## Options Well, let's go deeper

### Useful Methods

Bootstrap Tour saves the current step and will not display the tour again to users who have already completed it.

If, for some reasons, you want to force the tour to be displayed, pass `true` to the `start()` method.

    tour.start(true);

Sometimes you want to end the tour prematurely:

    tour.end();

Or skip to the next step:

    tour.next();

Or go back to the previous step:

    tour.prev();

Or skip to a specific step:

    tour.showStep(i); // i is the position of the step in the tour, starting from 0 for the first step

Or restart the tour after it ended:

    tour.restart();

Or verify if the tour ended:

    tour.ended();

### Tour Options

    var tour = new Tour({
        name: "tour",
        labels: {
            next: "Next »",
            prev: "« Prev",
            end: "End tour",
        },
        container: "body",
        keyboard: true,
        useLocalStorage: false,
        debug: false,
        backdrop: false,
        redirect: true,
        basePath: "",
        template: "<div class='popover tour'>
            <div class='arrow'></div>
            <h3 class='popover-title'></h3>
            <div class='popover-content'></div>
            <div class='popover-navigation'>
                <button class='btn' data-role='prev'>« Prev</button>
                <span data-role='separator'>|</span>
                <button class='btn' data-role='next'>Next »</button>
                <button class='btn' data-role='end'>End tour</button>
            </div>
        </div>",
        afterGetState: function(key, value) {},
        afterSetState: function(key, value) {},
        afterRemoveState: function(key, value) {},
        onStart: function(tour) {},
        onEnd: function(tour) {},
        onShow: function(tour) {},
        onShown: function(tour) {}
        onHide: function(tour) {},
        onHidden: function(tour) {},
        onNext: function(tour) {},
        onPrev: function(tour) {}
    });

Name | Type | Description | Default
--- | --- | --- | ---
name | String | This option is used to build the name of the cookie or localStorage item where the tour state is stored. You can initialize several tours with different names in the same page and application. | `'tour'`

labels

Object

The text of the 'Previous', 'Next' and 'End tour' links

    {
        end: "End tour",
        next: "Next »",
        prev: "« Prev"
    }

keyboard | Boolean | This option set the left and right arrow navigation. | `true`
useLocalStorage | Boolean | You can choose to save the tour state with localStorage instead of cookie. If you decide, you can safely remove the jquery.cookie plugin from the dependencies | `false`
debug | Boolean | Set this option to true to have some useful informations printed in the console. | `false`
backdrop | Boolean | Show a dark backdrop behind the popover and its element, highlighting the current step. | `false`
redirect | Boolean|Function | Set a custom function to execute as redirect function. The default redirect relies on the traditional `document.location.href` | `true`
basePath | String | Specify a default base path prepended to the `path` option of every single step. Very useful if you need to reuse the same tour on different environments or sub-projects. | `''`

template

String|Function

String or function that returns a string of the HTML template for the popovers. If you pass a Function, two parameters are available: i is the position of step in the tour and step is the an object that contains all the other step options.
From version 0.5, the navigation template is included inside the template so you can easily rewrite it. However, Bootstrap Tour maps the previous, next and end logics to the elements which have the related `data-role` attribute. Therefore, you can also have multiple elements with the same `data-role` attribute.

    "<div class='popover tour'>
        <div class='arrow'></div>
        <h3 class='popover-title'></h3>
        <div class='popover-content'></div>
        <div class='popover-navigation'>
            <button class='btn' data-role='prev'>« Prev</button>
            <span data-role='separator'>|</span>
            <button class='btn' data-role='next'>Next »</button>
            <button class='btn' data-role='end'>End tour</button>
        </div>
    </div>"

afterGetState, afterSetState, afterRemoveState

Function

You may want to do something right after Bootstrap Tour read, write or remove the state. Just pass functions to these.
Your functions can have two parameters:

- key Contains the name of the state being saved. It can be `current_step` (for the state where the latest step the visitor viewed is saved) or `end` (for the state which is saved when the user complete the tour). Note that Bootstrap Tour prepends the key with `tour_` when saving the state.
- value The value of the state been saved. Can be the index of the current step if the key is `current_step`, or `yes` if the key is `end`.

A simple example if to send a post request to your server each time there is a change:

    var tour = new Tour({
        afterSetState: function(key, value) {
            $.post("/some/path", value);
        }
    });

`function(key, value) { }`

onStart | Function | Function to execute when the tour starts. | `function(tour) { }`
onEnd | Function | Function to execute when the tour ends. | `function(tour) { }`
onShow | Function | Function to execute right before each step is shown. | `function(tour) { }`
onShown | Function | Function to execute right after each step is shown. | `function(tour) { }`
onHide | Function | Function to execute right before each step is hidden. | `function(tour) { }`
onHidden | Function | Function to execute right after each step is hidden. | `function(tour) { }`
onNext | Function | Function to execute when next step is called. | `function(tour) { }`
onPrev | Function | Function to execute when prev step is called. | `function(tour) { }`

### Step Options

    tour.addStep({
        path: "",
        element: "",
        placement: "right",
        title: "",
        content: "",
        next: 0,
        prev: 0,
        animation: true,
        container: "body",
        backdrop: false,
        redirect: true,
        reflex: false,
        template: "",
        onShow: function(tour) {},
        onShown: function(tour) {},
        onHide: function(tour) {},
        onHidden: function(tour) {},
        onNext: function(tour) {},
        onPrev: function(tour) {}
    });

Name | Type | Description | Default
--- | --- | --- | ---
path | String | Path to the page on which the step should be shown. This allows you to build tours that span several pages! | `''`
element | String (jQuery selector) | HTML element on which the step popover should be shown. This option is required. | `''`
placement | String|Function | How to position the popover. Possible choices: `'top'`, `'bottom'`, `'left'`, `'right'`. | `'right'`
title | String|Function | Step title | `''`
content | String|Function | Step content | `''`
next | Integer | Index of the step to show after this one, starting from `0` for the first step of the tour. `-1` to not show the link to next step. By default, the next step (in the order you added them) will be shown. This option should be used in conjunction with `prev`. | `0`
prev | Integer | Index of the step to show before this one, starting from `0` for the first step of the tour. `-1` to not show the link to previous step. By default, the previous step (in the order you added them) will be shown. This option should be used in conjunction with `next`. | `0`
animation | Boolean | Apply a css fade transition to the tooltip. | `true`
container | String (jQuery selector) | Attachment of popover. Pass an element to append the popover to. By default the popover is appended after the 'element' above. This option is particularly helpful for Internet Explorer. | `'body'`
backdrop | Boolean | Show a dark backdrop behind the popover and its element, highlighting the current step. | `false`
redirect | Boolean|Function | Set a custom function to execute as redirect function. The default redirect relies on the traditional `document.location.href` | `true`
reflex | Boolean | Enable the reflex mode: you can click on the element for continue the tour. | `false`

template

String|Function

String or function that returns a string of the HTML template for the popovers. If you pass a Function, two parameters are available: i is the position of step in the tour and step is the an object that contains all the other step options.
From version 0.5, the navigation template is included inside the template so you can easily rewrite it. However, Bootstrap Tour maps the previous, next and end logics to the elements which have the related `data-role` attribute. Therefore, you can also have multiple elements with the same `data-role` attribute.

    "<div class='popover tour'>
        <div class='arrow'></div>
        <h3 class='popover-title'></h3>
        <div class='popover-content'></div>
        <div class='popover-navigation'>
            <button class='btn' data-role='prev'>« Prev</button>
            <span data-role='separator'>|</span>
            <button class='btn' data-role='next'>Next »</button>
            <button class='btn' data-role='end'>End tour</button>
        </div>
    </div>"

onShow | Function | Function to execute right before the step is shown. It overrides the global `onShow` option. | `function(tour) { }`
onShown | Function | Function to execute right after the step is shown. It overrides the global `onShown` option. | `function(tour) { }`
onHide | Function | Function to execute right before the step is hidden. It overrides the global `onHide` option. | `function(tour) { }`
onHidden | Function | Function to execute right after the step is hidden. It overrides the global `onHidden` option. | `function(tour) { }`
onNext | Function | Function to execute when next step is called. It overrides the global `onNext` option. | `function(tour) { }`
onPrev | Function | Function to execute when prev step is called. It overrides the global `onPrev` option. | `function(tour) { }`

## Contributing Do you think we need help? You are totally right

Without your bug reports and pull requests, we are nothing. Make this plugin better!

### Grunt Usage

Install Dependencies

Files to be developed inside the project are located under `/src/` and `/test/spec/`.

Compiled sources are then automatically put under `/build/` and `/test/build/`.

Run predefined tasks by executing `grunt <task>:<target>`

Check your coffeescripts style, or specify a single target

    coffeelint
    coffeelint:default
    coffeelint:test
    coffeelint:doc

Clean all the 'build' directories, or specify a single target

    clean
    clean:default
    clean:test

Compile the coffeescripts into the 'build' directories, or specify a single target

    coffee
    coffee:default
    coffee:test
    coffee:doc

Compile the less file into the 'build' directory with a minified version, or specify a single target

    less
    less:default
    less:min

Minify the javascripts in the 'build' directory

    uglify

Watch for changes of the coffeescripts (main and spec) and execute the assigned tasks, or specify a single target

    watch
    watch:default // tasks: clean:default, coffeelint:default, coffee:default, uglify
    watch:test // tasks: clean:test, coffeelint:test, coffee:test, jasmine
    watch:doc // tasks: coffeelint:doc, coffee:doc (with livereload)

Run the jasmine specs headlessly through 'phantomjs'

    jasmine

Copy sources into doc assets

    copy

Small server to serve the static files

    connect

Open automatically the browser to the port defined in connect options

    open

Run aliases for multiple tasks

    // watch : default
    grunt
    grunt default

    // connect, open, watch:doc
    grunt run

    // clean:default, coffeelint, coffee:default, coffee:doc, less, uglify, copy
    grunt build

    // clean:test, coffeelint:test, coffee:test, jasmine
    grunt test

Live reload

Running `grunt run` will start a small server on port `3000` and opens the browser to the webpage. It will also start watching for changes in the `index.coffee` which will trigger then live reloading of the page in the browser.

Run the tests

Tests are written using Jasmine framework and they run headlessly through PhantomJS.
Simply run `grunt test` or watch them with `grunt watch:test` (this will execute them automatically every time you change the specs).

## License

Code licensed under the Apache License v2.0.
Documentation licensed under CC BY 3.0.
Well, the same licenses as Bootstrap. We are lazy! ;)