[Pkg-javascript-commits] [node-bootstrap-tour] 01/03: Imported Upstream version 0.10.2+dfsg

Julien Puydt julien.puydt at laposte.net
Sat Oct 10 08:09:32 UTC 2015


This is an automated email from the git hooks/post-receive script.

jpuydt-guest pushed a commit to branch master
in repository node-bootstrap-tour.

commit cb1d2742d0f8e87568b1875db494c1f1403b070c
Author: Julien Puydt <julien.puydt at laposte.net>
Date:   Sat Oct 10 08:45:17 2015 +0200

    Imported Upstream version 0.10.2+dfsg
---
 .editorconfig                                      |   21 +
 .gitignore                                         |   10 +
 .travis.yml                                        |   14 +
 CNAME                                              |    1 +
 LICENSE                                            |  176 +++
 README.md                                          |   77 ++
 _config.yml                                        |    5 +
 bower.json                                         |   20 +
 build/css/bootstrap-tour-standalone.css            |  728 +++++++++++
 build/css/bootstrap-tour-standalone.min.css        |   26 +
 build/css/bootstrap-tour.css                       |   73 ++
 build/css/bootstrap-tour.min.css                   |   22 +
 build/js/bootstrap-tour-standalone.js              | 1374 ++++++++++++++++++++
 build/js/bootstrap-tour.js                         |  802 ++++++++++++
 coffeelint.json                                    |  127 ++
 composer.json                                      |   13 +
 gulpfile.coffee                                    |  214 +++
 gulpfile.js                                        |    2 +
 karma.json                                         |   19 +
 package.js                                         |    3 +
 package.json                                       |   83 ++
 smart.json                                         |    9 +
 src/coffee/bootstrap-tour.coffee                   |  655 ++++++++++
 src/coffee/bootstrap-tour.docs.coffee              |   94 ++
 src/coffee/bootstrap-tour.spec.coffee              |  775 +++++++++++
 src/docs/CNAME                                     |    1 +
 src/docs/_includes/footer.html                     |   14 +
 src/docs/_includes/header.html                     |   29 +
 src/docs/_includes/nav.html                        |   26 +
 src/docs/_layouts/default.html                     |   12 +
 src/docs/api.html                                  |  746 +++++++++++
 src/docs/assets/css/bootstrap-tour.css             |   73 ++
 src/docs/assets/css/bootstrap-tour.docs.css        |   61 +
 .../assets/fonts/glyphicons-halflings-regular.eot  |  Bin 0 -> 14079 bytes
 .../assets/fonts/glyphicons-halflings-regular.svg  |  228 ++++
 .../assets/fonts/glyphicons-halflings-regular.ttf  |  Bin 0 -> 29512 bytes
 .../assets/fonts/glyphicons-halflings-regular.woff |  Bin 0 -> 16448 bytes
 .../img/apple-touch-icon-144-precomposed.png       |  Bin 0 -> 3549 bytes
 src/docs/assets/img/favicon.png                    |  Bin 0 -> 887 bytes
 src/docs/assets/img/masthead-pattern.png           |  Bin 0 -> 6450 bytes
 src/docs/assets/js/bootstrap-tour.js               |  802 ++++++++++++
 src/docs/assets/vendor/bootstrap.min.css           |    9 +
 src/docs/assets/vendor/jquery.smoothscroll.js      |   47 +
 src/docs/assets/vendor/pygments-manni.css          |   66 +
 src/docs/index.html                                |  107 ++
 src/less/bootstrap-tour-standalone.less            |   15 +
 src/less/bootstrap-tour.less                       |   60 +
 test/bootstrap-tour.js                             |  802 ++++++++++++
 48 files changed, 8441 insertions(+)

diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..fdbdf0d
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,21 @@
+EditorConfig helps developers define and maintain consistent
+# coding styles between different editors and IDEs
+# editorconfig.org
+
+root = true
+
+
+[*]
+
+# Change these settings to your own preference
+indent_style = space
+indent_size = 2
+
+# We recommend you to keep these unchanged
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..cba3758
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,10 @@
+node_modules
+bower_components
+bootstrap-tour.sublime-project
+bootstrap-tour.sublime-workspace
+npm-debug.log
+test
+docs
+_SpecRunner.html
+*.DS_Store
+smart.lock
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..c3b821f
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,14 @@
+language: node_js
+node_js:
+  - "0.10"
+before_install:
+  - "export DISPLAY=:99.0"
+  - "sh -e /etc/init.d/xvfb start"
+before_script:
+  - npm install -g gulp
+  - npm install -g bower
+  - bower install
+branches:
+  only:
+    - master
+    - develop
diff --git a/CNAME b/CNAME
new file mode 100644
index 0000000..b876b5a
--- /dev/null
+++ b/CNAME
@@ -0,0 +1 @@
+bootstraptour.com
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..2bb9ad2
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,176 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..88a9010
--- /dev/null
+++ b/README.md
@@ -0,0 +1,77 @@
+# Bootstrap Tour
+[![Build Status](http://img.shields.io/travis/sorich87/bootstrap-tour.svg?style=flat)](https://travis-ci.org/sorich87/bootstrap-tour)
+[![Dependency Status](http://img.shields.io/david/sorich87/bootstrap-tour.svg?style=flat)](https://david-dm.org/sorich87/bootstrap-tour)
+[![devDependency Status](http://img.shields.io/david/dev/sorich87/bootstrap-tour/dev-status.svg?style=flat)](https://david-dm.org/sorich87/bootstrap-tour#info=devDependencies)
+[![NPM Version](http://img.shields.io/npm/v/bootstrap-tour.svg?style=flat)](https://www.npmjs.org/)
+
+Quick and easy way to build your product tours with Bootstrap Popovers.
+
+*Compatible with Bootstrap >= 2.3.0*
+
+## Demo and Documentation
+[http://bootstraptour.com](http://bootstraptour.com)
+
+## Contributing
+In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [Gulp](http://gulpjs.com/).
+
+Feel free to contribute with pull requests, bug reports or enhancement suggestions.
+
+We use [Gulp](http://gulpjs.com/) and [Jasmine](http://pivotal.github.io/jasmine/). Both make your life easier ;)
+
+### Develop
+
+Files to be developed are located under `./src/`.
+Compiled sources are then automatically put under `./build/`, `./test/` and `./docs/`.
+
+#### Requirements
+
+To begin, you need a few standard dependencies installed. These commands will install ruby, gem, node, npm, and grunt's command line runner:
+
+##### Linux
+
+```bash
+$ sudo apt-get install ruby
+$ sudo apt-get install ruby-dev
+$ sudo apt-get install npm
+$ sudo apt-get install nodejs-legacy
+```
+
+##### Mac OS X
+
+```bash
+ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)"
+\curl -L https://get.rvm.io | bash
+rvm install ruby-2.1.1
+brew install node
+```
+
+##### Development requirements
+
+```bash
+$ npm install -g gulp
+$ npm install
+$ gem install jekyll
+```
+
+For Mac OS X Mavericks (10.9) users: You will need to [jump through all these hoops](http://dean.io/setting-up-a-ruby-on-rails-development-environment-on-mavericks/) before you can install Jekyll.
+
+#### Gulp usage
+
+Run gulp and start to develop with ease:
+
+```bash
+$ gulp
+$ gulp dist
+$ gulp test
+$ gulp docs
+$ gulp clean
+$ gulp server
+$ gulp bump --type minor (major.minor.patch)
+```
+
+Check `gulpfile.coffee` to know more.
+
+## License
+
+Code licensed under the [Apache License v2.0](http://www.apache.org/licenses/LICENSE-2.0).
+Documentation licensed under [CC BY 3.0](http://creativecommons.org/licenses/by/3.0/).
diff --git a/_config.yml b/_config.yml
new file mode 100644
index 0000000..80dfdc7
--- /dev/null
+++ b/_config.yml
@@ -0,0 +1,5 @@
+markdown:         rdiscount
+permalink:        pretty
+source:           ./src/docs
+destination:      ./docs
+encoding:         UTF-8
diff --git a/bower.json b/bower.json
new file mode 100644
index 0000000..908256f
--- /dev/null
+++ b/bower.json
@@ -0,0 +1,20 @@
+{
+  "name": "bootstrap-tour",
+  "version": "0.10.2",
+  "main": [
+    "./build/js/bootstrap-tour.js",
+    "./build/js/bootstrap-tour-standalone.js",
+    "./build/css/bootstrap-tour.css",
+    "./build/css/bootstrap-tour-standalone.css"
+  ],
+  "dependencies": {
+    "bootstrap": ">=2.3.2",
+    "jquery": ">=1.9.0"
+  },
+  "devDependencies": {
+    "html5shiv": "~3.7.2",
+    "jquery": "~2.1.1",
+    "bootstrap": "~3.2.0",
+    "blueimp-md5": "~1.1.0"
+  }
+}
diff --git a/build/css/bootstrap-tour-standalone.css b/build/css/bootstrap-tour-standalone.css
new file mode 100644
index 0000000..19ae087
--- /dev/null
+++ b/build/css/bootstrap-tour-standalone.css
@@ -0,0 +1,728 @@
+/* ========================================================================
+ * bootstrap-tour - v0.10.1
+ * http://bootstraptour.com
+ * ========================================================================
+ * Copyright 2012-2013 Ulrich Sossou
+ *
+ * ========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================================
+ */
+
+/*!
+ * Bootstrap v3.1.0 (http://getbootstrap.com)
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+.btn {
+  display: inline-block;
+  margin-bottom: 0;
+  font-weight: normal;
+  text-align: center;
+  vertical-align: middle;
+  cursor: pointer;
+  background-image: none;
+  border: 1px solid transparent;
+  white-space: nowrap;
+  padding: 6px 12px;
+  font-size: 14px;
+  line-height: 1.42857143;
+  border-radius: 4px;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+.btn:focus,
+.btn:active:focus,
+.btn.active:focus {
+  outline: thin dotted;
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+.btn:hover,
+.btn:focus {
+  color: #333333;
+  text-decoration: none;
+}
+.btn:active,
+.btn.active {
+  outline: 0;
+  background-image: none;
+  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+  box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+}
+.btn.disabled,
+.btn[disabled],
+fieldset[disabled] .btn {
+  cursor: not-allowed;
+  pointer-events: none;
+  opacity: 0.65;
+  filter: alpha(opacity=65);
+  -webkit-box-shadow: none;
+  box-shadow: none;
+}
+.btn-default {
+  color: #333333;
+  background-color: #ffffff;
+  border-color: #cccccc;
+}
+.btn-default:hover,
+.btn-default:focus,
+.btn-default:active,
+.btn-default.active,
+.open > .dropdown-toggle.btn-default {
+  color: #333333;
+  background-color: #e6e6e6;
+  border-color: #adadad;
+}
+.btn-default:active,
+.btn-default.active,
+.open > .dropdown-toggle.btn-default {
+  background-image: none;
+}
+.btn-default.disabled,
+.btn-default[disabled],
+fieldset[disabled] .btn-default,
+.btn-default.disabled:hover,
+.btn-default[disabled]:hover,
+fieldset[disabled] .btn-default:hover,
+.btn-default.disabled:focus,
+.btn-default[disabled]:focus,
+fieldset[disabled] .btn-default:focus,
+.btn-default.disabled:active,
+.btn-default[disabled]:active,
+fieldset[disabled] .btn-default:active,
+.btn-default.disabled.active,
+.btn-default[disabled].active,
+fieldset[disabled] .btn-default.active {
+  background-color: #ffffff;
+  border-color: #cccccc;
+}
+.btn-default .badge {
+  color: #ffffff;
+  background-color: #333333;
+}
+.btn-primary {
+  color: #ffffff;
+  background-color: #428bca;
+  border-color: #357ebd;
+}
+.btn-primary:hover,
+.btn-primary:focus,
+.btn-primary:active,
+.btn-primary.active,
+.open > .dropdown-toggle.btn-primary {
+  color: #ffffff;
+  background-color: #3071a9;
+  border-color: #285e8e;
+}
+.btn-primary:active,
+.btn-primary.active,
+.open > .dropdown-toggle.btn-primary {
+  background-image: none;
+}
+.btn-primary.disabled,
+.btn-primary[disabled],
+fieldset[disabled] .btn-primary,
+.btn-primary.disabled:hover,
+.btn-primary[disabled]:hover,
+fieldset[disabled] .btn-primary:hover,
+.btn-primary.disabled:focus,
+.btn-primary[disabled]:focus,
+fieldset[disabled] .btn-primary:focus,
+.btn-primary.disabled:active,
+.btn-primary[disabled]:active,
+fieldset[disabled] .btn-primary:active,
+.btn-primary.disabled.active,
+.btn-primary[disabled].active,
+fieldset[disabled] .btn-primary.active {
+  background-color: #428bca;
+  border-color: #357ebd;
+}
+.btn-primary .badge {
+  color: #428bca;
+  background-color: #ffffff;
+}
+.btn-success {
+  color: #ffffff;
+  background-color: #5cb85c;
+  border-color: #4cae4c;
+}
+.btn-success:hover,
+.btn-success:focus,
+.btn-success:active,
+.btn-success.active,
+.open > .dropdown-toggle.btn-success {
+  color: #ffffff;
+  background-color: #449d44;
+  border-color: #398439;
+}
+.btn-success:active,
+.btn-success.active,
+.open > .dropdown-toggle.btn-success {
+  background-image: none;
+}
+.btn-success.disabled,
+.btn-success[disabled],
+fieldset[disabled] .btn-success,
+.btn-success.disabled:hover,
+.btn-success[disabled]:hover,
+fieldset[disabled] .btn-success:hover,
+.btn-success.disabled:focus,
+.btn-success[disabled]:focus,
+fieldset[disabled] .btn-success:focus,
+.btn-success.disabled:active,
+.btn-success[disabled]:active,
+fieldset[disabled] .btn-success:active,
+.btn-success.disabled.active,
+.btn-success[disabled].active,
+fieldset[disabled] .btn-success.active {
+  background-color: #5cb85c;
+  border-color: #4cae4c;
+}
+.btn-success .badge {
+  color: #5cb85c;
+  background-color: #ffffff;
+}
+.btn-info {
+  color: #ffffff;
+  background-color: #5bc0de;
+  border-color: #46b8da;
+}
+.btn-info:hover,
+.btn-info:focus,
+.btn-info:active,
+.btn-info.active,
+.open > .dropdown-toggle.btn-info {
+  color: #ffffff;
+  background-color: #31b0d5;
+  border-color: #269abc;
+}
+.btn-info:active,
+.btn-info.active,
+.open > .dropdown-toggle.btn-info {
+  background-image: none;
+}
+.btn-info.disabled,
+.btn-info[disabled],
+fieldset[disabled] .btn-info,
+.btn-info.disabled:hover,
+.btn-info[disabled]:hover,
+fieldset[disabled] .btn-info:hover,
+.btn-info.disabled:focus,
+.btn-info[disabled]:focus,
+fieldset[disabled] .btn-info:focus,
+.btn-info.disabled:active,
+.btn-info[disabled]:active,
+fieldset[disabled] .btn-info:active,
+.btn-info.disabled.active,
+.btn-info[disabled].active,
+fieldset[disabled] .btn-info.active {
+  background-color: #5bc0de;
+  border-color: #46b8da;
+}
+.btn-info .badge {
+  color: #5bc0de;
+  background-color: #ffffff;
+}
+.btn-warning {
+  color: #ffffff;
+  background-color: #f0ad4e;
+  border-color: #eea236;
+}
+.btn-warning:hover,
+.btn-warning:focus,
+.btn-warning:active,
+.btn-warning.active,
+.open > .dropdown-toggle.btn-warning {
+  color: #ffffff;
+  background-color: #ec971f;
+  border-color: #d58512;
+}
+.btn-warning:active,
+.btn-warning.active,
+.open > .dropdown-toggle.btn-warning {
+  background-image: none;
+}
+.btn-warning.disabled,
+.btn-warning[disabled],
+fieldset[disabled] .btn-warning,
+.btn-warning.disabled:hover,
+.btn-warning[disabled]:hover,
+fieldset[disabled] .btn-warning:hover,
+.btn-warning.disabled:focus,
+.btn-warning[disabled]:focus,
+fieldset[disabled] .btn-warning:focus,
+.btn-warning.disabled:active,
+.btn-warning[disabled]:active,
+fieldset[disabled] .btn-warning:active,
+.btn-warning.disabled.active,
+.btn-warning[disabled].active,
+fieldset[disabled] .btn-warning.active {
+  background-color: #f0ad4e;
+  border-color: #eea236;
+}
+.btn-warning .badge {
+  color: #f0ad4e;
+  background-color: #ffffff;
+}
+.btn-danger {
+  color: #ffffff;
+  background-color: #d9534f;
+  border-color: #d43f3a;
+}
+.btn-danger:hover,
+.btn-danger:focus,
+.btn-danger:active,
+.btn-danger.active,
+.open > .dropdown-toggle.btn-danger {
+  color: #ffffff;
+  background-color: #c9302c;
+  border-color: #ac2925;
+}
+.btn-danger:active,
+.btn-danger.active,
+.open > .dropdown-toggle.btn-danger {
+  background-image: none;
+}
+.btn-danger.disabled,
+.btn-danger[disabled],
+fieldset[disabled] .btn-danger,
+.btn-danger.disabled:hover,
+.btn-danger[disabled]:hover,
+fieldset[disabled] .btn-danger:hover,
+.btn-danger.disabled:focus,
+.btn-danger[disabled]:focus,
+fieldset[disabled] .btn-danger:focus,
+.btn-danger.disabled:active,
+.btn-danger[disabled]:active,
+fieldset[disabled] .btn-danger:active,
+.btn-danger.disabled.active,
+.btn-danger[disabled].active,
+fieldset[disabled] .btn-danger.active {
+  background-color: #d9534f;
+  border-color: #d43f3a;
+}
+.btn-danger .badge {
+  color: #d9534f;
+  background-color: #ffffff;
+}
+.btn-link {
+  color: #428bca;
+  font-weight: normal;
+  cursor: pointer;
+  border-radius: 0;
+}
+.btn-link,
+.btn-link:active,
+.btn-link[disabled],
+fieldset[disabled] .btn-link {
+  background-color: transparent;
+  -webkit-box-shadow: none;
+  box-shadow: none;
+}
+.btn-link,
+.btn-link:hover,
+.btn-link:focus,
+.btn-link:active {
+  border-color: transparent;
+}
+.btn-link:hover,
+.btn-link:focus {
+  color: #2a6496;
+  text-decoration: underline;
+  background-color: transparent;
+}
+.btn-link[disabled]:hover,
+fieldset[disabled] .btn-link:hover,
+.btn-link[disabled]:focus,
+fieldset[disabled] .btn-link:focus {
+  color: #777777;
+  text-decoration: none;
+}
+.btn-lg,
+.btn-group-lg > .btn {
+  padding: 10px 16px;
+  font-size: 18px;
+  line-height: 1.33;
+  border-radius: 6px;
+}
+.btn-sm,
+.btn-group-sm > .btn {
+  padding: 5px 10px;
+  font-size: 12px;
+  line-height: 1.5;
+  border-radius: 3px;
+}
+.btn-xs,
+.btn-group-xs > .btn {
+  padding: 1px 5px;
+  font-size: 12px;
+  line-height: 1.5;
+  border-radius: 3px;
+}
+.btn-block {
+  display: block;
+  width: 100%;
+}
+.btn-block + .btn-block {
+  margin-top: 5px;
+}
+input[type="submit"].btn-block,
+input[type="reset"].btn-block,
+input[type="button"].btn-block {
+  width: 100%;
+}
+.btn-group,
+.btn-group-vertical {
+  position: relative;
+  display: inline-block;
+  vertical-align: middle;
+}
+.btn-group > .btn,
+.btn-group-vertical > .btn {
+  position: relative;
+  float: left;
+}
+.btn-group > .btn:hover,
+.btn-group-vertical > .btn:hover,
+.btn-group > .btn:focus,
+.btn-group-vertical > .btn:focus,
+.btn-group > .btn:active,
+.btn-group-vertical > .btn:active,
+.btn-group > .btn.active,
+.btn-group-vertical > .btn.active {
+  z-index: 2;
+}
+.btn-group > .btn:focus,
+.btn-group-vertical > .btn:focus {
+  outline: 0;
+}
+.btn-group .btn + .btn,
+.btn-group .btn + .btn-group,
+.btn-group .btn-group + .btn,
+.btn-group .btn-group + .btn-group {
+  margin-left: -1px;
+}
+.btn-toolbar {
+  margin-left: -5px;
+}
+.btn-toolbar .btn-group,
+.btn-toolbar .input-group {
+  float: left;
+}
+.btn-toolbar > .btn,
+.btn-toolbar > .btn-group,
+.btn-toolbar > .input-group {
+  margin-left: 5px;
+}
+.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
+  border-radius: 0;
+}
+.btn-group > .btn:first-child {
+  margin-left: 0;
+}
+.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {
+  border-bottom-right-radius: 0;
+  border-top-right-radius: 0;
+}
+.btn-group > .btn:last-child:not(:first-child),
+.btn-group > .dropdown-toggle:not(:first-child) {
+  border-bottom-left-radius: 0;
+  border-top-left-radius: 0;
+}
+.btn-group > .btn-group {
+  float: left;
+}
+.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
+  border-radius: 0;
+}
+.btn-group > .btn-group:first-child > .btn:last-child,
+.btn-group > .btn-group:first-child > .dropdown-toggle {
+  border-bottom-right-radius: 0;
+  border-top-right-radius: 0;
+}
+.btn-group > .btn-group:last-child > .btn:first-child {
+  border-bottom-left-radius: 0;
+  border-top-left-radius: 0;
+}
+.btn-group .dropdown-toggle:active,
+.btn-group.open .dropdown-toggle {
+  outline: 0;
+}
+.btn-group > .btn + .dropdown-toggle {
+  padding-left: 8px;
+  padding-right: 8px;
+}
+.btn-group > .btn-lg + .dropdown-toggle {
+  padding-left: 12px;
+  padding-right: 12px;
+}
+.btn-group.open .dropdown-toggle {
+  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+  box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+}
+.btn-group.open .dropdown-toggle.btn-link {
+  -webkit-box-shadow: none;
+  box-shadow: none;
+}
+.btn .caret {
+  margin-left: 0;
+}
+.btn-lg .caret {
+  border-width: 5px 5px 0;
+  border-bottom-width: 0;
+}
+.dropup .btn-lg .caret {
+  border-width: 0 5px 5px;
+}
+.btn-group-vertical > .btn,
+.btn-group-vertical > .btn-group,
+.btn-group-vertical > .btn-group > .btn {
+  display: block;
+  float: none;
+  width: 100%;
+  max-width: 100%;
+}
+.btn-group-vertical > .btn-group > .btn {
+  float: none;
+}
+.btn-group-vertical > .btn + .btn,
+.btn-group-vertical > .btn + .btn-group,
+.btn-group-vertical > .btn-group + .btn,
+.btn-group-vertical > .btn-group + .btn-group {
+  margin-top: -1px;
+  margin-left: 0;
+}
+.btn-group-vertical > .btn:not(:first-child):not(:last-child) {
+  border-radius: 0;
+}
+.btn-group-vertical > .btn:first-child:not(:last-child) {
+  border-top-right-radius: 4px;
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.btn-group-vertical > .btn:last-child:not(:first-child) {
+  border-bottom-left-radius: 4px;
+  border-top-right-radius: 0;
+  border-top-left-radius: 0;
+}
+.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
+  border-radius: 0;
+}
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {
+  border-top-right-radius: 0;
+  border-top-left-radius: 0;
+}
+.btn-group-justified {
+  display: table;
+  width: 100%;
+  table-layout: fixed;
+  border-collapse: separate;
+}
+.btn-group-justified > .btn,
+.btn-group-justified > .btn-group {
+  float: none;
+  display: table-cell;
+  width: 1%;
+}
+.btn-group-justified > .btn-group .btn {
+  width: 100%;
+}
+.btn-group-justified > .btn-group .dropdown-menu {
+  left: auto;
+}
+[data-toggle="buttons"] > .btn > input[type="radio"],
+[data-toggle="buttons"] > .btn > input[type="checkbox"] {
+  position: absolute;
+  z-index: -1;
+  opacity: 0;
+  filter: alpha(opacity=0);
+}
+.popover {
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 1060;
+  display: none;
+  max-width: 276px;
+  padding: 1px;
+  text-align: left;
+  background-color: #ffffff;
+  background-clip: padding-box;
+  border: 1px solid #cccccc;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  border-radius: 6px;
+  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+  box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+  white-space: normal;
+}
+.popover.top {
+  margin-top: -10px;
+}
+.popover.right {
+  margin-left: 10px;
+}
+.popover.bottom {
+  margin-top: 10px;
+}
+.popover.left {
+  margin-left: -10px;
+}
+.popover-title {
+  margin: 0;
+  padding: 8px 14px;
+  font-size: 14px;
+  font-weight: normal;
+  line-height: 18px;
+  background-color: #f7f7f7;
+  border-bottom: 1px solid #ebebeb;
+  border-radius: 5px 5px 0 0;
+}
+.popover-content {
+  padding: 9px 14px;
+}
+.popover > .arrow,
+.popover > .arrow:after {
+  position: absolute;
+  display: block;
+  width: 0;
+  height: 0;
+  border-color: transparent;
+  border-style: solid;
+}
+.popover > .arrow {
+  border-width: 11px;
+}
+.popover > .arrow:after {
+  border-width: 10px;
+  content: "";
+}
+.popover.top > .arrow {
+  left: 50%;
+  margin-left: -11px;
+  border-bottom-width: 0;
+  border-top-color: #999999;
+  border-top-color: rgba(0, 0, 0, 0.25);
+  bottom: -11px;
+}
+.popover.top > .arrow:after {
+  content: " ";
+  bottom: 1px;
+  margin-left: -10px;
+  border-bottom-width: 0;
+  border-top-color: #ffffff;
+}
+.popover.right > .arrow {
+  top: 50%;
+  left: -11px;
+  margin-top: -11px;
+  border-left-width: 0;
+  border-right-color: #999999;
+  border-right-color: rgba(0, 0, 0, 0.25);
+}
+.popover.right > .arrow:after {
+  content: " ";
+  left: 1px;
+  bottom: -10px;
+  border-left-width: 0;
+  border-right-color: #ffffff;
+}
+.popover.bottom > .arrow {
+  left: 50%;
+  margin-left: -11px;
+  border-top-width: 0;
+  border-bottom-color: #999999;
+  border-bottom-color: rgba(0, 0, 0, 0.25);
+  top: -11px;
+}
+.popover.bottom > .arrow:after {
+  content: " ";
+  top: 1px;
+  margin-left: -10px;
+  border-top-width: 0;
+  border-bottom-color: #ffffff;
+}
+.popover.left > .arrow {
+  top: 50%;
+  right: -11px;
+  margin-top: -11px;
+  border-right-width: 0;
+  border-left-color: #999999;
+  border-left-color: rgba(0, 0, 0, 0.25);
+}
+.popover.left > .arrow:after {
+  content: " ";
+  right: 1px;
+  border-right-width: 0;
+  border-left-color: #ffffff;
+  bottom: -10px;
+}
+.tour-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1100;
+  background-color: #000;
+  opacity: 0.8;
+  filter: alpha(opacity=80);
+}
+.tour-step-backdrop {
+  position: relative;
+  z-index: 1101;
+  background: inherit;
+}
+.tour-step-backdrop > td {
+  position: relative;
+  z-index: 1101;
+}
+.tour-step-background {
+  position: absolute !important;
+  z-index: 1100;
+  background: inherit;
+  border-radius: 6px;
+}
+.popover[class*="tour-"] {
+  z-index: 1100;
+}
+.popover[class*="tour-"] .popover-navigation {
+  padding: 9px 14px;
+}
+.popover[class*="tour-"] .popover-navigation *[data-role="end"] {
+  float: right;
+}
+.popover[class*="tour-"] .popover-navigation *[data-role="prev"],
+.popover[class*="tour-"] .popover-navigation *[data-role="next"],
+.popover[class*="tour-"] .popover-navigation *[data-role="end"] {
+  cursor: pointer;
+}
+.popover[class*="tour-"] .popover-navigation *[data-role="prev"].disabled,
+.popover[class*="tour-"] .popover-navigation *[data-role="next"].disabled,
+.popover[class*="tour-"] .popover-navigation *[data-role="end"].disabled {
+  cursor: default;
+}
+.popover[class*="tour-"].orphan {
+  position: fixed;
+  margin-top: 0;
+}
+.popover[class*="tour-"].orphan .arrow {
+  display: none;
+}
diff --git a/build/css/bootstrap-tour-standalone.min.css b/build/css/bootstrap-tour-standalone.min.css
new file mode 100644
index 0000000..e00c1cc
--- /dev/null
+++ b/build/css/bootstrap-tour-standalone.min.css
@@ -0,0 +1,26 @@
+/* ========================================================================
+ * bootstrap-tour - v0.10.1
+ * http://bootstraptour.com
+ * ========================================================================
+ * Copyright 2012-2013 Ulrich Sossou
+ *
+ * ========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================================
+ */
+
+/*!
+ * Bootstrap v3.1.0 (http://getbootstrap.com)
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */.btn{display:inline-block;margin-bottom:0;font-weight:400;text-align:center;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:foc [...]
\ No newline at end of file
diff --git a/build/css/bootstrap-tour.css b/build/css/bootstrap-tour.css
new file mode 100644
index 0000000..b730758
--- /dev/null
+++ b/build/css/bootstrap-tour.css
@@ -0,0 +1,73 @@
+/* ========================================================================
+ * bootstrap-tour - v0.10.1
+ * http://bootstraptour.com
+ * ========================================================================
+ * Copyright 2012-2013 Ulrich Sossou
+ *
+ * ========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================================
+ */
+
+.tour-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1100;
+  background-color: #000;
+  opacity: 0.8;
+  filter: alpha(opacity=80);
+}
+.tour-step-backdrop {
+  position: relative;
+  z-index: 1101;
+  background: inherit;
+}
+.tour-step-backdrop > td {
+  position: relative;
+  z-index: 1101;
+}
+.tour-step-background {
+  position: absolute !important;
+  z-index: 1100;
+  background: inherit;
+  border-radius: 6px;
+}
+.popover[class*="tour-"] {
+  z-index: 1100;
+}
+.popover[class*="tour-"] .popover-navigation {
+  padding: 9px 14px;
+}
+.popover[class*="tour-"] .popover-navigation *[data-role="end"] {
+  float: right;
+}
+.popover[class*="tour-"] .popover-navigation *[data-role="prev"],
+.popover[class*="tour-"] .popover-navigation *[data-role="next"],
+.popover[class*="tour-"] .popover-navigation *[data-role="end"] {
+  cursor: pointer;
+}
+.popover[class*="tour-"] .popover-navigation *[data-role="prev"].disabled,
+.popover[class*="tour-"] .popover-navigation *[data-role="next"].disabled,
+.popover[class*="tour-"] .popover-navigation *[data-role="end"].disabled {
+  cursor: default;
+}
+.popover[class*="tour-"].orphan {
+  position: fixed;
+  margin-top: 0;
+}
+.popover[class*="tour-"].orphan .arrow {
+  display: none;
+}
diff --git a/build/css/bootstrap-tour.min.css b/build/css/bootstrap-tour.min.css
new file mode 100644
index 0000000..f98810c
--- /dev/null
+++ b/build/css/bootstrap-tour.min.css
@@ -0,0 +1,22 @@
+/* ========================================================================
+ * bootstrap-tour - v0.10.1
+ * http://bootstraptour.com
+ * ========================================================================
+ * Copyright 2012-2013 Ulrich Sossou
+ *
+ * ========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================================
+ */
+
+.tour-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1100;background-color:#000;opacity:.8;filter:alpha(opacity=80)}.tour-step-backdrop{position:relative;z-index:1101;background:inherit}.tour-step-backdrop>td{position:relative;z-index:1101}.tour-step-background{position:absolute!important;z-index:1100;background:inherit;border-radius:6px}.popover[class*=tour-]{z-index:1100}.popover[class*=tour-] .popover-navigation{padding:9px 14px}.popover[class*=tour-] .popover-navigatio [...]
\ No newline at end of file
diff --git a/build/js/bootstrap-tour-standalone.js b/build/js/bootstrap-tour-standalone.js
new file mode 100644
index 0000000..9d1fd55
--- /dev/null
+++ b/build/js/bootstrap-tour-standalone.js
@@ -0,0 +1,1374 @@
+/* ========================================================================
+ * bootstrap-tour - v0.10.1
+ * http://bootstraptour.com
+ * ========================================================================
+ * Copyright 2012-2013 Ulrich Sossou
+ *
+ * ========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================================
+ */
+
+/* ========================================================================
+ * Bootstrap: tooltip.js v3.2.0
+ * http://getbootstrap.com/javascript/#tooltip
+ * Inspired by the original jQuery.tipsy by Jason Frame
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // TOOLTIP PUBLIC CLASS DEFINITION
+  // ===============================
+
+  var Tooltip = function (element, options) {
+    this.type       =
+    this.options    =
+    this.enabled    =
+    this.timeout    =
+    this.hoverState =
+    this.$element   = null
+
+    this.init('tooltip', element, options)
+  }
+
+  Tooltip.VERSION  = '3.2.0'
+
+  Tooltip.DEFAULTS = {
+    animation: true,
+    placement: 'top',
+    selector: false,
+    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
+    trigger: 'hover focus',
+    title: '',
+    delay: 0,
+    html: false,
+    container: false,
+    viewport: {
+      selector: 'body',
+      padding: 0
+    }
+  }
+
+  Tooltip.prototype.init = function (type, element, options) {
+    this.enabled   = true
+    this.type      = type
+    this.$element  = $(element)
+    this.options   = this.getOptions(options)
+    this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
+
+    var triggers = this.options.trigger.split(' ')
+
+    for (var i = triggers.length; i--;) {
+      var trigger = triggers[i]
+
+      if (trigger == 'click') {
+        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
+      } else if (trigger != 'manual') {
+        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
+        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
+
+        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
+        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
+      }
+    }
+
+    this.options.selector ?
+      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
+      this.fixTitle()
+  }
+
+  Tooltip.prototype.getDefaults = function () {
+    return Tooltip.DEFAULTS
+  }
+
+  Tooltip.prototype.getOptions = function (options) {
+    options = $.extend({}, this.getDefaults(), this.$element.data(), options)
+
+    if (options.delay && typeof options.delay == 'number') {
+      options.delay = {
+        show: options.delay,
+        hide: options.delay
+      }
+    }
+
+    return options
+  }
+
+  Tooltip.prototype.getDelegateOptions = function () {
+    var options  = {}
+    var defaults = this.getDefaults()
+
+    this._options && $.each(this._options, function (key, value) {
+      if (defaults[key] != value) options[key] = value
+    })
+
+    return options
+  }
+
+  Tooltip.prototype.enter = function (obj) {
+    var self = obj instanceof this.constructor ?
+      obj : $(obj.currentTarget).data('bs.' + this.type)
+
+    if (!self) {
+      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
+      $(obj.currentTarget).data('bs.' + this.type, self)
+    }
+
+    clearTimeout(self.timeout)
+
+    self.hoverState = 'in'
+
+    if (!self.options.delay || !self.options.delay.show) return self.show()
+
+    self.timeout = setTimeout(function () {
+      if (self.hoverState == 'in') self.show()
+    }, self.options.delay.show)
+  }
+
+  Tooltip.prototype.leave = function (obj) {
+    var self = obj instanceof this.constructor ?
+      obj : $(obj.currentTarget).data('bs.' + this.type)
+
+    if (!self) {
+      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
+      $(obj.currentTarget).data('bs.' + this.type, self)
+    }
+
+    clearTimeout(self.timeout)
+
+    self.hoverState = 'out'
+
+    if (!self.options.delay || !self.options.delay.hide) return self.hide()
+
+    self.timeout = setTimeout(function () {
+      if (self.hoverState == 'out') self.hide()
+    }, self.options.delay.hide)
+  }
+
+  Tooltip.prototype.show = function () {
+    var e = $.Event('show.bs.' + this.type)
+
+    if (this.hasContent() && this.enabled) {
+      this.$element.trigger(e)
+
+      var inDom = $.contains(document.documentElement, this.$element[0])
+      if (e.isDefaultPrevented() || !inDom) return
+      var that = this
+
+      var $tip = this.tip()
+
+      var tipId = this.getUID(this.type)
+
+      this.setContent()
+      $tip.attr('id', tipId)
+      this.$element.attr('aria-describedby', tipId)
+
+      if (this.options.animation) $tip.addClass('fade')
+
+      var placement = typeof this.options.placement == 'function' ?
+        this.options.placement.call(this, $tip[0], this.$element[0]) :
+        this.options.placement
+
+      var autoToken = /\s?auto?\s?/i
+      var autoPlace = autoToken.test(placement)
+      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
+
+      $tip
+        .detach()
+        .css({ top: 0, left: 0, display: 'block' })
+        .addClass(placement)
+        .data('bs.' + this.type, this)
+
+      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
+
+      var pos          = this.getPosition()
+      var actualWidth  = $tip[0].offsetWidth
+      var actualHeight = $tip[0].offsetHeight
+
+      if (autoPlace) {
+        var orgPlacement = placement
+        var $parent      = this.$element.parent()
+        var parentDim    = this.getPosition($parent)
+
+        placement = placement == 'bottom' && pos.top   + pos.height       + actualHeight - parentDim.scroll > parentDim.height ? 'top'    :
+                    placement == 'top'    && pos.top   - parentDim.scroll - actualHeight < 0                                   ? 'bottom' :
+                    placement == 'right'  && pos.right + actualWidth      > parentDim.width                                    ? 'left'   :
+                    placement == 'left'   && pos.left  - actualWidth      < parentDim.left                                     ? 'right'  :
+                    placement
+
+        $tip
+          .removeClass(orgPlacement)
+          .addClass(placement)
+      }
+
+      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
+
+      this.applyPlacement(calculatedOffset, placement)
+
+      var complete = function () {
+        that.$element.trigger('shown.bs.' + that.type)
+        that.hoverState = null
+      }
+
+      $.support.transition && this.$tip.hasClass('fade') ?
+        $tip
+          .one('bsTransitionEnd', complete)
+          .emulateTransitionEnd(150) :
+        complete()
+    }
+  }
+
+  Tooltip.prototype.applyPlacement = function (offset, placement) {
+    var $tip   = this.tip()
+    var width  = $tip[0].offsetWidth
+    var height = $tip[0].offsetHeight
+
+    // manually read margins because getBoundingClientRect includes difference
+    var marginTop = parseInt($tip.css('margin-top'), 10)
+    var marginLeft = parseInt($tip.css('margin-left'), 10)
+
+    // we must check for NaN for ie 8/9
+    if (isNaN(marginTop))  marginTop  = 0
+    if (isNaN(marginLeft)) marginLeft = 0
+
+    offset.top  = offset.top  + marginTop
+    offset.left = offset.left + marginLeft
+
+    // $.fn.offset doesn't round pixel values
+    // so we use setOffset directly with our own function B-0
+    $.offset.setOffset($tip[0], $.extend({
+      using: function (props) {
+        $tip.css({
+          top: Math.round(props.top),
+          left: Math.round(props.left)
+        })
+      }
+    }, offset), 0)
+
+    $tip.addClass('in')
+
+    // check to see if placing tip in new offset caused the tip to resize itself
+    var actualWidth  = $tip[0].offsetWidth
+    var actualHeight = $tip[0].offsetHeight
+
+    if (placement == 'top' && actualHeight != height) {
+      offset.top = offset.top + height - actualHeight
+    }
+
+    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
+
+    if (delta.left) offset.left += delta.left
+    else offset.top += delta.top
+
+    var arrowDelta          = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
+    var arrowPosition       = delta.left ? 'left'        : 'top'
+    var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
+
+    $tip.offset(offset)
+    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
+  }
+
+  Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
+    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
+  }
+
+  Tooltip.prototype.setContent = function () {
+    var $tip  = this.tip()
+    var title = this.getTitle()
+
+    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
+    $tip.removeClass('fade in top bottom left right')
+  }
+
+  Tooltip.prototype.hide = function () {
+    var that = this
+    var $tip = this.tip()
+    var e    = $.Event('hide.bs.' + this.type)
+
+    this.$element.removeAttr('aria-describedby')
+
+    function complete() {
+      if (that.hoverState != 'in') $tip.detach()
+      that.$element.trigger('hidden.bs.' + that.type)
+    }
+
+    this.$element.trigger(e)
+
+    if (e.isDefaultPrevented()) return
+
+    $tip.removeClass('in')
+
+    $.support.transition && this.$tip.hasClass('fade') ?
+      $tip
+        .one('bsTransitionEnd', complete)
+        .emulateTransitionEnd(150) :
+      complete()
+
+    this.hoverState = null
+
+    return this
+  }
+
+  Tooltip.prototype.fixTitle = function () {
+    var $e = this.$element
+    if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
+      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
+    }
+  }
+
+  Tooltip.prototype.hasContent = function () {
+    return this.getTitle()
+  }
+
+  Tooltip.prototype.getPosition = function ($element) {
+    $element   = $element || this.$element
+    var el     = $element[0]
+    var isBody = el.tagName == 'BODY'
+    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
+      scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
+      width:  isBody ? $(window).width()  : $element.outerWidth(),
+      height: isBody ? $(window).height() : $element.outerHeight()
+    }, isBody ? { top: 0, left: 0 } : $element.offset())
+  }
+
+  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
+    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :
+           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :
+           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
+        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }
+
+  }
+
+  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
+    var delta = { top: 0, left: 0 }
+    if (!this.$viewport) return delta
+
+    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
+    var viewportDimensions = this.getPosition(this.$viewport)
+
+    if (/right|left/.test(placement)) {
+      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
+      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
+      if (topEdgeOffset < viewportDimensions.top) { // top overflow
+        delta.top = viewportDimensions.top - topEdgeOffset
+      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
+        delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
+      }
+    } else {
+      var leftEdgeOffset  = pos.left - viewportPadding
+      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
+      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
+        delta.left = viewportDimensions.left - leftEdgeOffset
+      } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
+        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
+      }
+    }
+
+    return delta
+  }
+
+  Tooltip.prototype.getTitle = function () {
+    var title
+    var $e = this.$element
+    var o  = this.options
+
+    title = $e.attr('data-original-title')
+      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
+
+    return title
+  }
+
+  Tooltip.prototype.getUID = function (prefix) {
+    do prefix += ~~(Math.random() * 1000000)
+    while (document.getElementById(prefix))
+    return prefix
+  }
+
+  Tooltip.prototype.tip = function () {
+    return (this.$tip = this.$tip || $(this.options.template))
+  }
+
+  Tooltip.prototype.arrow = function () {
+    return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
+  }
+
+  Tooltip.prototype.validate = function () {
+    if (!this.$element[0].parentNode) {
+      this.hide()
+      this.$element = null
+      this.options  = null
+    }
+  }
+
+  Tooltip.prototype.enable = function () {
+    this.enabled = true
+  }
+
+  Tooltip.prototype.disable = function () {
+    this.enabled = false
+  }
+
+  Tooltip.prototype.toggleEnabled = function () {
+    this.enabled = !this.enabled
+  }
+
+  Tooltip.prototype.toggle = function (e) {
+    var self = this
+    if (e) {
+      self = $(e.currentTarget).data('bs.' + this.type)
+      if (!self) {
+        self = new this.constructor(e.currentTarget, this.getDelegateOptions())
+        $(e.currentTarget).data('bs.' + this.type, self)
+      }
+    }
+
+    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
+  }
+
+  Tooltip.prototype.destroy = function () {
+    clearTimeout(this.timeout)
+    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
+  }
+
+
+  // TOOLTIP PLUGIN DEFINITION
+  // =========================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.tooltip')
+      var options = typeof option == 'object' && option
+
+      if (!data && option == 'destroy') return
+      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  var old = $.fn.tooltip
+
+  $.fn.tooltip             = Plugin
+  $.fn.tooltip.Constructor = Tooltip
+
+
+  // TOOLTIP NO CONFLICT
+  // ===================
+
+  $.fn.tooltip.noConflict = function () {
+    $.fn.tooltip = old
+    return this
+  }
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: popover.js v3.2.0
+ * http://getbootstrap.com/javascript/#popovers
+ * ========================================================================
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // POPOVER PUBLIC CLASS DEFINITION
+  // ===============================
+
+  var Popover = function (element, options) {
+    this.init('popover', element, options)
+  }
+
+  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
+
+  Popover.VERSION  = '3.2.0'
+
+  Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
+    placement: 'right',
+    trigger: 'click',
+    content: '',
+    template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
+  })
+
+
+  // NOTE: POPOVER EXTENDS tooltip.js
+  // ================================
+
+  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
+
+  Popover.prototype.constructor = Popover
+
+  Popover.prototype.getDefaults = function () {
+    return Popover.DEFAULTS
+  }
+
+  Popover.prototype.setContent = function () {
+    var $tip    = this.tip()
+    var title   = this.getTitle()
+    var content = this.getContent()
+
+    $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
+    $tip.find('.popover-content').empty()[ // we use append for html objects to maintain js events
+      this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
+    ](content)
+
+    $tip.removeClass('fade top bottom left right in')
+
+    // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
+    // this manually by checking the contents.
+    if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
+  }
+
+  Popover.prototype.hasContent = function () {
+    return this.getTitle() || this.getContent()
+  }
+
+  Popover.prototype.getContent = function () {
+    var $e = this.$element
+    var o  = this.options
+
+    return $e.attr('data-content')
+      || (typeof o.content == 'function' ?
+            o.content.call($e[0]) :
+            o.content)
+  }
+
+  Popover.prototype.arrow = function () {
+    return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
+  }
+
+  Popover.prototype.tip = function () {
+    if (!this.$tip) this.$tip = $(this.options.template)
+    return this.$tip
+  }
+
+
+  // POPOVER PLUGIN DEFINITION
+  // =========================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.popover')
+      var options = typeof option == 'object' && option
+
+      if (!data && option == 'destroy') return
+      if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  var old = $.fn.popover
+
+  $.fn.popover             = Plugin
+  $.fn.popover.Constructor = Popover
+
+
+  // POPOVER NO CONFLICT
+  // ===================
+
+  $.fn.popover.noConflict = function () {
+    $.fn.popover = old
+    return this
+  }
+
+}(jQuery);
+
+(function($, window) {
+  var Tour, document;
+  document = window.document;
+  Tour = (function() {
+    function Tour(options) {
+      var storage;
+      try {
+        storage = window.localStorage;
+      } catch (_error) {
+        storage = false;
+      }
+      this._options = $.extend({
+        name: 'tour',
+        steps: [],
+        container: 'body',
+        autoscroll: true,
+        keyboard: true,
+        storage: storage,
+        debug: false,
+        backdrop: false,
+        backdropPadding: 0,
+        redirect: true,
+        orphan: false,
+        duration: false,
+        delay: false,
+        basePath: '',
+        template: '<div class="popover" role="tooltip"> <div class="arrow"></div> <h3 class="popover-title"></h3> <div class="popover-content"></div> <div class="popover-navigation"> <div class="btn-group"> <button class="btn btn-sm btn-default" data-role="prev">« Prev</button> <button class="btn btn-sm btn-default" data-role="next">Next »</button> <button class="btn btn-sm btn-default" data-role="pause-resume" data-pause-text="Pause" data-resume-text="Resume">Pause</button>  [...]
+        afterSetState: function(key, value) {},
+        afterGetState: function(key, value) {},
+        afterRemoveState: function(key) {},
+        onStart: function(tour) {},
+        onEnd: function(tour) {},
+        onShow: function(tour) {},
+        onShown: function(tour) {},
+        onHide: function(tour) {},
+        onHidden: function(tour) {},
+        onNext: function(tour) {},
+        onPrev: function(tour) {},
+        onPause: function(tour, duration) {},
+        onResume: function(tour, duration) {}
+      }, options);
+      this._force = false;
+      this._inited = false;
+      this.backdrop = {
+        overlay: null,
+        $element: null,
+        $background: null,
+        backgroundShown: false,
+        overlayElementShown: false
+      };
+      this;
+    }
+
+    Tour.prototype.addSteps = function(steps) {
+      var step, _i, _len;
+      for (_i = 0, _len = steps.length; _i < _len; _i++) {
+        step = steps[_i];
+        this.addStep(step);
+      }
+      return this;
+    };
+
+    Tour.prototype.addStep = function(step) {
+      this._options.steps.push(step);
+      return this;
+    };
+
+    Tour.prototype.getStep = function(i) {
+      if (this._options.steps[i] != null) {
+        return $.extend({
+          id: "step-" + i,
+          path: '',
+          placement: 'right',
+          title: '',
+          content: '<p></p>',
+          next: i === this._options.steps.length - 1 ? -1 : i + 1,
+          prev: i - 1,
+          animation: true,
+          container: this._options.container,
+          autoscroll: this._options.autoscroll,
+          backdrop: this._options.backdrop,
+          backdropPadding: this._options.backdropPadding,
+          redirect: this._options.redirect,
+          orphan: this._options.orphan,
+          duration: this._options.duration,
+          delay: this._options.delay,
+          template: this._options.template,
+          onShow: this._options.onShow,
+          onShown: this._options.onShown,
+          onHide: this._options.onHide,
+          onHidden: this._options.onHidden,
+          onNext: this._options.onNext,
+          onPrev: this._options.onPrev,
+          onPause: this._options.onPause,
+          onResume: this._options.onResume
+        }, this._options.steps[i]);
+      }
+    };
+
+    Tour.prototype.init = function(force) {
+      this._force = force;
+      if (this.ended()) {
+        this._debug('Tour ended, init prevented.');
+        return this;
+      }
+      this.setCurrentStep();
+      this._initMouseNavigation();
+      this._initKeyboardNavigation();
+      this._onResize((function(_this) {
+        return function() {
+          return _this.showStep(_this._current);
+        };
+      })(this));
+      if (this._current !== null) {
+        this.showStep(this._current);
+      }
+      this._inited = true;
+      return this;
+    };
+
+    Tour.prototype.start = function(force) {
+      var promise;
+      if (force == null) {
+        force = false;
+      }
+      if (!this._inited) {
+        this.init(force);
+      }
+      if (this._current === null) {
+        promise = this._makePromise(this._options.onStart != null ? this._options.onStart(this) : void 0);
+        this._callOnPromiseDone(promise, this.showStep, 0);
+      }
+      return this;
+    };
+
+    Tour.prototype.next = function() {
+      var promise;
+      promise = this.hideStep(this._current);
+      return this._callOnPromiseDone(promise, this._showNextStep);
+    };
+
+    Tour.prototype.prev = function() {
+      var promise;
+      promise = this.hideStep(this._current);
+      return this._callOnPromiseDone(promise, this._showPrevStep);
+    };
+
+    Tour.prototype.goTo = function(i) {
+      var promise;
+      promise = this.hideStep(this._current);
+      return this._callOnPromiseDone(promise, this.showStep, i);
+    };
+
+    Tour.prototype.end = function() {
+      var endHelper, promise;
+      endHelper = (function(_this) {
+        return function(e) {
+          $(document).off("click.tour-" + _this._options.name);
+          $(document).off("keyup.tour-" + _this._options.name);
+          $(window).off("resize.tour-" + _this._options.name);
+          _this._setState('end', 'yes');
+          _this._inited = false;
+          _this._force = false;
+          _this._clearTimer();
+          if (_this._options.onEnd != null) {
+            return _this._options.onEnd(_this);
+          }
+        };
+      })(this);
+      promise = this.hideStep(this._current);
+      return this._callOnPromiseDone(promise, endHelper);
+    };
+
+    Tour.prototype.ended = function() {
+      return !this._force && !!this._getState('end');
+    };
+
+    Tour.prototype.restart = function() {
+      this._removeState('current_step');
+      this._removeState('end');
+      return this.start();
+    };
+
+    Tour.prototype.pause = function() {
+      var step;
+      step = this.getStep(this._current);
+      if (!(step && step.duration)) {
+        return this;
+      }
+      this._paused = true;
+      this._duration -= new Date().getTime() - this._start;
+      window.clearTimeout(this._timer);
+      this._debug("Paused/Stopped step " + (this._current + 1) + " timer (" + this._duration + " remaining).");
+      if (step.onPause != null) {
+        return step.onPause(this, this._duration);
+      }
+    };
+
+    Tour.prototype.resume = function() {
+      var step;
+      step = this.getStep(this._current);
+      if (!(step && step.duration)) {
+        return this;
+      }
+      this._paused = false;
+      this._start = new Date().getTime();
+      this._duration = this._duration || step.duration;
+      this._timer = window.setTimeout((function(_this) {
+        return function() {
+          if (_this._isLast()) {
+            return _this.next();
+          } else {
+            return _this.end();
+          }
+        };
+      })(this), this._duration);
+      this._debug("Started step " + (this._current + 1) + " timer with duration " + this._duration);
+      if ((step.onResume != null) && this._duration !== step.duration) {
+        return step.onResume(this, this._duration);
+      }
+    };
+
+    Tour.prototype.hideStep = function(i) {
+      var hideStepHelper, promise, step;
+      step = this.getStep(i);
+      if (!step) {
+        return;
+      }
+      this._clearTimer();
+      promise = this._makePromise(step.onHide != null ? step.onHide(this, i) : void 0);
+      hideStepHelper = (function(_this) {
+        return function(e) {
+          var $element;
+          $element = $(step.element);
+          if (!($element.data('bs.popover') || $element.data('popover'))) {
+            $element = $('body');
+          }
+          $element.popover('destroy').removeClass("tour-" + _this._options.name + "-element tour-" + _this._options.name + "-" + i + "-element");
+          if (step.reflex) {
+            $element.removeClass('tour-step-element-reflex').off("" + (_this._reflexEvent(step.reflex)) + ".tour-" + _this._options.name);
+          }
+          if (step.backdrop) {
+            _this._hideBackdrop();
+          }
+          if (step.onHidden != null) {
+            return step.onHidden(_this);
+          }
+        };
+      })(this);
+      this._callOnPromiseDone(promise, hideStepHelper);
+      return promise;
+    };
+
+    Tour.prototype.showStep = function(i) {
+      var promise, showStepHelper, skipToPrevious, step;
+      if (this.ended()) {
+        this._debug('Tour ended, showStep prevented.');
+        return this;
+      }
+      step = this.getStep(i);
+      if (!step) {
+        return;
+      }
+      skipToPrevious = i < this._current;
+      promise = this._makePromise(step.onShow != null ? step.onShow(this, i) : void 0);
+      showStepHelper = (function(_this) {
+        return function(e) {
+          var current_path, path, showPopoverAndOverlay;
+          _this.setCurrentStep(i);
+          path = (function() {
+            switch ({}.toString.call(step.path)) {
+              case '[object Function]':
+                return step.path();
+              case '[object String]':
+                return this._options.basePath + step.path;
+              default:
+                return step.path;
+            }
+          }).call(_this);
+          current_path = [document.location.pathname, document.location.hash].join('');
+          if (_this._isRedirect(path, current_path)) {
+            _this._redirect(step, path);
+            return;
+          }
+          if (_this._isOrphan(step)) {
+            if (!step.orphan) {
+              _this._debug("Skip the orphan step " + (_this._current + 1) + ".\nOrphan option is false and the element does not exist or is hidden.");
+              if (skipToPrevious) {
+                _this._showPrevStep();
+              } else {
+                _this._showNextStep();
+              }
+              return;
+            }
+            _this._debug("Show the orphan step " + (_this._current + 1) + ". Orphans option is true.");
+          }
+          if (step.backdrop) {
+            _this._showBackdrop(!_this._isOrphan(step) ? step.element : void 0);
+          }
+          showPopoverAndOverlay = function() {
+            if (_this.getCurrentStep() !== i) {
+              return;
+            }
+            if ((step.element != null) && step.backdrop) {
+              _this._showOverlayElement(step);
+            }
+            _this._showPopover(step, i);
+            if (step.onShown != null) {
+              step.onShown(_this);
+            }
+            return _this._debug("Step " + (_this._current + 1) + " of " + _this._options.steps.length);
+          };
+          if (step.autoscroll) {
+            _this._scrollIntoView(step.element, showPopoverAndOverlay);
+          } else {
+            showPopoverAndOverlay();
+          }
+          if (step.duration) {
+            return _this.resume();
+          }
+        };
+      })(this);
+      if (step.delay) {
+        this._debug("Wait " + step.delay + " milliseconds to show the step " + (this._current + 1));
+        window.setTimeout((function(_this) {
+          return function() {
+            return _this._callOnPromiseDone(promise, showStepHelper);
+          };
+        })(this), step.delay);
+      } else {
+        this._callOnPromiseDone(promise, showStepHelper);
+      }
+      return promise;
+    };
+
+    Tour.prototype.getCurrentStep = function() {
+      return this._current;
+    };
+
+    Tour.prototype.setCurrentStep = function(value) {
+      if (value != null) {
+        this._current = value;
+        this._setState('current_step', value);
+      } else {
+        this._current = this._getState('current_step');
+        this._current = this._current === null ? null : parseInt(this._current, 10);
+      }
+      return this;
+    };
+
+    Tour.prototype._setState = function(key, value) {
+      var e, keyName;
+      if (this._options.storage) {
+        keyName = "" + this._options.name + "_" + key;
+        try {
+          this._options.storage.setItem(keyName, value);
+        } catch (_error) {
+          e = _error;
+          if (e.code === DOMException.QUOTA_EXCEEDED_ERR) {
+            this._debug('LocalStorage quota exceeded. State storage failed.');
+          }
+        }
+        return this._options.afterSetState(keyName, value);
+      } else {
+        if (this._state == null) {
+          this._state = {};
+        }
+        return this._state[key] = value;
+      }
+    };
+
+    Tour.prototype._removeState = function(key) {
+      var keyName;
+      if (this._options.storage) {
+        keyName = "" + this._options.name + "_" + key;
+        this._options.storage.removeItem(keyName);
+        return this._options.afterRemoveState(keyName);
+      } else {
+        if (this._state != null) {
+          return delete this._state[key];
+        }
+      }
+    };
+
+    Tour.prototype._getState = function(key) {
+      var keyName, value;
+      if (this._options.storage) {
+        keyName = "" + this._options.name + "_" + key;
+        value = this._options.storage.getItem(keyName);
+      } else {
+        if (this._state != null) {
+          value = this._state[key];
+        }
+      }
+      if (value === void 0 || value === 'null') {
+        value = null;
+      }
+      this._options.afterGetState(key, value);
+      return value;
+    };
+
+    Tour.prototype._showNextStep = function() {
+      var promise, showNextStepHelper, step;
+      step = this.getStep(this._current);
+      showNextStepHelper = (function(_this) {
+        return function(e) {
+          return _this.showStep(step.next);
+        };
+      })(this);
+      promise = this._makePromise(step.onNext != null ? step.onNext(this) : void 0);
+      return this._callOnPromiseDone(promise, showNextStepHelper);
+    };
+
+    Tour.prototype._showPrevStep = function() {
+      var promise, showPrevStepHelper, step;
+      step = this.getStep(this._current);
+      showPrevStepHelper = (function(_this) {
+        return function(e) {
+          return _this.showStep(step.prev);
+        };
+      })(this);
+      promise = this._makePromise(step.onPrev != null ? step.onPrev(this) : void 0);
+      return this._callOnPromiseDone(promise, showPrevStepHelper);
+    };
+
+    Tour.prototype._debug = function(text) {
+      if (this._options.debug) {
+        return window.console.log("Bootstrap Tour '" + this._options.name + "' | " + text);
+      }
+    };
+
+    Tour.prototype._isRedirect = function(path, currentPath) {
+      return (path != null) && path !== '' && (({}.toString.call(path) === '[object RegExp]' && !path.test(currentPath)) || ({}.toString.call(path) === '[object String]' && path.replace(/\?.*$/, '').replace(/\/?$/, '') !== currentPath.replace(/\/?$/, '')));
+    };
+
+    Tour.prototype._redirect = function(step, path) {
+      if ($.isFunction(step.redirect)) {
+        return step.redirect.call(this, path);
+      } else if (step.redirect === true) {
+        this._debug("Redirect to " + path);
+        return document.location.href = path;
+      }
+    };
+
+    Tour.prototype._isOrphan = function(step) {
+      return (step.element == null) || !$(step.element).length || $(step.element).is(':hidden') && ($(step.element)[0].namespaceURI !== 'http://www.w3.org/2000/svg');
+    };
+
+    Tour.prototype._isLast = function() {
+      return this._current < this._options.steps.length - 1;
+    };
+
+    Tour.prototype._showPopover = function(step, i) {
+      var $element, $tip, isOrphan, options;
+      $(".tour-" + this._options.name).remove();
+      options = $.extend({}, this._options);
+      isOrphan = this._isOrphan(step);
+      step.template = this._template(step, i);
+      if (isOrphan) {
+        step.element = 'body';
+        step.placement = 'top';
+      }
+      $element = $(step.element);
+      $element.addClass("tour-" + this._options.name + "-element tour-" + this._options.name + "-" + i + "-element");
+      if (step.options) {
+        $.extend(options, step.options);
+      }
+      if (step.reflex && !isOrphan) {
+        $element.addClass('tour-step-element-reflex');
+        $element.off("" + (this._reflexEvent(step.reflex)) + ".tour-" + this._options.name);
+        $element.on("" + (this._reflexEvent(step.reflex)) + ".tour-" + this._options.name, (function(_this) {
+          return function() {
+            if (_this._isLast()) {
+              return _this.next();
+            } else {
+              return _this.end();
+            }
+          };
+        })(this));
+      }
+      $element.popover({
+        placement: step.placement,
+        trigger: 'manual',
+        title: step.title,
+        content: step.content,
+        html: true,
+        animation: step.animation,
+        container: step.container,
+        template: step.template,
+        selector: step.element
+      }).popover('show');
+      $tip = $element.data('bs.popover') ? $element.data('bs.popover').tip() : $element.data('popover').tip();
+      $tip.attr('id', step.id);
+      this._reposition($tip, step);
+      if (isOrphan) {
+        return this._center($tip);
+      }
+    };
+
+    Tour.prototype._template = function(step, i) {
+      var $navigation, $next, $prev, $resume, $template;
+      $template = $.isFunction(step.template) ? $(step.template(i, step)) : $(step.template);
+      $navigation = $template.find('.popover-navigation');
+      $prev = $navigation.find('[data-role="prev"]');
+      $next = $navigation.find('[data-role="next"]');
+      $resume = $navigation.find('[data-role="pause-resume"]');
+      if (this._isOrphan(step)) {
+        $template.addClass('orphan');
+      }
+      $template.addClass("tour-" + this._options.name + " tour-" + this._options.name + "-" + i);
+      if (step.prev < 0) {
+        $prev.addClass('disabled');
+      }
+      if (step.next < 0) {
+        $next.addClass('disabled');
+      }
+      if (!step.duration) {
+        $resume.remove();
+      }
+      return $template.clone().wrap('<div>').parent().html();
+    };
+
+    Tour.prototype._reflexEvent = function(reflex) {
+      if ({}.toString.call(reflex) === '[object Boolean]') {
+        return 'click';
+      } else {
+        return reflex;
+      }
+    };
+
+    Tour.prototype._reposition = function($tip, step) {
+      var offsetBottom, offsetHeight, offsetRight, offsetWidth, originalLeft, originalTop, tipOffset;
+      offsetWidth = $tip[0].offsetWidth;
+      offsetHeight = $tip[0].offsetHeight;
+      tipOffset = $tip.offset();
+      originalLeft = tipOffset.left;
+      originalTop = tipOffset.top;
+      offsetBottom = $(document).outerHeight() - tipOffset.top - $tip.outerHeight();
+      if (offsetBottom < 0) {
+        tipOffset.top = tipOffset.top + offsetBottom;
+      }
+      offsetRight = $('html').outerWidth() - tipOffset.left - $tip.outerWidth();
+      if (offsetRight < 0) {
+        tipOffset.left = tipOffset.left + offsetRight;
+      }
+      if (tipOffset.top < 0) {
+        tipOffset.top = 0;
+      }
+      if (tipOffset.left < 0) {
+        tipOffset.left = 0;
+      }
+      $tip.offset(tipOffset);
+      if (step.placement === 'bottom' || step.placement === 'top') {
+        if (originalLeft !== tipOffset.left) {
+          return this._replaceArrow($tip, (tipOffset.left - originalLeft) * 2, offsetWidth, 'left');
+        }
+      } else {
+        if (originalTop !== tipOffset.top) {
+          return this._replaceArrow($tip, (tipOffset.top - originalTop) * 2, offsetHeight, 'top');
+        }
+      }
+    };
+
+    Tour.prototype._center = function($tip) {
+      return $tip.css('top', $(window).outerHeight() / 2 - $tip.outerHeight() / 2);
+    };
+
+    Tour.prototype._replaceArrow = function($tip, delta, dimension, position) {
+      return $tip.find('.arrow').css(position, delta ? 50 * (1 - delta / dimension) + '%' : '');
+    };
+
+    Tour.prototype._scrollIntoView = function(element, callback) {
+      var $element, $window, counter, offsetTop, scrollTop, windowHeight;
+      $element = $(element);
+      if (!$element.length) {
+        return callback();
+      }
+      $window = $(window);
+      offsetTop = $element.offset().top;
+      windowHeight = $window.height();
+      scrollTop = Math.max(0, offsetTop - (windowHeight / 2));
+      this._debug("Scroll into view. ScrollTop: " + scrollTop + ". Element offset: " + offsetTop + ". Window height: " + windowHeight + ".");
+      counter = 0;
+      return $('body, html').stop(true, true).animate({
+        scrollTop: Math.ceil(scrollTop)
+      }, (function(_this) {
+        return function() {
+          if (++counter === 2) {
+            callback();
+            return _this._debug("Scroll into view.\nAnimation end element offset: " + ($element.offset().top) + ".\nWindow height: " + ($window.height()) + ".");
+          }
+        };
+      })(this));
+    };
+
+    Tour.prototype._onResize = function(callback, timeout) {
+      return $(window).on("resize.tour-" + this._options.name, function() {
+        clearTimeout(timeout);
+        return timeout = setTimeout(callback, 100);
+      });
+    };
+
+    Tour.prototype._initMouseNavigation = function() {
+      var _this;
+      _this = this;
+      return $(document).off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='prev']").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='next']").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='end']").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='pause-resume']").on("click.tour-" + this._options.name, ".pop [...]
+        return function(e) {
+          e.preventDefault();
+          return _this.next();
+        };
+      })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='prev']", (function(_this) {
+        return function(e) {
+          e.preventDefault();
+          return _this.prev();
+        };
+      })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='end']", (function(_this) {
+        return function(e) {
+          e.preventDefault();
+          return _this.end();
+        };
+      })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='pause-resume']", function(e) {
+        var $this;
+        e.preventDefault();
+        $this = $(this);
+        $this.text(_this._paused ? $this.data('pause-text') : $this.data('resume-text'));
+        if (_this._paused) {
+          return _this.resume();
+        } else {
+          return _this.pause();
+        }
+      });
+    };
+
+    Tour.prototype._initKeyboardNavigation = function() {
+      if (!this._options.keyboard) {
+        return;
+      }
+      return $(document).on("keyup.tour-" + this._options.name, (function(_this) {
+        return function(e) {
+          if (!e.which) {
+            return;
+          }
+          switch (e.which) {
+            case 39:
+              e.preventDefault();
+              if (_this._isLast()) {
+                return _this.next();
+              } else {
+                return _this.end();
+              }
+              break;
+            case 37:
+              e.preventDefault();
+              if (_this._current > 0) {
+                return _this.prev();
+              }
+              break;
+            case 27:
+              e.preventDefault();
+              return _this.end();
+          }
+        };
+      })(this));
+    };
+
+    Tour.prototype._makePromise = function(result) {
+      if (result && $.isFunction(result.then)) {
+        return result;
+      } else {
+        return null;
+      }
+    };
+
+    Tour.prototype._callOnPromiseDone = function(promise, cb, arg) {
+      if (promise) {
+        return promise.then((function(_this) {
+          return function(e) {
+            return cb.call(_this, arg);
+          };
+        })(this));
+      } else {
+        return cb.call(this, arg);
+      }
+    };
+
+    Tour.prototype._showBackdrop = function(element) {
+      if (this.backdrop.backgroundShown) {
+        return;
+      }
+      this.backdrop = $('<div>', {
+        "class": 'tour-backdrop'
+      });
+      this.backdrop.backgroundShown = true;
+      return $('body').append(this.backdrop);
+    };
+
+    Tour.prototype._hideBackdrop = function() {
+      this._hideOverlayElement();
+      return this._hideBackground();
+    };
+
+    Tour.prototype._hideBackground = function() {
+      if (this.backdrop) {
+        this.backdrop.remove();
+        this.backdrop.overlay = null;
+        return this.backdrop.backgroundShown = false;
+      }
+    };
+
+    Tour.prototype._showOverlayElement = function(step) {
+      var $element, elementData;
+      $element = $(step.element);
+      if (!$element || $element.length === 0 || this.backdrop.overlayElementShown) {
+        return;
+      }
+      this.backdrop.overlayElementShown = true;
+      this.backdrop.$element = $element.addClass('tour-step-backdrop');
+      this.backdrop.$background = $('<div>', {
+        "class": 'tour-step-background'
+      });
+      elementData = {
+        width: $element.innerWidth(),
+        height: $element.innerHeight(),
+        offset: $element.offset()
+      };
+      this.backdrop.$background.appendTo('body');
+      if (step.backdropPadding) {
+        elementData = this._applyBackdropPadding(step.backdropPadding, elementData);
+      }
+      return this.backdrop.$background.width(elementData.width).height(elementData.height).offset(elementData.offset);
+    };
+
+    Tour.prototype._hideOverlayElement = function() {
+      if (!this.backdrop.overlayElementShown) {
+        return;
+      }
+      this.backdrop.$element.removeClass('tour-step-backdrop');
+      this.backdrop.$background.remove();
+      this.backdrop.$element = null;
+      this.backdrop.$background = null;
+      return this.backdrop.overlayElementShown = false;
+    };
+
+    Tour.prototype._applyBackdropPadding = function(padding, data) {
+      if (typeof padding === 'object') {
+        if (padding.top == null) {
+          padding.top = 0;
+        }
+        if (padding.right == null) {
+          padding.right = 0;
+        }
+        if (padding.bottom == null) {
+          padding.bottom = 0;
+        }
+        if (padding.left == null) {
+          padding.left = 0;
+        }
+        data.offset.top = data.offset.top - padding.top;
+        data.offset.left = data.offset.left - padding.left;
+        data.width = data.width + padding.left + padding.right;
+        data.height = data.height + padding.top + padding.bottom;
+      } else {
+        data.offset.top = data.offset.top - padding;
+        data.offset.left = data.offset.left - padding;
+        data.width = data.width + (padding * 2);
+        data.height = data.height + (padding * 2);
+      }
+      return data;
+    };
+
+    Tour.prototype._clearTimer = function() {
+      window.clearTimeout(this._timer);
+      this._timer = null;
+      return this._duration = null;
+    };
+
+    return Tour;
+
+  })();
+  return window.Tour = Tour;
+})(jQuery, window);
diff --git a/build/js/bootstrap-tour.js b/build/js/bootstrap-tour.js
new file mode 100644
index 0000000..1874061
--- /dev/null
+++ b/build/js/bootstrap-tour.js
@@ -0,0 +1,802 @@
+/* ========================================================================
+ * bootstrap-tour - v0.10.1
+ * http://bootstraptour.com
+ * ========================================================================
+ * Copyright 2012-2013 Ulrich Sossou
+ *
+ * ========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================================
+ */
+
+(function($, window) {
+  var Tour, document;
+  document = window.document;
+  Tour = (function() {
+    function Tour(options) {
+      var storage;
+      try {
+        storage = window.localStorage;
+      } catch (_error) {
+        storage = false;
+      }
+      this._options = $.extend({
+        name: 'tour',
+        steps: [],
+        container: 'body',
+        autoscroll: true,
+        keyboard: true,
+        storage: storage,
+        debug: false,
+        backdrop: false,
+        backdropPadding: 0,
+        redirect: true,
+        orphan: false,
+        duration: false,
+        delay: false,
+        basePath: '',
+        template: '<div class="popover" role="tooltip"> <div class="arrow"></div> <h3 class="popover-title"></h3> <div class="popover-content"></div> <div class="popover-navigation"> <div class="btn-group"> <button class="btn btn-sm btn-default" data-role="prev">« Prev</button> <button class="btn btn-sm btn-default" data-role="next">Next »</button> <button class="btn btn-sm btn-default" data-role="pause-resume" data-pause-text="Pause" data-resume-text="Resume">Pause</button>  [...]
+        afterSetState: function(key, value) {},
+        afterGetState: function(key, value) {},
+        afterRemoveState: function(key) {},
+        onStart: function(tour) {},
+        onEnd: function(tour) {},
+        onShow: function(tour) {},
+        onShown: function(tour) {},
+        onHide: function(tour) {},
+        onHidden: function(tour) {},
+        onNext: function(tour) {},
+        onPrev: function(tour) {},
+        onPause: function(tour, duration) {},
+        onResume: function(tour, duration) {}
+      }, options);
+      this._force = false;
+      this._inited = false;
+      this.backdrop = {
+        overlay: null,
+        $element: null,
+        $background: null,
+        backgroundShown: false,
+        overlayElementShown: false
+      };
+      this;
+    }
+
+    Tour.prototype.addSteps = function(steps) {
+      var step, _i, _len;
+      for (_i = 0, _len = steps.length; _i < _len; _i++) {
+        step = steps[_i];
+        this.addStep(step);
+      }
+      return this;
+    };
+
+    Tour.prototype.addStep = function(step) {
+      this._options.steps.push(step);
+      return this;
+    };
+
+    Tour.prototype.getStep = function(i) {
+      if (this._options.steps[i] != null) {
+        return $.extend({
+          id: "step-" + i,
+          path: '',
+          placement: 'right',
+          title: '',
+          content: '<p></p>',
+          next: i === this._options.steps.length - 1 ? -1 : i + 1,
+          prev: i - 1,
+          animation: true,
+          container: this._options.container,
+          autoscroll: this._options.autoscroll,
+          backdrop: this._options.backdrop,
+          backdropPadding: this._options.backdropPadding,
+          redirect: this._options.redirect,
+          orphan: this._options.orphan,
+          duration: this._options.duration,
+          delay: this._options.delay,
+          template: this._options.template,
+          onShow: this._options.onShow,
+          onShown: this._options.onShown,
+          onHide: this._options.onHide,
+          onHidden: this._options.onHidden,
+          onNext: this._options.onNext,
+          onPrev: this._options.onPrev,
+          onPause: this._options.onPause,
+          onResume: this._options.onResume
+        }, this._options.steps[i]);
+      }
+    };
+
+    Tour.prototype.init = function(force) {
+      this._force = force;
+      if (this.ended()) {
+        this._debug('Tour ended, init prevented.');
+        return this;
+      }
+      this.setCurrentStep();
+      this._initMouseNavigation();
+      this._initKeyboardNavigation();
+      this._onResize((function(_this) {
+        return function() {
+          return _this.showStep(_this._current);
+        };
+      })(this));
+      if (this._current !== null) {
+        this.showStep(this._current);
+      }
+      this._inited = true;
+      return this;
+    };
+
+    Tour.prototype.start = function(force) {
+      var promise;
+      if (force == null) {
+        force = false;
+      }
+      if (!this._inited) {
+        this.init(force);
+      }
+      if (this._current === null) {
+        promise = this._makePromise(this._options.onStart != null ? this._options.onStart(this) : void 0);
+        this._callOnPromiseDone(promise, this.showStep, 0);
+      }
+      return this;
+    };
+
+    Tour.prototype.next = function() {
+      var promise;
+      promise = this.hideStep(this._current);
+      return this._callOnPromiseDone(promise, this._showNextStep);
+    };
+
+    Tour.prototype.prev = function() {
+      var promise;
+      promise = this.hideStep(this._current);
+      return this._callOnPromiseDone(promise, this._showPrevStep);
+    };
+
+    Tour.prototype.goTo = function(i) {
+      var promise;
+      promise = this.hideStep(this._current);
+      return this._callOnPromiseDone(promise, this.showStep, i);
+    };
+
+    Tour.prototype.end = function() {
+      var endHelper, promise;
+      endHelper = (function(_this) {
+        return function(e) {
+          $(document).off("click.tour-" + _this._options.name);
+          $(document).off("keyup.tour-" + _this._options.name);
+          $(window).off("resize.tour-" + _this._options.name);
+          _this._setState('end', 'yes');
+          _this._inited = false;
+          _this._force = false;
+          _this._clearTimer();
+          if (_this._options.onEnd != null) {
+            return _this._options.onEnd(_this);
+          }
+        };
+      })(this);
+      promise = this.hideStep(this._current);
+      return this._callOnPromiseDone(promise, endHelper);
+    };
+
+    Tour.prototype.ended = function() {
+      return !this._force && !!this._getState('end');
+    };
+
+    Tour.prototype.restart = function() {
+      this._removeState('current_step');
+      this._removeState('end');
+      return this.start();
+    };
+
+    Tour.prototype.pause = function() {
+      var step;
+      step = this.getStep(this._current);
+      if (!(step && step.duration)) {
+        return this;
+      }
+      this._paused = true;
+      this._duration -= new Date().getTime() - this._start;
+      window.clearTimeout(this._timer);
+      this._debug("Paused/Stopped step " + (this._current + 1) + " timer (" + this._duration + " remaining).");
+      if (step.onPause != null) {
+        return step.onPause(this, this._duration);
+      }
+    };
+
+    Tour.prototype.resume = function() {
+      var step;
+      step = this.getStep(this._current);
+      if (!(step && step.duration)) {
+        return this;
+      }
+      this._paused = false;
+      this._start = new Date().getTime();
+      this._duration = this._duration || step.duration;
+      this._timer = window.setTimeout((function(_this) {
+        return function() {
+          if (_this._isLast()) {
+            return _this.next();
+          } else {
+            return _this.end();
+          }
+        };
+      })(this), this._duration);
+      this._debug("Started step " + (this._current + 1) + " timer with duration " + this._duration);
+      if ((step.onResume != null) && this._duration !== step.duration) {
+        return step.onResume(this, this._duration);
+      }
+    };
+
+    Tour.prototype.hideStep = function(i) {
+      var hideStepHelper, promise, step;
+      step = this.getStep(i);
+      if (!step) {
+        return;
+      }
+      this._clearTimer();
+      promise = this._makePromise(step.onHide != null ? step.onHide(this, i) : void 0);
+      hideStepHelper = (function(_this) {
+        return function(e) {
+          var $element;
+          $element = $(step.element);
+          if (!($element.data('bs.popover') || $element.data('popover'))) {
+            $element = $('body');
+          }
+          $element.popover('destroy').removeClass("tour-" + _this._options.name + "-element tour-" + _this._options.name + "-" + i + "-element");
+          if (step.reflex) {
+            $element.removeClass('tour-step-element-reflex').off("" + (_this._reflexEvent(step.reflex)) + ".tour-" + _this._options.name);
+          }
+          if (step.backdrop) {
+            _this._hideBackdrop();
+          }
+          if (step.onHidden != null) {
+            return step.onHidden(_this);
+          }
+        };
+      })(this);
+      this._callOnPromiseDone(promise, hideStepHelper);
+      return promise;
+    };
+
+    Tour.prototype.showStep = function(i) {
+      var promise, showStepHelper, skipToPrevious, step;
+      if (this.ended()) {
+        this._debug('Tour ended, showStep prevented.');
+        return this;
+      }
+      step = this.getStep(i);
+      if (!step) {
+        return;
+      }
+      skipToPrevious = i < this._current;
+      promise = this._makePromise(step.onShow != null ? step.onShow(this, i) : void 0);
+      showStepHelper = (function(_this) {
+        return function(e) {
+          var current_path, path, showPopoverAndOverlay;
+          _this.setCurrentStep(i);
+          path = (function() {
+            switch ({}.toString.call(step.path)) {
+              case '[object Function]':
+                return step.path();
+              case '[object String]':
+                return this._options.basePath + step.path;
+              default:
+                return step.path;
+            }
+          }).call(_this);
+          current_path = [document.location.pathname, document.location.hash].join('');
+          if (_this._isRedirect(path, current_path)) {
+            _this._redirect(step, path);
+            return;
+          }
+          if (_this._isOrphan(step)) {
+            if (!step.orphan) {
+              _this._debug("Skip the orphan step " + (_this._current + 1) + ".\nOrphan option is false and the element does not exist or is hidden.");
+              if (skipToPrevious) {
+                _this._showPrevStep();
+              } else {
+                _this._showNextStep();
+              }
+              return;
+            }
+            _this._debug("Show the orphan step " + (_this._current + 1) + ". Orphans option is true.");
+          }
+          if (step.backdrop) {
+            _this._showBackdrop(!_this._isOrphan(step) ? step.element : void 0);
+          }
+          showPopoverAndOverlay = function() {
+            if (_this.getCurrentStep() !== i) {
+              return;
+            }
+            if ((step.element != null) && step.backdrop) {
+              _this._showOverlayElement(step);
+            }
+            _this._showPopover(step, i);
+            if (step.onShown != null) {
+              step.onShown(_this);
+            }
+            return _this._debug("Step " + (_this._current + 1) + " of " + _this._options.steps.length);
+          };
+          if (step.autoscroll) {
+            _this._scrollIntoView(step.element, showPopoverAndOverlay);
+          } else {
+            showPopoverAndOverlay();
+          }
+          if (step.duration) {
+            return _this.resume();
+          }
+        };
+      })(this);
+      if (step.delay) {
+        this._debug("Wait " + step.delay + " milliseconds to show the step " + (this._current + 1));
+        window.setTimeout((function(_this) {
+          return function() {
+            return _this._callOnPromiseDone(promise, showStepHelper);
+          };
+        })(this), step.delay);
+      } else {
+        this._callOnPromiseDone(promise, showStepHelper);
+      }
+      return promise;
+    };
+
+    Tour.prototype.getCurrentStep = function() {
+      return this._current;
+    };
+
+    Tour.prototype.setCurrentStep = function(value) {
+      if (value != null) {
+        this._current = value;
+        this._setState('current_step', value);
+      } else {
+        this._current = this._getState('current_step');
+        this._current = this._current === null ? null : parseInt(this._current, 10);
+      }
+      return this;
+    };
+
+    Tour.prototype._setState = function(key, value) {
+      var e, keyName;
+      if (this._options.storage) {
+        keyName = "" + this._options.name + "_" + key;
+        try {
+          this._options.storage.setItem(keyName, value);
+        } catch (_error) {
+          e = _error;
+          if (e.code === DOMException.QUOTA_EXCEEDED_ERR) {
+            this._debug('LocalStorage quota exceeded. State storage failed.');
+          }
+        }
+        return this._options.afterSetState(keyName, value);
+      } else {
+        if (this._state == null) {
+          this._state = {};
+        }
+        return this._state[key] = value;
+      }
+    };
+
+    Tour.prototype._removeState = function(key) {
+      var keyName;
+      if (this._options.storage) {
+        keyName = "" + this._options.name + "_" + key;
+        this._options.storage.removeItem(keyName);
+        return this._options.afterRemoveState(keyName);
+      } else {
+        if (this._state != null) {
+          return delete this._state[key];
+        }
+      }
+    };
+
+    Tour.prototype._getState = function(key) {
+      var keyName, value;
+      if (this._options.storage) {
+        keyName = "" + this._options.name + "_" + key;
+        value = this._options.storage.getItem(keyName);
+      } else {
+        if (this._state != null) {
+          value = this._state[key];
+        }
+      }
+      if (value === void 0 || value === 'null') {
+        value = null;
+      }
+      this._options.afterGetState(key, value);
+      return value;
+    };
+
+    Tour.prototype._showNextStep = function() {
+      var promise, showNextStepHelper, step;
+      step = this.getStep(this._current);
+      showNextStepHelper = (function(_this) {
+        return function(e) {
+          return _this.showStep(step.next);
+        };
+      })(this);
+      promise = this._makePromise(step.onNext != null ? step.onNext(this) : void 0);
+      return this._callOnPromiseDone(promise, showNextStepHelper);
+    };
+
+    Tour.prototype._showPrevStep = function() {
+      var promise, showPrevStepHelper, step;
+      step = this.getStep(this._current);
+      showPrevStepHelper = (function(_this) {
+        return function(e) {
+          return _this.showStep(step.prev);
+        };
+      })(this);
+      promise = this._makePromise(step.onPrev != null ? step.onPrev(this) : void 0);
+      return this._callOnPromiseDone(promise, showPrevStepHelper);
+    };
+
+    Tour.prototype._debug = function(text) {
+      if (this._options.debug) {
+        return window.console.log("Bootstrap Tour '" + this._options.name + "' | " + text);
+      }
+    };
+
+    Tour.prototype._isRedirect = function(path, currentPath) {
+      return (path != null) && path !== '' && (({}.toString.call(path) === '[object RegExp]' && !path.test(currentPath)) || ({}.toString.call(path) === '[object String]' && path.replace(/\?.*$/, '').replace(/\/?$/, '') !== currentPath.replace(/\/?$/, '')));
+    };
+
+    Tour.prototype._redirect = function(step, path) {
+      if ($.isFunction(step.redirect)) {
+        return step.redirect.call(this, path);
+      } else if (step.redirect === true) {
+        this._debug("Redirect to " + path);
+        return document.location.href = path;
+      }
+    };
+
+    Tour.prototype._isOrphan = function(step) {
+      return (step.element == null) || !$(step.element).length || $(step.element).is(':hidden') && ($(step.element)[0].namespaceURI !== 'http://www.w3.org/2000/svg');
+    };
+
+    Tour.prototype._isLast = function() {
+      return this._current < this._options.steps.length - 1;
+    };
+
+    Tour.prototype._showPopover = function(step, i) {
+      var $element, $tip, isOrphan, options;
+      $(".tour-" + this._options.name).remove();
+      options = $.extend({}, this._options);
+      isOrphan = this._isOrphan(step);
+      step.template = this._template(step, i);
+      if (isOrphan) {
+        step.element = 'body';
+        step.placement = 'top';
+      }
+      $element = $(step.element);
+      $element.addClass("tour-" + this._options.name + "-element tour-" + this._options.name + "-" + i + "-element");
+      if (step.options) {
+        $.extend(options, step.options);
+      }
+      if (step.reflex && !isOrphan) {
+        $element.addClass('tour-step-element-reflex');
+        $element.off("" + (this._reflexEvent(step.reflex)) + ".tour-" + this._options.name);
+        $element.on("" + (this._reflexEvent(step.reflex)) + ".tour-" + this._options.name, (function(_this) {
+          return function() {
+            if (_this._isLast()) {
+              return _this.next();
+            } else {
+              return _this.end();
+            }
+          };
+        })(this));
+      }
+      $element.popover({
+        placement: step.placement,
+        trigger: 'manual',
+        title: step.title,
+        content: step.content,
+        html: true,
+        animation: step.animation,
+        container: step.container,
+        template: step.template,
+        selector: step.element
+      }).popover('show');
+      $tip = $element.data('bs.popover') ? $element.data('bs.popover').tip() : $element.data('popover').tip();
+      $tip.attr('id', step.id);
+      this._reposition($tip, step);
+      if (isOrphan) {
+        return this._center($tip);
+      }
+    };
+
+    Tour.prototype._template = function(step, i) {
+      var $navigation, $next, $prev, $resume, $template;
+      $template = $.isFunction(step.template) ? $(step.template(i, step)) : $(step.template);
+      $navigation = $template.find('.popover-navigation');
+      $prev = $navigation.find('[data-role="prev"]');
+      $next = $navigation.find('[data-role="next"]');
+      $resume = $navigation.find('[data-role="pause-resume"]');
+      if (this._isOrphan(step)) {
+        $template.addClass('orphan');
+      }
+      $template.addClass("tour-" + this._options.name + " tour-" + this._options.name + "-" + i);
+      if (step.prev < 0) {
+        $prev.addClass('disabled');
+      }
+      if (step.next < 0) {
+        $next.addClass('disabled');
+      }
+      if (!step.duration) {
+        $resume.remove();
+      }
+      return $template.clone().wrap('<div>').parent().html();
+    };
+
+    Tour.prototype._reflexEvent = function(reflex) {
+      if ({}.toString.call(reflex) === '[object Boolean]') {
+        return 'click';
+      } else {
+        return reflex;
+      }
+    };
+
+    Tour.prototype._reposition = function($tip, step) {
+      var offsetBottom, offsetHeight, offsetRight, offsetWidth, originalLeft, originalTop, tipOffset;
+      offsetWidth = $tip[0].offsetWidth;
+      offsetHeight = $tip[0].offsetHeight;
+      tipOffset = $tip.offset();
+      originalLeft = tipOffset.left;
+      originalTop = tipOffset.top;
+      offsetBottom = $(document).outerHeight() - tipOffset.top - $tip.outerHeight();
+      if (offsetBottom < 0) {
+        tipOffset.top = tipOffset.top + offsetBottom;
+      }
+      offsetRight = $('html').outerWidth() - tipOffset.left - $tip.outerWidth();
+      if (offsetRight < 0) {
+        tipOffset.left = tipOffset.left + offsetRight;
+      }
+      if (tipOffset.top < 0) {
+        tipOffset.top = 0;
+      }
+      if (tipOffset.left < 0) {
+        tipOffset.left = 0;
+      }
+      $tip.offset(tipOffset);
+      if (step.placement === 'bottom' || step.placement === 'top') {
+        if (originalLeft !== tipOffset.left) {
+          return this._replaceArrow($tip, (tipOffset.left - originalLeft) * 2, offsetWidth, 'left');
+        }
+      } else {
+        if (originalTop !== tipOffset.top) {
+          return this._replaceArrow($tip, (tipOffset.top - originalTop) * 2, offsetHeight, 'top');
+        }
+      }
+    };
+
+    Tour.prototype._center = function($tip) {
+      return $tip.css('top', $(window).outerHeight() / 2 - $tip.outerHeight() / 2);
+    };
+
+    Tour.prototype._replaceArrow = function($tip, delta, dimension, position) {
+      return $tip.find('.arrow').css(position, delta ? 50 * (1 - delta / dimension) + '%' : '');
+    };
+
+    Tour.prototype._scrollIntoView = function(element, callback) {
+      var $element, $window, counter, offsetTop, scrollTop, windowHeight;
+      $element = $(element);
+      if (!$element.length) {
+        return callback();
+      }
+      $window = $(window);
+      offsetTop = $element.offset().top;
+      windowHeight = $window.height();
+      scrollTop = Math.max(0, offsetTop - (windowHeight / 2));
+      this._debug("Scroll into view. ScrollTop: " + scrollTop + ". Element offset: " + offsetTop + ". Window height: " + windowHeight + ".");
+      counter = 0;
+      return $('body, html').stop(true, true).animate({
+        scrollTop: Math.ceil(scrollTop)
+      }, (function(_this) {
+        return function() {
+          if (++counter === 2) {
+            callback();
+            return _this._debug("Scroll into view.\nAnimation end element offset: " + ($element.offset().top) + ".\nWindow height: " + ($window.height()) + ".");
+          }
+        };
+      })(this));
+    };
+
+    Tour.prototype._onResize = function(callback, timeout) {
+      return $(window).on("resize.tour-" + this._options.name, function() {
+        clearTimeout(timeout);
+        return timeout = setTimeout(callback, 100);
+      });
+    };
+
+    Tour.prototype._initMouseNavigation = function() {
+      var _this;
+      _this = this;
+      return $(document).off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='prev']").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='next']").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='end']").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='pause-resume']").on("click.tour-" + this._options.name, ".pop [...]
+        return function(e) {
+          e.preventDefault();
+          return _this.next();
+        };
+      })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='prev']", (function(_this) {
+        return function(e) {
+          e.preventDefault();
+          return _this.prev();
+        };
+      })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='end']", (function(_this) {
+        return function(e) {
+          e.preventDefault();
+          return _this.end();
+        };
+      })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='pause-resume']", function(e) {
+        var $this;
+        e.preventDefault();
+        $this = $(this);
+        $this.text(_this._paused ? $this.data('pause-text') : $this.data('resume-text'));
+        if (_this._paused) {
+          return _this.resume();
+        } else {
+          return _this.pause();
+        }
+      });
+    };
+
+    Tour.prototype._initKeyboardNavigation = function() {
+      if (!this._options.keyboard) {
+        return;
+      }
+      return $(document).on("keyup.tour-" + this._options.name, (function(_this) {
+        return function(e) {
+          if (!e.which) {
+            return;
+          }
+          switch (e.which) {
+            case 39:
+              e.preventDefault();
+              if (_this._isLast()) {
+                return _this.next();
+              } else {
+                return _this.end();
+              }
+              break;
+            case 37:
+              e.preventDefault();
+              if (_this._current > 0) {
+                return _this.prev();
+              }
+              break;
+            case 27:
+              e.preventDefault();
+              return _this.end();
+          }
+        };
+      })(this));
+    };
+
+    Tour.prototype._makePromise = function(result) {
+      if (result && $.isFunction(result.then)) {
+        return result;
+      } else {
+        return null;
+      }
+    };
+
+    Tour.prototype._callOnPromiseDone = function(promise, cb, arg) {
+      if (promise) {
+        return promise.then((function(_this) {
+          return function(e) {
+            return cb.call(_this, arg);
+          };
+        })(this));
+      } else {
+        return cb.call(this, arg);
+      }
+    };
+
+    Tour.prototype._showBackdrop = function(element) {
+      if (this.backdrop.backgroundShown) {
+        return;
+      }
+      this.backdrop = $('<div>', {
+        "class": 'tour-backdrop'
+      });
+      this.backdrop.backgroundShown = true;
+      return $('body').append(this.backdrop);
+    };
+
+    Tour.prototype._hideBackdrop = function() {
+      this._hideOverlayElement();
+      return this._hideBackground();
+    };
+
+    Tour.prototype._hideBackground = function() {
+      if (this.backdrop) {
+        this.backdrop.remove();
+        this.backdrop.overlay = null;
+        return this.backdrop.backgroundShown = false;
+      }
+    };
+
+    Tour.prototype._showOverlayElement = function(step) {
+      var $element, elementData;
+      $element = $(step.element);
+      if (!$element || $element.length === 0 || this.backdrop.overlayElementShown) {
+        return;
+      }
+      this.backdrop.overlayElementShown = true;
+      this.backdrop.$element = $element.addClass('tour-step-backdrop');
+      this.backdrop.$background = $('<div>', {
+        "class": 'tour-step-background'
+      });
+      elementData = {
+        width: $element.innerWidth(),
+        height: $element.innerHeight(),
+        offset: $element.offset()
+      };
+      this.backdrop.$background.appendTo('body');
+      if (step.backdropPadding) {
+        elementData = this._applyBackdropPadding(step.backdropPadding, elementData);
+      }
+      return this.backdrop.$background.width(elementData.width).height(elementData.height).offset(elementData.offset);
+    };
+
+    Tour.prototype._hideOverlayElement = function() {
+      if (!this.backdrop.overlayElementShown) {
+        return;
+      }
+      this.backdrop.$element.removeClass('tour-step-backdrop');
+      this.backdrop.$background.remove();
+      this.backdrop.$element = null;
+      this.backdrop.$background = null;
+      return this.backdrop.overlayElementShown = false;
+    };
+
+    Tour.prototype._applyBackdropPadding = function(padding, data) {
+      if (typeof padding === 'object') {
+        if (padding.top == null) {
+          padding.top = 0;
+        }
+        if (padding.right == null) {
+          padding.right = 0;
+        }
+        if (padding.bottom == null) {
+          padding.bottom = 0;
+        }
+        if (padding.left == null) {
+          padding.left = 0;
+        }
+        data.offset.top = data.offset.top - padding.top;
+        data.offset.left = data.offset.left - padding.left;
+        data.width = data.width + padding.left + padding.right;
+        data.height = data.height + padding.top + padding.bottom;
+      } else {
+        data.offset.top = data.offset.top - padding;
+        data.offset.left = data.offset.left - padding;
+        data.width = data.width + (padding * 2);
+        data.height = data.height + (padding * 2);
+      }
+      return data;
+    };
+
+    Tour.prototype._clearTimer = function() {
+      window.clearTimeout(this._timer);
+      this._timer = null;
+      return this._duration = null;
+    };
+
+    return Tour;
+
+  })();
+  return window.Tour = Tour;
+})(jQuery, window);
diff --git a/coffeelint.json b/coffeelint.json
new file mode 100644
index 0000000..4187a7d
--- /dev/null
+++ b/coffeelint.json
@@ -0,0 +1,127 @@
+{
+    "coffeescript_error": {
+        "level": "error"
+    },
+    "arrow_spacing": {
+        "name": "arrow_spacing",
+        "level": "ignore"
+    },
+    "no_tabs": {
+        "name": "no_tabs",
+        "level": "error"
+    },
+    "no_trailing_whitespace": {
+        "name": "no_trailing_whitespace",
+        "level": "error",
+        "allowed_in_comments": false,
+        "allowed_in_empty_lines": false
+    },
+    "max_line_length": {
+        "name": "max_line_length",
+        "value": 120,
+        "level": "error",
+        "limitComments": true
+    },
+    "line_endings": {
+        "name": "line_endings",
+        "level": "warn",
+        "value": "unix"
+    },
+    "no_trailing_semicolons": {
+        "name": "no_trailing_semicolons",
+        "level": "error"
+    },
+    "indentation": {
+        "name": "indentation",
+        "value": 2,
+        "level": "error"
+    },
+    "camel_case_classes": {
+        "name": "camel_case_classes",
+        "level": "error"
+    },
+    "colon_assignment_spacing": {
+        "name": "colon_assignment_spacing",
+        "level": "ignore",
+        "spacing": {
+            "left": 0,
+            "right": 0
+        }
+    },
+    "no_implicit_braces": {
+        "name": "no_implicit_braces",
+        "level": "ignore",
+        "strict": true
+    },
+    "no_plusplus": {
+        "name": "no_plusplus",
+        "level": "ignore"
+    },
+    "no_throwing_strings": {
+        "name": "no_throwing_strings",
+        "level": "error"
+    },
+    "no_backticks": {
+        "name": "no_backticks",
+        "level": "error"
+    },
+    "no_implicit_parens": {
+        "name": "no_implicit_parens",
+        "strict": true,
+        "level": "ignore"
+    },
+    "no_empty_param_list": {
+        "name": "no_empty_param_list",
+        "level": "error"
+    },
+    "no_stand_alone_at": {
+        "name": "no_stand_alone_at",
+        "level": "ignore"
+    },
+    "space_operators": {
+        "name": "space_operators",
+        "level": "ignore"
+    },
+    "duplicate_key": {
+        "name": "duplicate_key",
+        "level": "error"
+    },
+    "empty_constructor_needs_parens": {
+        "name": "empty_constructor_needs_parens",
+        "level": "ignore"
+    },
+    "cyclomatic_complexity": {
+        "name": "cyclomatic_complexity",
+        "value": 10,
+        "level": "ignore"
+    },
+    "newlines_after_classes": {
+        "name": "newlines_after_classes",
+        "value": 3,
+        "level": "error"
+    },
+    "no_unnecessary_fat_arrows": {
+        "name": "no_unnecessary_fat_arrows",
+        "level": "error"
+    },
+    "missing_fat_arrows": {
+        "name": "missing_fat_arrows",
+        "level": "ignore"
+    },
+    "non_empty_constructor_needs_parens": {
+        "name": "non_empty_constructor_needs_parens",
+        "level": "ignore"
+    },
+    "no_unnecessary_double_quotes": {
+        "name": "no_unnecessary_double_quotes",
+        "level": "error"
+    },
+    "no_debugger": {
+        "name": "no_debugger",
+        "level": "warn"
+    },
+    "no_interpolation_in_single_quotes": {
+        "name": "no_interpolation_in_single_quotes",
+        "level": "ignore"
+    }
+}
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..bb3ba64
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,13 @@
+{
+    "name": "sorich87/bootstrap-tour",
+    "description": "Quick and easy way to build your product tours with Bootstrap Popovers.",
+    "type":"component",
+    "url":"https://github.com/sorich87/bootstrap-tour.git",
+    "homepage": "http://bootstraptour.com/",
+    "description": "Show people how to use your web site",
+    "keywords": [
+        "bootstrap",
+        "tour"
+    ],
+    "license": "Apache-2.0"
+}
diff --git a/gulpfile.coffee b/gulpfile.coffee
new file mode 100644
index 0000000..cc1665c
--- /dev/null
+++ b/gulpfile.coffee
@@ -0,0 +1,214 @@
+gulp = require 'gulp'
+$ = require('gulp-load-plugins') lazy: false
+extend = require('util')._extend
+streamqueue = require 'streamqueue'
+spawn = require('child_process').spawn
+karma = require('karma').server
+karmaConfig = require './karma.json'
+pkg = require './package.json'
+name = pkg.name
+
+paths =
+  src: './src'
+  dist: './build'
+  test: './test'
+  docs: './docs'
+server =
+  host: 'localhost'
+  port: 3000
+banner = '''
+  /* ========================================================================
+   * <%= pkg.name %> - v<%= pkg.version %>
+   * <%= pkg.homepage %>
+   * ========================================================================
+   * Copyright 2012-2013 <%= pkg.author.name %>
+   *
+   * ========================================================================
+   * Licensed under the Apache License, Version 2.0 (the "License");
+   * you may not use this file except in compliance with the License.
+   * You may obtain a copy of the License at
+   *
+   *     http://www.apache.org/licenses/LICENSE-2.0
+   *
+   * Unless required by applicable law or agreed to in writing, software
+   * distributed under the License is distributed on an "AS IS" BASIS,
+   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   * See the License for the specific language governing permissions and
+   * limitations under the License.
+   * ========================================================================
+   */
+
+
+  '''
+
+# coffee
+gulp.task 'coffee', ->
+  gulp
+  .src "#{paths.src}/coffee/#{name}.coffee"
+  .pipe $.changed "#{paths.dist}/js"
+  .pipe $.coffeelint './coffeelint.json'
+  .pipe $.coffeelint.reporter()
+    .on 'error', $.util.log
+  .pipe $.coffee bare: true
+    .on 'error', $.util.log
+  .pipe $.header banner, pkg: pkg
+  .pipe gulp.dest "#{paths.dist}/js"
+  .pipe gulp.dest "#{paths.src}/docs/assets/js"
+  .pipe gulp.dest paths.test
+  .pipe $.uglify()
+  .pipe $.header banner, pkg: pkg
+  .pipe $.rename suffix: '.min'
+  .pipe gulp.dest "#{paths.dist}/js"
+
+gulp.task 'coffee-standalone', ->
+  streamqueue objectMode: true,
+    gulp
+    .src [
+      "./bower_components/bootstrap/js/tooltip.js"
+      "./bower_components/bootstrap/js/popover.js"
+    ]
+  ,
+    gulp
+    .src "#{paths.src}/coffee/#{name}.coffee"
+    .pipe $.changed "#{paths.dist}/js"
+    .pipe $.coffeelint './coffeelint.json'
+    .pipe $.coffeelint.reporter()
+      .on 'error', $.util.log
+    .pipe $.coffee bare: true
+      .on 'error', $.util.log
+  .pipe $.concat "#{name}-standalone.js"
+  .pipe $.header banner, pkg: pkg
+  .pipe gulp.dest "#{paths.dist}/js"
+  .pipe $.uglify()
+  .pipe $.header banner, pkg: pkg
+  .pipe $.rename suffix: '.min'
+  .pipe gulp.dest "#{paths.dist}/js"
+
+# less
+gulp.task 'less', ->
+  gulp
+  .src [
+    "#{paths.src}/less/#{name}.less"
+  ]
+  .pipe $.changed "#{paths.dist}/css"
+  .pipe $.less()
+    .on 'error', $.util.log
+  .pipe $.header banner, pkg: pkg
+  .pipe gulp.dest "#{paths.dist}/css"
+  .pipe gulp.dest "#{paths.src}/docs/assets/css"
+  .pipe $.less compress: true, cleancss: true
+  .pipe $.header banner, pkg: pkg
+  .pipe $.rename suffix: '.min'
+  .pipe gulp.dest "#{paths.dist}/css"
+
+gulp.task 'less-standalone', ->
+  gulp
+  .src "#{paths.src}/less/#{name}-standalone.less"
+  .pipe $.changed "#{paths.dist}/css"
+  .pipe $.less()
+    .on 'error', $.util.log
+  .pipe $.header banner, pkg: pkg
+  .pipe gulp.dest "#{paths.dist}/css"
+  .pipe $.less compress: true, cleancss: true
+  .pipe $.header banner, pkg: pkg
+  .pipe $.rename suffix: '.min'
+  .pipe gulp.dest "#{paths.dist}/css"
+
+# test
+gulp.task 'test-coffee', ['coffee'], ->
+  gulp
+  .src "#{paths.src}/coffee/#{name}.spec.coffee"
+  .pipe $.changed paths.test
+  .pipe $.coffeelint './coffeelint.json'
+  .pipe $.coffeelint.reporter()
+    .on 'error', $.util.log
+  .pipe $.coffee()
+    .on 'error', $.util.log
+  .pipe gulp.dest paths.test
+
+gulp.task 'test-go', ['test-coffee'], (done) ->
+  karma.start extend(karmaConfig, singleRun: true), done
+
+# docs
+gulp.task 'docs-build', ['coffee', 'less'], (done) ->
+  spawn 'jekyll', ['build']
+    .on 'close', done
+
+gulp.task 'docs-copy', ['docs-build'], ->
+  gulp
+  .src "./bower_components/**/*"
+  .pipe gulp.dest "#{paths.docs}/components"
+
+gulp.task 'docs-coffee', ['docs-build'], ->
+  gulp
+  .src "#{paths.src}/coffee/#{name}.docs.coffee"
+  .pipe $.changed "#{paths.docs}/assets/js"
+  .pipe $.coffeelint.reporter()
+    .on 'error', $.util.log
+  .pipe $.coffee()
+    .on 'error', $.util.log
+  .pipe gulp.dest "#{paths.docs}/assets/js"
+
+# clean
+gulp.task 'clean-dist', ->
+  gulp
+  .src paths.dist
+  .pipe $.clean()
+
+gulp.task 'clean-test', ->
+  gulp
+  .src paths.test
+  .pipe $.clean()
+
+gulp.task 'clean-docs', ->
+  gulp
+  .src paths.docs
+  .pipe $.clean()
+
+# connect
+gulp.task 'connect', ['docs'], ->
+  $.connect.server
+    root: [paths.docs]
+    host: server.host
+    port: server.port
+    livereload: true
+
+# open
+gulp.task 'open', ['connect'], ->
+  gulp
+  .src "#{paths.docs}/index.html"
+  .pipe $.open '', url: "http://#{server.host}:#{server.port}"
+
+gulp.task 'watch', ['connect'], ->
+  gulp.watch "#{paths.src}/coffee/#{name}.coffee", ['coffee', 'coffee-standalone']
+  gulp.watch "#{paths.src}/less/#{name}.less", ["less", "less-standalone"]
+  gulp.watch "#{paths.src}/less/#{name}-standalone.less", ['less-standalone']
+  gulp.watch "#{paths.src}/coffee/#{name}.spec.coffee", ['test']
+  gulp.watch [
+    "#{paths.src}/coffee/#{name}.docs.coffee"
+    "#{paths.src}/docs/**/*"
+  ], ['docs']
+  gulp.watch [
+    "#{paths.dist}/js/**/*.js"
+    "#{paths.dist}/css/**/*.css"
+    "#{paths.docs}/index.html"
+  ]
+  .on 'change', (event) ->
+    gulp.src event.path
+    .pipe $.connect.reload()
+
+# bump
+gulp.task 'bump', ['test'], ->
+  bumpType = $.util.env.type || 'patch'
+
+  return gulp.src(['./bower.json', './package.json', './smart.json'])
+    .pipe $.bump(type: bumpType)
+    .pipe gulp.dest('./')
+
+# tasks
+gulp.task 'clean', ['clean-dist', 'clean-test', 'clean-docs']
+gulp.task 'server', ['connect', 'open', 'watch']
+gulp.task 'dist', ['coffee', 'coffee-standalone', 'less', 'less-standalone']
+gulp.task 'test', ['coffee', 'test-coffee', 'test-go']
+gulp.task 'docs', ['coffee', 'less', 'docs-build', 'docs-copy', 'docs-coffee']
+gulp.task 'default', ['dist', 'docs', 'server']
diff --git a/gulpfile.js b/gulpfile.js
new file mode 100644
index 0000000..c7f2b8b
--- /dev/null
+++ b/gulpfile.js
@@ -0,0 +1,2 @@
+require('coffee-script/register');
+require('./gulpfile.coffee');
diff --git a/karma.json b/karma.json
new file mode 100644
index 0000000..74fb1f2
--- /dev/null
+++ b/karma.json
@@ -0,0 +1,19 @@
+{
+  "frameworks": ["jasmine"],
+  "files": [
+    "bower_components/jquery/dist/jquery.js",
+    "bower_components/bootstrap/dist/js/bootstrap.js",
+    "test/bootstrap-tour.js",
+    "test/bootstrap-tour.spec.js"
+  ],
+  "reporters": ["progress"],
+  "port": 9876,
+  "colors": true,
+  "autoWatch": true,
+  "browsers": ["Firefox"],
+  "singleRun": false,
+  "plugins": [
+    "karma-jasmine",
+    "karma-firefox-launcher"
+  ]
+}
diff --git a/package.js b/package.js
new file mode 100644
index 0000000..de35ef2
--- /dev/null
+++ b/package.js
@@ -0,0 +1,3 @@
+Package.describe({
+  summary: "Quick and easy way to build your product tours with Bootstrap Popovers."
+});
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..fcdf9df
--- /dev/null
+++ b/package.json
@@ -0,0 +1,83 @@
+{
+  "name": "bootstrap-tour",
+  "description": "Quick and easy way to build your product tours with Bootstrap Popovers.",
+  "version": "0.10.2",
+  "keywords": [
+    "tour",
+    "bootstrap",
+    "js",
+    "tour",
+    "intro"
+  ],
+  "homepage": "http://bootstraptour.com",
+  "author": {
+    "name": "Ulrich Sossou",
+    "email": "sorich87 at gmail.com",
+    "url": "http://ulrichsossou.com"
+  },
+  "contributors": [
+    {
+      "name": "Emanuele Marchi",
+      "email": "emanuele at lostcrew.it",
+      "url": "http://lostcrew.it"
+    },
+    {
+      "name": "Nicola Molinari",
+      "email": "emmenko at gmail.com"
+    }
+  ],
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/sorich87/bootstrap-tour.git"
+  },
+  "bugs": {
+    "url": "https://github.com/sorich87/bootstrap-tour/issues"
+  },
+  "licenses": [
+    {
+      "type": "Apache-2.0",
+      "url": "http://www.apache.org/licenses/LICENSE-2.0"
+    }
+  ],
+  "dependencies": {
+    "bootstrap": "~3",
+    "jquery": ">=1.8"
+  },
+  "devDependencies": {
+    "coffee-script": "~1.7.1",
+    "gulp": "~3.8.6",
+    "gulp-bump": "^0.1.11",
+    "gulp-changed": "~0.4.1",
+    "gulp-clean": "~0.3.1",
+    "gulp-coffee": "~2.1.1",
+    "gulp-coffeelint": "~0.3.3",
+    "gulp-concat": "~2.3.4",
+    "gulp-connect": "~2.0.6",
+    "gulp-header": "~1.0.5",
+    "gulp-jasmine": "~0.3.0",
+    "gulp-karma": "0.0.4",
+    "gulp-less": "~1.3.2",
+    "gulp-load-plugins": "~0.5.3",
+    "gulp-open": "~0.2.8",
+    "gulp-rename": "~1.2.0",
+    "gulp-uglify": "~0.3.1",
+    "gulp-util": "~3.0.0",
+    "karma": "~0.12.19",
+    "karma-firefox-launcher": "~0.1.3",
+    "karma-jasmine": "~0.1.5",
+    "streamqueue": "0.1.1"
+  },
+  "engines": {
+    "node": ">= 0.8.0"
+  },
+  "main": [
+    "./build/js/bootstrap-tour.js",
+    "./build/js/bootstrap-tour-standalone.js",
+    "./build/css/bootstrap-tour.css",
+    "./build/css/bootstrap-tour-standalone.css"
+  ],
+  "scripts": {
+    "build": "gulp dist",
+    "test": "gulp test"
+  }
+}
diff --git a/smart.json b/smart.json
new file mode 100644
index 0000000..a3184aa
--- /dev/null
+++ b/smart.json
@@ -0,0 +1,9 @@
+{
+  "name": "bootstrap-tour",
+  "description": "Quick and easy way to build your product tours with Bootstrap Popovers.",
+  "homepage": "http://bootstraptour.com",
+  "author": "Ulrich Sossou <sorich87 at gmail.com> (http://ulrichsossou.com)",
+  "version": "0.10.2",
+  "git": "https://github.com/sorich87/bootstrap-tour.git",
+  "packages": {}
+}
diff --git a/src/coffee/bootstrap-tour.coffee b/src/coffee/bootstrap-tour.coffee
new file mode 100644
index 0000000..43fa372
--- /dev/null
+++ b/src/coffee/bootstrap-tour.coffee
@@ -0,0 +1,655 @@
+(($, window) ->
+  document = window.document
+
+  class Tour
+    constructor: (options) ->
+      try
+        storage = window.localStorage
+      catch
+        # localStorage may be unavailable due to security settings
+        storage = false
+      @_options = $.extend
+        name: 'tour'
+        steps: []
+        container: 'body'
+        autoscroll: true
+        keyboard: true
+        storage: storage
+        debug: false
+        backdrop: false
+        backdropPadding: 0
+        redirect: true
+        orphan: false
+        duration: false
+        delay: false
+        basePath: ''
+        template: '<div class="popover" role="tooltip">
+          <div class="arrow"></div>
+          <h3 class="popover-title"></h3>
+          <div class="popover-content"></div>
+          <div class="popover-navigation">
+            <div class="btn-group">
+              <button class="btn btn-sm btn-default" data-role="prev">« Prev</button>
+              <button class="btn btn-sm btn-default" data-role="next">Next »</button>
+              <button class="btn btn-sm btn-default"
+                      data-role="pause-resume"
+                      data-pause-text="Pause"
+                      data-resume-text="Resume">Pause</button>
+            </div>
+            <button class="btn btn-sm btn-default" data-role="end">End tour</button>
+          </div>
+        </div>'
+        afterSetState: (key, value) ->
+        afterGetState: (key, value) ->
+        afterRemoveState: (key) ->
+        onStart: (tour) ->
+        onEnd: (tour) ->
+        onShow: (tour) ->
+        onShown: (tour) ->
+        onHide: (tour) ->
+        onHidden: (tour) ->
+        onNext: (tour) ->
+        onPrev: (tour) ->
+        onPause: (tour, duration) ->
+        onResume: (tour, duration) ->
+      , options
+
+      @_force = false
+      @_inited = false
+      @backdrop =
+        overlay: null
+        $element: null
+        $background: null
+        backgroundShown: false
+        overlayElementShown: false
+      @
+
+    # Add multiple steps
+    addSteps: (steps) ->
+      @addStep step for step in steps
+      @
+
+    # Add a new step
+    addStep: (step) ->
+      @_options.steps.push step
+      @
+
+    # Get a step by its indice
+    getStep: (i) ->
+      if @_options.steps[i]?
+        $.extend
+          id: "step-#{i}"
+          path: ''
+          placement: 'right'
+          title: ''
+          content: '<p></p>' # no empty as default, otherwise popover won't show up
+          next: if i is @_options.steps.length - 1 then -1 else i + 1
+          prev: i - 1
+          animation: true
+          container: @_options.container
+          autoscroll: @_options.autoscroll
+          backdrop: @_options.backdrop
+          backdropPadding: @_options.backdropPadding
+          redirect: @_options.redirect
+          orphan: @_options.orphan
+          duration: @_options.duration
+          delay: @_options.delay
+          template: @_options.template
+          onShow: @_options.onShow
+          onShown: @_options.onShown
+          onHide: @_options.onHide
+          onHidden: @_options.onHidden
+          onNext: @_options.onNext
+          onPrev: @_options.onPrev
+          onPause: @_options.onPause
+          onResume: @_options.onResume
+        , @_options.steps[i]
+
+    # Setup event bindings and continue a tour that has already started
+    init: (force) ->
+      @_force = force
+
+      if @ended()
+        @_debug 'Tour ended, init prevented.'
+        return @
+
+      @setCurrentStep()
+
+      @_initMouseNavigation()
+      @_initKeyboardNavigation()
+
+      # Reshow popover on window resize using debounced resize
+      @_onResize => @showStep @_current
+
+      # Continue a tour that had started on a previous page load
+      @showStep @_current unless @_current is null
+
+      @_inited = true
+      @
+
+    # Start tour from current step
+    start: (force = false) ->
+      @init force unless @_inited # Backward compatibility
+
+      if @_current is null
+        promise = @_makePromise(@_options.onStart(@) if @_options.onStart?)
+        @_callOnPromiseDone(promise, @showStep, 0)
+      @
+
+    # Hide current step and show next step
+    next: ->
+      promise = @hideStep @_current
+      @_callOnPromiseDone promise, @_showNextStep
+
+    # Hide current step and show prev step
+    prev: ->
+      promise = @hideStep @_current
+      @_callOnPromiseDone promise, @_showPrevStep
+
+    goTo: (i) ->
+      promise = @hideStep @_current
+      @_callOnPromiseDone promise, @showStep, i
+
+    # End tour
+    end: ->
+      endHelper = (e) =>
+        $(document).off "click.tour-#{@_options.name}"
+        $(document).off "keyup.tour-#{@_options.name}"
+        $(window).off "resize.tour-#{@_options.name}"
+        @_setState('end', 'yes')
+        @_inited = false
+        @_force = false
+
+        @_clearTimer()
+
+        @_options.onEnd(@) if @_options.onEnd?
+
+      promise = @hideStep(@_current)
+      @_callOnPromiseDone(promise, endHelper)
+
+    # Verify if tour is enabled
+    ended: ->
+      not @_force and not not @_getState 'end'
+
+    # Restart tour
+    restart: ->
+      @_removeState 'current_step'
+      @_removeState 'end'
+      @start()
+
+    # Pause step timer
+    pause: ->
+      step = @getStep @_current
+      return @ unless step and step.duration
+
+      @_paused = true
+      @_duration -= new Date().getTime() - @_start
+      window.clearTimeout(@_timer)
+
+      @_debug "Paused/Stopped step #{@_current + 1} timer (#{@_duration} remaining)."
+
+      step.onPause @, @_duration if step.onPause?
+
+    # Resume step timer
+    resume: ->
+      step = @getStep @_current
+      return @ unless step and step.duration
+
+      @_paused = false
+      @_start = new Date().getTime()
+      @_duration = @_duration or step.duration
+      @_timer = window.setTimeout =>
+        if @_isLast() then @next() else @end()
+      , @_duration
+
+      @_debug "Started step #{@_current + 1} timer with duration #{@_duration}"
+
+      step.onResume @, @_duration if step.onResume? and @_duration isnt step.duration
+
+    # Hide the specified step
+    hideStep: (i) ->
+      step = @getStep i
+      return unless step
+
+      @_clearTimer()
+
+      # If onHide returns a promise, let's wait until it's done to execute
+      promise = @_makePromise(step.onHide @, i if step.onHide?)
+
+      hideStepHelper = (e) =>
+        $element = $ step.element
+        $element = $('body') unless $element.data('bs.popover') or $element.data('popover')
+        $element
+        .popover('destroy')
+        .removeClass "tour-#{@_options.name}-element tour-#{@_options.name}-#{i}-element"
+        if step.reflex
+          $element
+          .removeClass('tour-step-element-reflex')
+          .off "#{@_reflexEvent(step.reflex)}.tour-#{@_options.name}"
+
+        @_hideBackdrop() if step.backdrop
+
+        step.onHidden(@) if step.onHidden?
+
+      @_callOnPromiseDone promise, hideStepHelper
+      promise
+
+    # Show the specified step
+    showStep: (i) ->
+      if @ended()
+        @_debug 'Tour ended, showStep prevented.'
+        return @
+
+      step = @getStep i
+      return unless step
+
+      skipToPrevious = i < @_current
+
+      # If onShow returns a promise, let's wait until it's done to execute
+      promise = @_makePromise(step.onShow @, i if step.onShow?)
+
+      showStepHelper = (e) =>
+        @setCurrentStep i
+
+        # Support string or function for path
+        path = switch ({}).toString.call step.path
+          when '[object Function]' then step.path()
+          when '[object String]' then @_options.basePath + step.path
+          else step.path
+
+        # Redirect to step path if not already there
+        current_path = [document.location.pathname, document.location.hash].join('')
+        if @_isRedirect path, current_path
+          @_redirect step, path
+          return
+
+        # Skip if step is orphan and orphan options is false
+        if @_isOrphan step
+          if not step.orphan
+            @_debug """Skip the orphan step #{@_current + 1}.
+            Orphan option is false and the element does not exist or is hidden."""
+            if skipToPrevious then @_showPrevStep() else @_showNextStep()
+            return
+
+          @_debug "Show the orphan step #{@_current + 1}. Orphans option is true."
+
+        # Show backdrop
+        @_showBackdrop(step.element unless @_isOrphan step) if step.backdrop
+
+        showPopoverAndOverlay = =>
+          return if @getCurrentStep() isnt i
+
+          @_showOverlayElement step if step.element? and step.backdrop
+          @_showPopover step, i
+          step.onShown @ if step.onShown?
+          @_debug "Step #{@_current + 1} of #{@_options.steps.length}"
+
+        if step.autoscroll
+          @_scrollIntoView step.element, showPopoverAndOverlay
+        else
+          showPopoverAndOverlay()
+
+        # Play step timer
+        @resume() if step.duration
+
+      if step.delay
+        @_debug "Wait #{step.delay} milliseconds to show the step #{@_current + 1}"
+        window.setTimeout =>
+          @_callOnPromiseDone promise, showStepHelper
+        , step.delay
+      else
+        @_callOnPromiseDone promise, showStepHelper
+
+      promise
+
+    getCurrentStep: ->
+      @_current
+
+    # Setup current step variable
+    setCurrentStep: (value) ->
+      if value?
+        @_current = value
+        @_setState 'current_step', value
+      else
+        @_current = @_getState 'current_step'
+        @_current = if @_current is null then null else parseInt @_current, 10
+      @
+
+    # Set a state in storage
+    _setState: (key, value) ->
+      if @_options.storage
+        keyName = "#{@_options.name}_#{key}"
+        try @_options.storage.setItem keyName, value
+        catch e
+          if e.code is DOMException.QUOTA_EXCEEDED_ERR
+            @_debug 'LocalStorage quota exceeded. State storage failed.'
+        @_options.afterSetState keyName, value
+      else
+        @_state ?= {}
+        @_state[key] = value
+
+    # Remove the current state from the storage layer
+    _removeState: (key) ->
+      if @_options.storage
+        keyName = "#{@_options.name}_#{key}"
+        @_options.storage.removeItem keyName
+        @_options.afterRemoveState keyName
+      else
+        delete @_state[key] if @_state?
+
+    # Get the current state from the storage layer
+    _getState: (key) ->
+      if @_options.storage
+        keyName = "#{@_options.name}_#{key}"
+        value = @_options.storage.getItem keyName
+      else
+        value = @_state[key] if @_state?
+
+      value = null if value is undefined or value is 'null'
+
+      @_options.afterGetState key, value
+      return value
+
+    # Show next step
+    _showNextStep: ->
+      step = @getStep @_current
+      showNextStepHelper = (e) => @showStep step.next
+
+      promise = @_makePromise(step.onNext @ if step.onNext?)
+      @_callOnPromiseDone promise, showNextStepHelper
+
+    # Show prev step
+    _showPrevStep: ->
+      step = @getStep @_current
+      showPrevStepHelper = (e) => @showStep step.prev
+
+      promise = @_makePromise(step.onPrev @ if step.onPrev?)
+      @_callOnPromiseDone promise, showPrevStepHelper
+
+    # Print message in console
+    _debug: (text) ->
+      window.console.log "Bootstrap Tour '#{@_options.name}' | #{text}" if @_options.debug
+
+    # Check if step path equals current document path
+    _isRedirect: (path, currentPath) ->
+      path? and path isnt '' and (
+        (({}).toString.call(path) is '[object RegExp]' and not path.test currentPath) or
+        (({}).toString.call(path) is '[object String]' and
+          path.replace(/\?.*$/, '').replace(/\/?$/, '') isnt currentPath.replace(/\/?$/, ''))
+      )
+
+    # Execute the redirect
+    _redirect: (step, path) ->
+      if $.isFunction step.redirect
+        step.redirect.call this, path
+      else if step.redirect is true
+        @_debug "Redirect to #{path}"
+        document.location.href = path
+
+    _isOrphan: (step) ->
+      # Do not check for is(':hidden') on svg elements. jQuery does not work properly on svg.
+      not step.element? or
+      not $(step.element).length or
+      $(step.element).is(':hidden') and
+      ($(step.element)[0].namespaceURI isnt 'http://www.w3.org/2000/svg')
+
+    _isLast: ->
+      @_current < @_options.steps.length - 1
+
+    # Show step popover
+    _showPopover: (step, i) ->
+      # Remove previously existing tour popovers. This prevents displaying of
+      # multiple inactive popovers when user navigates the tour too quickly.
+      $(".tour-#{@_options.name}").remove()
+
+      options = $.extend {}, @_options
+      isOrphan = @_isOrphan step
+
+      step.template = @_template step, i
+
+      if isOrphan
+        step.element = 'body'
+        step.placement = 'top'
+
+      $element = $ step.element
+      $element.addClass "tour-#{@_options.name}-element tour-#{@_options.name}-#{i}-element"
+
+      $.extend options, step.options if step.options
+      if step.reflex and not isOrphan
+        $element.addClass('tour-step-element-reflex')
+        $element.off("#{@_reflexEvent(step.reflex)}.tour-#{@_options.name}")
+        $element.on "#{@_reflexEvent(step.reflex)}.tour-#{@_options.name}", =>
+          if @_isLast() then @next() else @end()
+
+      $element
+      .popover(
+        placement: step.placement
+        trigger: 'manual'
+        title: step.title
+        content: step.content
+        html: true
+        animation: step.animation
+        container: step.container
+        template: step.template
+        selector: step.element
+      )
+      .popover 'show'
+
+      # Tip adjustment
+      $tip = if $element.data 'bs.popover' then $element.data('bs.popover').tip() else $element.data('popover').tip()
+      $tip.attr 'id', step.id
+      @_reposition $tip, step
+      @_center $tip if isOrphan
+
+    # Get popover template
+    _template: (step, i) ->
+      $template = if $.isFunction step.template then $(step.template i, step) else $(step.template)
+      $navigation = $template.find '.popover-navigation'
+      $prev = $navigation.find '[data-role="prev"]'
+      $next = $navigation.find '[data-role="next"]'
+      $resume = $navigation.find '[data-role="pause-resume"]'
+
+      $template.addClass 'orphan' if @_isOrphan step
+      $template.addClass "tour-#{@_options.name} tour-#{@_options.name}-#{i}"
+      $prev.addClass('disabled') if step.prev < 0
+      $next.addClass('disabled') if step.next < 0
+      $resume.remove() unless step.duration
+      $template.clone().wrap('<div>').parent().html()
+
+    _reflexEvent: (reflex) ->
+      if ({}).toString.call(reflex) is '[object Boolean]' then 'click' else reflex
+
+    # Prevent popover from crossing over the edge of the window
+    _reposition: ($tip, step) ->
+      offsetWidth = $tip[0].offsetWidth
+      offsetHeight = $tip[0].offsetHeight
+
+      tipOffset = $tip.offset()
+      originalLeft = tipOffset.left
+      originalTop = tipOffset.top
+      offsetBottom = $(document).outerHeight() - tipOffset.top - $tip.outerHeight()
+      tipOffset.top = tipOffset.top + offsetBottom if offsetBottom < 0
+      offsetRight = $('html').outerWidth() - tipOffset.left - $tip.outerWidth()
+      tipOffset.left = tipOffset.left + offsetRight if offsetRight < 0
+
+      tipOffset.top = 0 if tipOffset.top < 0
+      tipOffset.left = 0 if tipOffset.left < 0
+
+      $tip.offset(tipOffset)
+
+      # Reposition the arrow
+      if step.placement is 'bottom' or step.placement is 'top'
+        if originalLeft isnt tipOffset.left
+          @_replaceArrow $tip, (tipOffset.left - originalLeft) * 2, offsetWidth, 'left'
+      else
+        if originalTop isnt tipOffset.top
+          @_replaceArrow $tip, (tipOffset.top - originalTop) * 2, offsetHeight, 'top'
+
+    # Center popover in the page
+    _center: ($tip) ->
+      $tip.css('top', $(window).outerHeight() / 2 - $tip.outerHeight() / 2)
+
+    # Copy pasted from bootstrap-tooltip.js with some alterations
+    _replaceArrow: ($tip, delta, dimension, position)->
+      $tip.find('.arrow').css position, if delta then 50 * (1 - delta / dimension) + '%' else ''
+
+    # Scroll to the popup if it is not in the viewport
+    _scrollIntoView: (element, callback) ->
+      $element = $(element)
+      return callback() unless $element.length
+
+      $window = $(window)
+      offsetTop = $element.offset().top
+      windowHeight = $window.height()
+      scrollTop = Math.max(0, offsetTop - (windowHeight / 2))
+
+      @_debug "Scroll into view. ScrollTop: #{scrollTop}. Element offset: #{offsetTop}. Window height: #{windowHeight}."
+      counter = 0
+      $('body, html').stop(true, true).animate
+        scrollTop: Math.ceil(scrollTop),
+        =>
+          if ++counter is 2
+            callback()
+            @_debug """Scroll into view.
+            Animation end element offset: #{$element.offset().top}.
+            Window height: #{$window.height()}."""
+
+    # Debounced window resize
+    _onResize: (callback, timeout) ->
+      $(window).on "resize.tour-#{@_options.name}", ->
+        clearTimeout(timeout)
+        timeout = setTimeout(callback, 100)
+
+    # Event bindings for mouse navigation
+    _initMouseNavigation: ->
+      _this = @
+
+      # Go to next step after click on element with attribute 'data-role=next'
+      # Go to previous step after click on element with attribute 'data-role=prev'
+      # End tour after click on element with attribute 'data-role=end'
+      # Pause/resume tour after click on element with attribute 'data-role=pause-resume'
+      $(document)
+      .off("click.tour-#{@_options.name}", ".popover.tour-#{@_options.name} *[data-role='prev']")
+      .off("click.tour-#{@_options.name}", ".popover.tour-#{@_options.name} *[data-role='next']")
+      .off("click.tour-#{@_options.name}", ".popover.tour-#{@_options.name} *[data-role='end']")
+      .off("click.tour-#{@_options.name}", ".popover.tour-#{@_options.name} *[data-role='pause-resume']")
+      .on "click.tour-#{@_options.name}", ".popover.tour-#{@_options.name} *[data-role='next']", (e) =>
+        e.preventDefault()
+        @next()
+      .on "click.tour-#{@_options.name}", ".popover.tour-#{@_options.name} *[data-role='prev']", (e) =>
+        e.preventDefault()
+        @prev()
+      .on "click.tour-#{@_options.name}", ".popover.tour-#{@_options.name} *[data-role='end']", (e) =>
+        e.preventDefault()
+        @end()
+      .on "click.tour-#{@_options.name}", ".popover.tour-#{@_options.name} *[data-role='pause-resume']", (e) ->
+        e.preventDefault()
+        $this = $ @
+
+        $this.text if _this._paused then $this.data 'pause-text' else $this.data 'resume-text'
+        if _this._paused then _this.resume() else _this.pause()
+
+    # Keyboard navigation
+    _initKeyboardNavigation: ->
+      return unless @_options.keyboard
+
+      $(document).on "keyup.tour-#{@_options.name}", (e) =>
+        return unless e.which
+
+        switch e.which
+          when 39
+            e.preventDefault()
+            if @_isLast() then @next() else @end()
+          when 37
+            e.preventDefault()
+            @prev() if @_current > 0
+          when 27
+            e.preventDefault()
+            @end()
+
+    # Checks if the result of a callback is a promise
+    _makePromise: (result) ->
+      if result and $.isFunction(result.then) then result else null
+
+    _callOnPromiseDone: (promise, cb, arg) ->
+      if promise
+        promise.then (e) =>
+          cb.call(@, arg)
+      else
+        cb.call(@, arg)
+
+    _showBackdrop: (element) ->
+      return if @backdrop.backgroundShown
+
+      @backdrop = $ '<div>', class: 'tour-backdrop'
+      @backdrop.backgroundShown = true
+      $('body').append @backdrop
+
+    _hideBackdrop: ->
+      @_hideOverlayElement()
+      @_hideBackground()
+
+    _hideBackground: ->
+      if @backdrop
+        @backdrop.remove()
+        @backdrop.overlay = null
+        @backdrop.backgroundShown = false
+
+    _showOverlayElement: (step) ->
+      $element = $ step.element
+
+      return if not $element or $element.length is 0 or @backdrop.overlayElementShown
+
+      @backdrop.overlayElementShown = true
+      @backdrop.$element = $element.addClass 'tour-step-backdrop'
+      @backdrop.$background = $ '<div>', class: 'tour-step-background'
+      elementData =
+        width: $element.innerWidth()
+        height: $element.innerHeight()
+        offset: $element.offset()
+
+      @backdrop.$background.appendTo('body')
+
+      elementData = @_applyBackdropPadding step.backdropPadding, elementData if step.backdropPadding
+      @backdrop
+      .$background
+      .width(elementData.width)
+      .height(elementData.height)
+      .offset(elementData.offset)
+
+    _hideOverlayElement: ->
+      return unless @backdrop.overlayElementShown
+
+      @backdrop.$element.removeClass 'tour-step-backdrop'
+      @backdrop.$background.remove()
+      @backdrop.$element = null
+      @backdrop.$background = null
+      @backdrop.overlayElementShown = false
+
+    _applyBackdropPadding: (padding, data) ->
+      if typeof padding is 'object'
+        padding.top ?= 0
+        padding.right ?= 0
+        padding.bottom ?= 0
+        padding.left ?= 0
+
+        data.offset.top = data.offset.top - padding.top
+        data.offset.left = data.offset.left - padding.left
+        data.width = data.width + padding.left + padding.right
+        data.height = data.height + padding.top + padding.bottom
+      else
+        data.offset.top = data.offset.top - padding
+        data.offset.left = data.offset.left - padding
+        data.width = data.width + (padding * 2)
+        data.height = data.height + (padding * 2)
+
+      data
+
+    _clearTimer: ->
+      window.clearTimeout @_timer
+      @_timer = null
+      @_duration = null
+
+  window.Tour = Tour
+
+) jQuery, window
diff --git a/src/coffee/bootstrap-tour.docs.coffee b/src/coffee/bootstrap-tour.docs.coffee
new file mode 100644
index 0000000..87fc21a
--- /dev/null
+++ b/src/coffee/bootstrap-tour.docs.coffee
@@ -0,0 +1,94 @@
+$ ->
+  $demo = $("#demo")
+  duration = 5000
+  remaining = duration
+  tour = new Tour(
+    onStart: -> $demo.addClass "disabled", true
+    onEnd: -> $demo.removeClass "disabled", true
+    debug: true
+    steps: [
+      path: "/"
+      element: "#demo"
+      placement: "bottom"
+      title: "Welcome to Bootstrap Tour!"
+      content: """
+      Introduce new users to your product by walking them through it step by step.
+      """
+    ,
+      path: "/"
+      element: "#usage"
+      placement: "top"
+      title: "A super simple setup"
+      content: "Easy is better, right? The tour is up and running with just a
+      few options and steps."
+    ,
+      path: "/"
+      element: "#license"
+      placement: "top"
+      title: "Best of all, it's free!"
+      content: "Yeah! Free as in beer... or speech. Use and abuse, but don't forget to contribute!"
+    ,
+      path: "/api"
+      element: "#options"
+      placement: "top"
+      title: "Flexibilty and expressiveness"
+      content: """
+      There are more options for those who want to get on the dark side.<br>
+      Power to the people!
+      """
+      reflex: true
+    ,
+      path: "/api"
+      element: "#duration"
+      placement: "top"
+      title: "Automagically expiring step",
+      content: """
+      A new addition: make your tour (or step) completely automatic. You set the duration, Bootstrap
+      Tour does the rest. For instance, this step will disappear in <em>5</em> seconds.
+      """
+      duration: 5000
+    ,
+      path: "/api"
+      element: "#methods table"
+      placement: "top"
+      title: "A new shiny Backdrop option"
+      content: """
+      If you need to highlight the current step's element, activate the backdrop and you won't lose
+      the focus anymore!
+      """
+      backdrop: true
+    ,
+      path: "/api"
+      element: "#reflex"
+      placement: "bottom"
+      title: "Reflex mode"
+      content: "Reflex mode is enabled, click on the text in the cell to continue!"
+      reflex: true
+    ,
+      path: "/api"
+      title: "And support for orphan steps"
+      content: """
+      If you activate the orphan property, the step(s) are shown centered in the page, and you can
+      forget to specify element and placement!
+      """
+      orphan: true
+      onHidden: -> window.location.assign "/"
+    ]
+  )
+  .init()
+
+  $('<div class="alert alert-info alert-dismissable"><button class="close" data-dismiss="alert" aria-hidden="true">×</button>You ended the demo tour. <a href="#" data-demo>Restart the demo tour.</a></div>').prependTo(".content").alert() if tour.ended()
+
+  $(document).on "click", "[data-demo]", (e) ->
+    e.preventDefault()
+    return if $(this).hasClass "disabled"
+    tour.restart()
+    $(".alert").alert "close"
+
+  $("html").smoothScroll()
+
+  $(".gravatar").each ->
+    $this = $(@)
+    email = md5 $this.data "email"
+
+    $(@).attr "src", "http://www.gravatar.com/avatar/#{email}?s=60"
diff --git a/src/coffee/bootstrap-tour.spec.coffee b/src/coffee/bootstrap-tour.spec.coffee
new file mode 100644
index 0000000..4b05fea
--- /dev/null
+++ b/src/coffee/bootstrap-tour.spec.coffee
@@ -0,0 +1,775 @@
+describe 'Bootstrap Tour', ->
+
+  beforeEach ->
+    $.support.transition = false
+    $.fx.off = true
+
+  afterEach ->
+    tour = @tour
+    @tour._setState('current_step', null)
+    @tour._setState('end', null)
+    $.each @tour._options.steps, (i, s) ->
+      $element = $(tour.getStep(i).element)
+
+      $element
+      .popover('destroy')
+      .removeData('bs.popover')
+      $element.remove()
+
+  it 'should set the tour options', ->
+    @tour = new Tour
+      name: 'test'
+      afterSetState: -> true
+      afterGetState: -> true
+    expect(@tour._options.name).toBe 'test'
+    expect(@tour._options.afterGetState).toBeTruthy
+    expect(@tour._options.afterSetState).toBeTruthy
+
+  it 'should have `tour` as default name', ->
+    @tour = new Tour
+    expect(@tour._options.name).toBe 'tour'
+
+  it 'should accept an array of steps', ->
+    @tour = new Tour
+    expect(@tour._options.steps).toEqual [] # tour accepts an array of steps
+
+  it '`_setState` should save state as localStorage item', ->
+    @tour = new Tour
+    @tour._setState('test', 'yes')
+    expect(window.localStorage.getItem('tour_test')).toBe 'yes'
+
+  it '`_setState` should execute storage.setItem function if provided', ->
+    aliasKeyName = undefined
+    aliasValue = undefined
+
+    @tour = new Tour
+      name: 'test'
+      storage:
+        setItem: (keyName, value) ->
+          aliasKeyName = keyName
+          aliasValue = value
+        getItem: (value) ->
+          return aliasValue
+
+    @tour._setState('save', 'yes')
+    expect(aliasKeyName).toBe 'test_save'
+    expect(aliasValue).toBe 'yes'
+
+  it '`_setState` should save state internally if storage is false', ->
+    @tour = new Tour
+      storage: false
+    @tour._setState('test', 'yes')
+    expect(@tour._state['test']).toBe 'yes'
+
+  it '`_removeState` should remove state localStorage item', ->
+    @tour = new Tour
+    @tour._setState('test', 'yes')
+    @tour._removeState('test')
+    expect(window.localStorage.getItem('tour_test')).toBe null
+
+  it '`_removeState` should remove state internally if storage is false', ->
+    @tour = new Tour
+      storage: false
+    @tour._setState('test', 'yes')
+    @tour._removeState('test')
+    expect(@tour._state['test']).toBeUndefined()
+
+  it '`_getState` should get state localStorage items', ->
+    @tour = new Tour
+    @tour._setState('test', 'yes')
+    expect(@tour._getState('test')).toBe 'yes'
+    window.localStorage.setItem('tour_test', null)
+
+  it '`_getState` should get the internal state if storage is false', ->
+    @tour = new Tour
+      storage: false
+    @tour._setState('test', 'yes')
+    expect(@tour._getState('test')).toBe 'yes'
+
+  it '`addStep` should add a step', ->
+    @tour = new Tour
+    step = element: $('<div></div>').appendTo('body')
+    @tour.addStep(step)
+    expect(@tour._options.steps).toEqual [step]
+
+  it '`addSteps` should add multiple step', ->
+    @tour = new Tour
+    firstStep = element: $('<div></div>').appendTo('body')
+    secondStep = element: $('<div></div>').appendTo('body')
+    @tour.addSteps([firstStep, secondStep])
+    expect(@tour._options.steps).toEqual [firstStep, secondStep]
+
+  it 'step should have an id', ->
+    @tour = new Tour
+    $element = $('<div></div>').appendTo('body')
+    @tour.addStep({element: $element})
+    @tour.start()
+    expect($element.data('bs.popover').tip().attr('id')).toBe 'step-0' # tour runs onStart when the first step shown
+
+  it 'with `onStart` option should run the callback before showing the first step', ->
+    tour_test = 0
+    @tour = new Tour
+      onStart: -> tour_test += 2
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+    expect(tour_test).toBe 2 # tour runs onStart when the first step shown
+
+  it 'with `onEnd` option should run the callback after hiding the last step', ->
+    tour_test = 0
+    @tour = new Tour
+      onEnd: -> tour_test += 2
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+    @tour.end()
+    expect(tour_test).toBe 2 # tour runs onEnd when the last step hidden
+
+  it 'with `onShow` option should run the callback before showing the step', ->
+    tour_test = 0
+    @tour = new Tour
+      onShow: -> tour_test += 2
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+    expect(tour_test).toBe 2 # tour runs onShow when first step shown
+    @tour.next()
+    expect(tour_test).toBe 4 # tour runs onShow when next step shown
+
+  it 'with `onShown` option should run the callback after showing the step', ->
+    tour_test = 0
+    @tour = new Tour
+      onShown: -> tour_test += 2
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+    expect(tour_test).toBe 2 # tour runs onShown after first step shown
+
+
+  it 'with `onHide` option should run the callback before hiding the step', ->
+    tour_test = 0
+    @tour = new Tour
+      onHide: -> tour_test += 2
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+    @tour.next()
+    expect(tour_test).toBe 2 # tour runs onHide when first step hidden
+    @tour.hideStep(1)
+    expect(tour_test).toBe 4 # tour runs onHide when next step hidden
+
+  it 'with onHidden option should run the callback after hiding the step', ->
+    tour_test = 0
+    @tour = new Tour
+      onHidden: -> tour_test += 2
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+    @tour.next()
+    expect(tour_test).toBe 2 # tour runs onHidden after first step hidden
+    @tour.next()
+    expect(tour_test).toBe 4 # tour runs onHidden after next step hidden
+
+  it '`addStep` with onShow option should run the callback before showing the step', ->
+    tour_test = 0
+    @tour = new Tour
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.addStep
+      element: $('<div></div>').appendTo('body')
+      onShow: -> tour_test = 2
+    @tour.start()
+    expect(tour_test).toBe 0 # tour does not run onShow when step not shown
+    @tour.next()
+    expect(tour_test).toBe 2 # tour runs onShow when step shown
+
+  it '`addStep` with onHide option should run the callback before hiding the step', ->
+    tour_test = 0
+    @tour = new Tour
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.addStep
+      element: $('<div></div>').appendTo('body')
+      onHide: -> tour_test = 2
+    @tour.start()
+    @tour.next()
+    expect(tour_test).toBe 0 # tour does not run onHide when step not hidden
+    @tour.hideStep(1)
+    expect(tour_test).toBe 2 # tour runs onHide when step hidden
+
+  it '`getStep` should get a step', ->
+    @tour = new Tour
+    step =
+      element: $('<div></div>').appendTo('body')
+      id: 'step-0'
+      path: 'test'
+      placement: 'left'
+      title: 'Test'
+      content: 'Just a test'
+      next: 2
+      prev: -1
+      animation: false
+      autoscroll: true
+      container: 'body'
+      backdrop: false
+      backdropPadding: 0
+      redirect: true
+      orphan: false
+      duration: false
+      delay: false
+      template: '<div class="popover">
+        <div class="arrow"></div>
+        <h3 class="popover-title"></h3>
+        <div class="popover-content"></div>
+        <nav class="popover-navigation">
+          <div class="btn-group">
+            <button class="btn btn-sm btn-default" data-role="prev">« Prev</button>
+            <button class="btn btn-sm btn-default" data-role="next">Next »</button>
+          </div>
+          <button class="btn btn-sm btn-default" data-role="end">End tour</button>
+        </nav>
+      </div>'
+      onShow: (tour) ->
+      onShown: (tour) ->
+      onHide: (tour) ->
+      onHidden: (tour) ->
+      onNext: (tour) ->
+      onPrev: (tour) ->
+      onPause: (tour) ->
+      onResume: (tour) ->
+    @tour.addStep(step)
+    # remove properties that we don't want to check from both steps object
+    expect(@tour.getStep(0)).toEqual step
+
+  it '`start` should start a tour', ->
+    @tour = new Tour
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+    expect($('.popover').length).toBe 1
+
+  it '`init` should continue a tour', ->
+    @tour = new Tour
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour._setState('current_step', 0)
+    @tour.init()
+    expect($('.popover').length).toBe 1
+
+  it '`init` should not continue a tour that ended', ->
+    @tour = new Tour
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour._setState('current_step', 0)
+    @tour._setState('end', 'yes')
+    @tour.init()
+    expect($('.popover').length).toBe 0 # previously ended tour don't start again
+
+  it '`init`(true) should force continuing a tour that ended', ->
+    @tour = new Tour
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour._setState('current_step', 0)
+    @tour._setState('end', 'yes')
+    @tour.init(true)
+    expect($('.popover').length).toBe 1 # previously ended tour starts again if forced to
+
+  it '`next` should hide current step and show next step', ->
+    @tour = new Tour
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+    @tour.next()
+    expect(@tour.getStep(0).element.data('bs.popover')).toBeUndefined() # tour hides current step
+    expect(@tour.getStep(1).element.data('bs.popover').tip().filter(':visible').length).toBe 1 # tour shows next step
+
+  it '`end` should hide current step and set end state', ->
+    @tour = new Tour
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+    @tour.end()
+    expect(@tour.getStep(0).element.data('bs.popover')).toBeUndefined() # tour hides current step
+    expect(@tour._getState('end')).toBe 'yes'
+
+  it '`ended` should return true if tour ended and false if not', ->
+    @tour = new Tour
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+    expect(@tour.ended()).toBe false
+    @tour.end()
+    expect(@tour.ended()).toBe true
+
+  it '`ended` should always return false if tour started by force', ->
+    @tour = new Tour
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.end()
+    @tour.start(true)
+    expect(@tour.ended()).toBe false
+
+  it '`restart` should clear all states and start tour', ->
+    @tour = new Tour
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+    @tour.next()
+    @tour.end()
+    @tour.restart()
+    expect(@tour._getState('end')).toBe null
+    expect(@tour._current).toBe 0
+    expect($('.popover').length).toBe 1 # tour starts
+
+  it '`hideStep` should hide a step', ->
+    @tour = new Tour
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+    @tour.hideStep(0)
+    expect(@tour.getStep(0).element.data('bs.popover')).toBeUndefined()
+
+  it '`showStep` should set a step and show it', ->
+    @tour = new Tour
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.showStep(1)
+    expect(@tour._current).toBe 1
+    expect($('.popover').length).toBe 1 # tour shows one step
+    expect(@tour.getStep(1).element.data('bs.popover').tip().filter(':visible').length).toBe 1 # tour shows correct step
+
+  it '`showStep` should not show anything when the step does not exist', ->
+    @tour = new Tour
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.showStep(2)
+    expect($('.popover').length).toBe 0
+
+  it '`showStep` should execute template if it is a function', ->
+    @tour = new Tour
+    @tour.addStep
+      element: $('<div></div>').appendTo('body')
+      template: -> '<div class="popover"></div>'
+    @tour.showStep(0)
+    expect($('.popover').length).toBe 1
+
+  it '`getStep` should add disabled classes to the first and last popover buttons', ->
+    @tour = new Tour
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.showStep(0)
+    expect($('.popover [data-role="prev"]').hasClass('disabled')).toBe true
+    @tour.showStep(1)
+    expect($('.popover [data-role="next"]').hasClass('disabled')).toBe true
+
+  it '`setCurrentStep` should set the current step', ->
+    @tour = new Tour
+    @tour.setCurrentStep(4)
+    expect(@tour._current).toBe 4 # tour sets current step if passed a value
+    @tour._setState('current_step', 2)
+    @tour.setCurrentStep()
+    expect(@tour._current).toBe 2 # tour reads current step state if not passed a value
+
+  it '`goTo` should show the specified step', ->
+    @tour = new Tour
+    @tour.addStep({element: $('<div></div>').appendTo('body')})
+    @tour.addStep({element: $('<div></div>').appendTo('body')})
+    @tour.goTo(1)
+    expect(@tour.getStep(1).element.data('bs.popover').tip().filter(':visible').length).toBe 1
+
+  it '`next` should show the next step', ->
+    @tour = new Tour
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+    @tour.next()
+    expect(@tour.getStep(1).element.data('bs.popover').tip().filter(':visible').length).toBe 1
+
+  it '`prev` should show the previous step', ->
+    @tour = new Tour
+    @tour.addStep({element: $('<div></div>').appendTo('body')})
+    @tour.addStep({element: $('<div></div>').appendTo('body')})
+    @tour.goTo(1)
+    @tour.prev()
+    expect(@tour.getStep(0).element.data('bs.popover').tip().filter(':visible').length).toBe 1
+
+  it '`showStep` should show multiple step on the same element', ->
+    @tour = new Tour
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+
+    # tour show the first step
+    expect(@tour.getStep(0).element.data('bs.popover').tip().filter(':visible').length).toBe 1
+    @tour.next()
+
+    # tour show the second step on the same element
+    expect(@tour.getStep(1).element.data('bs.popover').tip().filter(':visible').length).toBe 1
+
+  it 'should evaluate `path correctly', ->
+    @tour = new Tour
+
+    # redirect if path doesn't match current path
+    expect(@tour._isRedirect('/anotherpath', '/somepath')).toBe true
+    # don't redirect if no path
+    expect(@tour._isRedirect(undefined, '/')).toBe false
+    # don't redirect if path empty
+    expect(@tour._isRedirect('', '/')).toBe false
+    # don't redirect if path matches current path
+    expect(@tour._isRedirect('/somepath', '/somepath')).toBe false
+    # don't redirect if path with slash matches current path
+    expect(@tour._isRedirect('/somepath/', '/somepath')).toBe false
+    # don't redirect if path matches current path with slash
+    expect(@tour._isRedirect('/somepath', '/somepath/')).toBe false
+    # don't redirect if path with query params matches current path
+    expect(@tour._isRedirect('/somepath?search=true', '/somepath')).toBe false
+    # don't redirect if path with slash and query params matches current path
+    expect(@tour._isRedirect('/somepath/?search=true', '/somepath')).toBe false
+    # don't redirect if current path matches path regex
+    expect(@tour._isRedirect /some*/, '/somepath').toBe false
+
+  it '`_getState` should return null after `_removeState` with null value', ->
+    @tour = new Tour
+    @tour._setState('test', 'test')
+    @tour._removeState('test')
+    expect(@tour._getState('test')).toBe null
+
+  it '`_removeState` should call `afterRemoveState` callback', ->
+    sentinel = false
+    @tour = new Tour
+      afterRemoveState: -> sentinel = true
+    @tour._removeState('current_step')
+    expect(sentinel).toBe true
+
+  it 'should not move to the next state until the onShow promise is resolved', ->
+    @tour = new Tour
+    deferred = $.Deferred()
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.addStep
+      element: $('<div></div>').appendTo('body')
+      onShow: -> return deferred
+    @tour.start()
+    @tour.next()
+    expect(@tour._current).toBe 0 # tour shows old state until resolving of onShow promise
+    deferred.resolve()
+    expect(@tour._current).toBe 1 # tour shows new state after resolving onShow promise
+
+  it 'should not hide popover until the onHide promise is resolved', ->
+    deferred = $.Deferred()
+    @tour = new Tour
+    @tour.addStep
+      element: $('<div></div>').appendTo('body')
+      onHide: -> return deferred
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+    @tour.next()
+    expect(@tour._current).toBe 0 # tour shows old state until resolving of onHide promise
+    deferred.resolve()
+    expect(@tour._current).toBe 1 # tour shows new state after resolving onShow promise
+
+  it 'should not start until the onStart promise is resolved', ->
+    deferred = $.Deferred()
+    @tour = new Tour
+      onStart: -> deferred
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+    expect($('.popover').length).toBe 0
+    deferred.resolve()
+    expect($('.popover').length).toBe 1
+
+  it 'should add `tour-step-element-reflex` class to the step element if reflex is active', ->
+    @tour = new Tour
+    $element = $('<div></div>').appendTo('body')
+    @tour.addStep
+      element: $element
+      reflex: true
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    expect($element.hasClass('tour-step-element-reflex')).toBe false
+    @tour.start()
+    expect($element.hasClass('tour-step-element-reflex')).toBe true
+    @tour.next()
+    expect($element.hasClass('tour-step-element-reflex')).toBe false
+
+  it '`showStep` redirects to the anchor when the path is an anchor', ->
+    @tour = new Tour
+    @tour.addStep
+      element: $('<div></div>').appendTo('body')
+      path: '#mytest'
+    @tour.showStep(0)
+    expect(document.location.hash).toBe '#mytest' # Tour step has moved to the anchor
+    document.location.hash = ''
+
+  it '`backdrop` parameter should show backdrop with step', ->
+    @tour = new Tour
+    @tour.addStep
+      element: $('<div></div>').appendTo('body')
+      backdrop: false
+    @tour.addStep
+      element: $('<div></div>').appendTo('body')
+      backdrop: true
+    @tour.start()
+    expect($('.tour-backdrop').length).toBe 0 # disable backdrop
+    expect($('.tour-step-backdrop').length).toBe 0 # disable backdrop
+    expect($('.tour-step-background').length).toBe 0 # disable backdrop
+    @tour.next()
+    expect($('.tour-backdrop').length).toBe 1 # enable backdrop
+    expect($('.tour-step-backdrop').length).toBe 1 # enable backdrop
+    expect($('.tour-step-background').length).toBe 1 # enable backdrop
+    @tour.end()
+    expect($('.tour-backdrop').length).toBe 0 # disable backdrop
+    expect($('.tour-step-backdrop').length).toBe 0 # disable backdrop
+    expect($('.tour-step-background').length).toBe 0 # disable backdrop
+
+  it 'step with backdrop and invalid selector should not attempt to create an overlay element', ->
+    @tour = new Tour
+    @tour._showOverlayElement '#nonExistingElement'
+    expect(@tour.backdrop.overlayElementShown).toBe false
+
+  it 'should render the padding on the backdrop element', ->
+    @tour = new Tour
+      backdrop: true
+    $firstElement = $('<div></div>', width: 10, height: 10).appendTo('body')
+    $secondElement = $('<div></div>', width: 10, height: 10).appendTo('body')
+    firstPadding = 20
+    secondPadding =
+      top: 40
+      right: 30
+      bottom: 20
+      left: 10
+
+    @tour.addStep
+      backdrop: true
+      backdropPadding: firstPadding
+      element: $firstElement
+    @tour.addStep
+      backdrop: true
+      backdropPadding: secondPadding
+      element: $secondElement
+    @tour.start()
+    expect(@tour.backdrop.$background.width()).toBe $firstElement.innerWidth() + (firstPadding * 2)
+    expect(@tour.backdrop.$background.height()).toBe $firstElement.innerHeight() + (firstPadding * 2)
+    @tour.next()
+    expect(@tour.backdrop.$background.width())
+    .toBe $secondElement.innerWidth() + secondPadding.left + secondPadding.right
+    expect(@tour.backdrop.$background.height())
+    .toBe $secondElement.innerHeight() + secondPadding.top + secondPadding.bottom
+
+  it '`basePath` should prepend the path to the steps', ->
+    @tour = new Tour
+      basePath: 'test/'
+    @tour.addStep
+      element: $('<div></div>').appendTo('body')
+      path: 'test.html'
+
+    # Tour adds basePath to step path
+    expect(@tour._isRedirect(@tour._options.basePath + @tour.getStep(0).path, 'test/test.html')).toBe false
+
+  it 'with `onNext` option should run the callback before showing the next step', ->
+    tour_test = 0
+    @tour = new Tour
+      onNext: -> tour_test += 2
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+    @tour.next()
+    expect(tour_test).toBe 2
+
+  it '`showStep` should not show step if tour ended', ->
+    @tour = new Tour
+      onNext: (t) -> t.end()
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+    @tour.next()
+    expect($('.popover').length).toBe 0
+
+  it '`addStep` with onNext option should run the callback before showing the next step', ->
+    tour_test = 0
+    @tour = new Tour
+    @tour.addStep
+      element: $('<div></div>').appendTo('body')
+      onNext: -> tour_test = 2
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+    expect(tour_test).toBe 0 # tour does not run onNext when next step is not called
+    @tour.next()
+    expect(tour_test).toBe 2 # tour runs onNext when next step is called
+
+  it 'with `onPrev` option should run the callback before showing the prev step', ->
+    tour_test = 0
+    @tour = new Tour
+      onPrev: -> tour_test += 2
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+    @tour.next()
+    @tour.prev()
+    expect(tour_test).toBe 2 # tour runs onPrev when prev step is called
+
+  it '`addStep` with `onPrev` option should run the callback before showing the prev step', ->
+    tour_test = 0
+    @tour = new Tour
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.addStep
+      element: $('<div></div>').appendTo('body')
+      onPrev: -> tour_test = 2
+    @tour.start()
+    expect(tour_test).toBe 0 # tour does not run onPrev when prev step is not called
+    @tour.next()
+    @tour.prev()
+    expect(tour_test).toBe 2 # tour runs onPrev when prev step is called
+
+  it 'should render custom navigation template', ->
+    @tour = new Tour
+      template:
+        '<div class="popover tour">
+          <div class="arrow"></div>
+          <h3 class="popover-title"></h3>
+          <div class="popover-content"></div>
+          <div class="popover-navigation">
+            <a data-role="prev"></a>
+            <a data-role="next"></a>
+            <a data-role="end"></a>
+          </div>
+        </div>'
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+    @tour.next()
+    expect($('.popover .popover-navigation a').length).toBe 3
+
+  it 'should have `data-role` attribute for navigation template', ->
+    @tour = new Tour
+    template = $(@tour._options.template)
+    expect(template.find('*[data-role=next]').size()).toBe 1
+    expect(template.find('*[data-role=prev]').size()).toBe 1
+    expect(template.find('*[data-role=end]').size()).toBe 1
+
+  it 'should unbind click events when hiding step (in reflex mode)', ->
+    $element = $('<div></div>').appendTo('body')
+    @tour = new Tour
+    @tour.addStep
+      element: $element
+      reflex: true
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+
+    expect($._data($element[0], 'events')).not.toBeDefined()
+    @tour.start()
+    expect($._data($element[0], 'events').click.length).toBeGreaterThan 0
+    expect($._data($element[0], 'events').click[0].namespace).toBe "tour-#{@tour._options.name}"
+
+    $.each [0..10], =>
+      @tour.next()
+      expect($._data($element[0], 'events')).not.toBeDefined()
+      @tour.prev()
+      expect($._data($element[0], 'events').click.length).toBeGreaterThan 0
+      expect($._data($element[0], 'events').click[0].namespace).toBe "tour-#{@tour._options.name}"
+
+  it 'should add `tour-{tourName}` and `tour-{tourName}-{stepId}` classses to the popover', ->
+    @tour = new Tour
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.showStep(0)
+    expect($('.popover').hasClass("tour-#{@tour._options.name}")).toBe true
+    expect($('.popover').hasClass("tour-#{@tour._options.name}-0")).toBe true
+
+  it 'should add `tour-{tourName}-element` and `tour-{tourName}-{stepId}-element` classses to the popover element', ->
+    @tour = new Tour
+    $element = $ '<div></div>'
+    @tour.addStep element: $element.appendTo 'body'
+    @tour.showStep 0
+    expect($element.hasClass "tour-#{@tour._options.name}-element").toBe true
+    expect($element.hasClass "tour-#{@tour._options.name}-0-element").toBe true
+
+  # orphan
+  it 'should show orphan steps', ->
+    @tour = new Tour
+    @tour.addStep
+      orphan: true
+    @tour.showStep(0)
+    expect($('.popover').length).toBe 1
+    $('.popover').remove()
+
+  it 'should add `orphan` class to the popover', ->
+    @tour = new Tour
+    @tour.addStep
+      orphan: true
+    @tour.showStep(0)
+    expect($('.popover').hasClass('orphan')).toBe true
+    $('.popover').remove()
+
+  it 'handles quota_exceeded exceptions', ->
+    @tour = new Tour
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    spyOn(@tour._options.storage, 'setItem').andCallFake ->
+      throw new Error 'QUOTA_EXCEEDED_ERR', 'QUOTA_EXCEEDED_ERR: DOM Exception 22'
+    spyOn(@tour, '_setState')
+    @tour._setState('test', '1')
+    expect(=> @tour._setState).not.toThrow()
+
+  it 'should not try to scroll to non-existing element', ->
+    @tour = new Tour
+      orphan: true
+    @tour.addStep
+      element: '#nonExistingElement'
+    @tour.showStep 0
+    expect($('.popover').length).toBe 1
+
+  # duration
+  it 'should start the timer', ->
+    @tour = new Tour
+      duration: 5000
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+    expect(@tour._timer).toBeDefined()
+    expect(@tour._duration).toBeDefined()
+    window.clearTimeout(@tour._timer)
+
+  it 'should pause the timer on pause', ->
+    @tour = new Tour
+      duration: 5000
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+    window.setTimeout( =>
+      @tour.pause()
+      expect(@tour._timer).toBe null
+      expect(@tour._duration).toBeGreaterThan(0).toBeLessThan(5000)
+    , 1000)
+
+  it 'should stop the timer on hideStep', ->
+    @tour = new Tour
+      duration: 5000
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+    @tour.hideStep(0)
+    expect(@tour._timer).toBe null
+    expect(@tour._duration).toBe null
+
+  it 'should stop the timer on end', ->
+    @tour = new Tour
+      duration: 5000
+    @tour.addStep(element: $('<div></div>').appendTo('body'))
+    @tour.start()
+    @tour.end()
+    expect(@tour._timer).toBe null
+    expect(@tour._duration).toBe null
+
+  ### TODO: fix $.support.transition conflict between jquery and bootstrap
+  it 'should not display inactive popover upon rapid navigation', ->
+    # Flag that gives signal to the async test that it should evaluate.
+    $.support.transition = true
+    $.fx.off = false
+    isStepShown = false
+
+    # Cleanup all leftover popovers from previous tests.
+    $('.popover').remove()
+
+    # Setup two-step tour. The problem should occur when switching from first
+    # step to the second while the transition effect of the first one is still
+    # active.
+    @tour = new Tour
+    @tour.addStep element: $('<div></div>').appendTo('body')
+    @tour.addStep
+      element: $('<div></div>').appendTo('body')
+      onShown: ->
+        isStepShown = true
+
+    # Request the first step and immediately the second one. This way the first
+    # step won't be displayed when the second step is requested, so the request
+    # for second step can not cleanup existing popovers yet.
+    runs ->
+      @tour.goTo(0)
+      @tour.goTo(1)
+    waitsFor ->
+      isStepShown
+    , 'The second step should be displayed.', 1000
+    runs -> expect($('.popover').length).toBe 1
+  ###
diff --git a/src/docs/CNAME b/src/docs/CNAME
new file mode 100644
index 0000000..b876b5a
--- /dev/null
+++ b/src/docs/CNAME
@@ -0,0 +1 @@
+bootstraptour.com
diff --git a/src/docs/_includes/footer.html b/src/docs/_includes/footer.html
new file mode 100644
index 0000000..ea93f42
--- /dev/null
+++ b/src/docs/_includes/footer.html
@@ -0,0 +1,14 @@
+<script src="/components/jquery/dist/jquery.min.js?{{ site.time | date_to_xmlschema | cgi_escape }}"></script>
+<script src="/components/bootstrap/dist/js/bootstrap.min.js?{{ site.time | date_to_xmlschema | cgi_escape }}"></script>
+<script src="/components/blueimp-md5/js/md5.min.js?{{ site.time | date_to_xmlschema | cgi_escape }}"></script>
+<script src="/assets/vendor/jquery.smoothscroll.js?{{ site.time | date_to_xmlschema | cgi_escape }}"></script>
+<script src="/assets/js/bootstrap-tour.js?{{ site.time | date_to_xmlschema | cgi_escape }}"></script>
+<script src="/assets/js/bootstrap-tour.docs.js?{{ site.time | date_to_xmlschema | cgi_escape }}"></script>
+<script>
+window.twttr = (function (d,s,id) {
+  var t, js, fjs = d.getElementsByTagName(s)[0];
+  if (d.getElementById(id)) return; js=d.createElement(s); js.id=id; js.async=1;
+  js.src="https://platform.twitter.com/widgets.js"; fjs.parentNode.insertBefore(js, fjs);
+  return window.twttr || (t = { _e: [], ready: function(f){ t._e.push(f) } });
+}(document, "script", "twitter-wjs"));
+</script>
diff --git a/src/docs/_includes/header.html b/src/docs/_includes/header.html
new file mode 100644
index 0000000..4c2e5d1
--- /dev/null
+++ b/src/docs/_includes/header.html
@@ -0,0 +1,29 @@
+<meta charset="utf-8">
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<meta name="description" content="Quick and easy way to build your product tours with Bootstrap Popovers.">
+<title>
+  {% if page.title == "Bootstrap Tour" %}
+    {{ page.title }}
+  {% else %}
+    {{ page.title }} · Bootstrap Tour
+  {% endif %}
+</title>
+<link href="/components/bootstrap/dist/css/bootstrap.min.css?{{ site.time | date_to_xmlschema | cgi_escape }}" rel="stylesheet">
+<link href="/assets/vendor/pygments-manni.css?{{ site.time | date_to_xmlschema | cgi_escape }}" rel="stylesheet">
+<link href="/assets/css/bootstrap-tour.css?{{ site.time | date_to_xmlschema | cgi_escape }}" rel="stylesheet">
+<link href="/assets/css/bootstrap-tour.docs.css?{{ site.time | date_to_xmlschema | cgi_escape }}" rel="stylesheet">
+<link href="http://boostraptour.com{{ page.url }}" rel="canonical">
+<!--[if lt IE 9]><script src="/components/html5shiv/dist/html5shiv.min.js"></script><![endif]-->
+<script>
+if (window.location.href.indexOf('sorich87.github.com') > -1) {
+  window.location.href = 'http://bootstraptour.com{{ page.url }}';
+}
+
+(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+ga('create', 'UA-47485647-1', 'bootstraptour.com');
+ga('send', 'pageview');
+</script>
diff --git a/src/docs/_includes/nav.html b/src/docs/_includes/nav.html
new file mode 100644
index 0000000..19e2244
--- /dev/null
+++ b/src/docs/_includes/nav.html
@@ -0,0 +1,26 @@
+<div id="navbar" class="navbar navbar-static-top">
+  <div class="container">
+    <button type="button" class="navbar-toggle pull-right" data-toggle="collapse" data-target=".navbar-collapse">
+      <span class="icon-bar"></span>
+      <span class="icon-bar"></span>
+      <span class="icon-bar"></span>
+    </button>
+    <a href="/" class="navbar-brand">Bootstrap Tour</a>
+    <div class="collapse navbar-collapse">
+      <ul class="navbar-nav nav">
+        <li {% if page.slug == "home" %} class="active"{% endif %}>
+          <a href="/">Getting started</a>
+        </li>
+        <li>
+          <a href="https://github.com/sorich87/bootstrap-tour/releases">Download</a>
+        </li>
+        <li {% if page.slug == "api" %} class="active"{% endif %}>
+          <a href="/api">API Documentation</a>
+        </li>
+        <li>
+          <a href="https://github.com/sorich87/bootstrap-tour/issues">Bug reports</a>
+        </li>
+      </ul>
+    </div>
+  </div>
+</div>
diff --git a/src/docs/_layouts/default.html b/src/docs/_layouts/default.html
new file mode 100644
index 0000000..195669e
--- /dev/null
+++ b/src/docs/_layouts/default.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    {% include header.html %}
+  </head>
+  <body>
+    <a href="https://github.com/sorich87/bootstrap-tour" id="github"><img src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub"></a>
+    {% include nav.html %}
+    {{ content }}
+    {% include footer.html %}
+  </body>
+</html>
diff --git a/src/docs/api.html b/src/docs/api.html
new file mode 100644
index 0000000..39a3ac2
--- /dev/null
+++ b/src/docs/api.html
@@ -0,0 +1,746 @@
+---
+layout: default
+title: API Documentation
+slug: api
+---
+
+<section id="options">
+  <div class="container">
+    <div class="page-header">
+      <h2>Options <small>Well, let's go deeper</small></h2>
+    </div>
+    <h3 id="tour-options">Global options</h3>
+{% highlight javascript %}
+var tour = new Tour({
+  name: "tour",
+  steps: [],
+  container: "body",
+  keyboard: true,
+  storage: window.localStorage,
+  debug: false,
+  backdrop: false,
+  backdropPadding: 0,
+  redirect: true,
+  orphan: false,
+  duration: false,
+  delay: false,
+  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 btn-default' data-role='prev'>« Prev</button>
+        <span data-role='separator'>|</span>
+        <button class='btn btn-default' data-role='next'>Next »</button>
+    </div>
+    <button class='btn btn-default' data-role='end'>End tour</button>
+    </nav>
+  </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) {},
+  onPause: function (tour, duration) {},
+  onResume: function (tour, duration) {}
+});
+{% endhighlight %}
+    <table class="table  table-bordered table-striped">
+      <thead>
+        <tr>
+          <th>Name</th>
+          <th>Type</th>
+          <th>Description</th>
+          <th width="50%">Default</th>
+        </tr>
+      </thead>
+      <tbody>
+        <tr>
+          <td>name</td>
+          <td>String</td>
+          <td>This option is used to build the name of the storage item where the tour state is stored.
+            The name should contain only alphanumerics, underscores and hyphens.
+            You can initialize several tours with different names in the same page and application.</td>
+          <td><code>'tour'</code></td>
+        </tr>
+        <tr>
+          <td>steps</td>
+          <td>Array</td>
+          <td>A list of object representing the steps to be included in the tour. Jump to
+          <a href="#step-options">Step options</a> for the single step API.</td>
+          <td><code>[]</code></td>
+        </tr>
+        <tr>
+          <td>container</td>
+          <td>String</td>
+          <td>Appends the step popover to a specific element.<br>
+          <em>See Usage section of
+          <a href="http://getbootstrap.com/javascript/#popovers" target="_blank">Popover</a>.
+          </em>
+          </td>
+          <td><code>'body'</code></td>
+        </tr>
+        <tr>
+          <td>autoscroll</td>
+          <td>Boolean</td>
+          <td>Autoscrolls the window when the step popover is out of view.</td>
+          <td><code>true</code></td>
+        </tr>
+        <tr>
+          <td>keyboard</td>
+          <td>Boolean</td>
+          <td>This option set the left and right arrow navigation.</td>
+          <td><code>true</code></td>
+        </tr>
+        <tr id="storage">
+          <td>storage</td>
+          <td>Object</td>
+          <td>The storage system you want to use. Could be the objects window.localStorage,
+          window.sessionStorage or your own object.<br>
+          You can set this option as
+          <code>false</code> to disable storage
+          persistence (the tour starts from beginning every time the page is
+          loaded).<br>
+          <em>Read more about <a href="https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage" target="_blank">DOM Storage interfaces</a>.</em>
+          </td>
+          <td><code>window.localStorage</code></td>
+        </tr>
+        <tr>
+          <td>debug</td>
+          <td>Boolean</td>
+          <td>Set this option to true to have some useful informations printed in the
+          console.</td>
+          <td><code>false</code></td>
+        </tr>
+        <tr>
+          <td>backdrop</td>
+          <td>Boolean</td>
+          <td>Show a dark backdrop behind the popover and its element,
+          highlighting the current step.</td>
+          <td><code>false</code></td>
+        </tr>
+        <tr class="success">
+          <td>backdropPadding <span class="label label-success">NEW</span></td>
+          <td>Number|Object</td>
+          <td>Add padding to the backdrop element that highlights the step element.<br>
+          It can be a number or a object containing optional <code>top</code>, <code>right</code>, <code>bottom</code> and <code>left</code> numbers.</td>
+          <td><code>0</code></td>
+        </tr>
+        <tr>
+          <td>redirect</td>
+          <td>Boolean|Function</td>
+          <td>Set a custom function to execute as redirect function.
+          The default redirect relies on the traditional
+          <code class="language-javascript">document.location.href</code></td>
+          <td><code>true</code></td>
+        </tr>
+        <tr>
+          <td>orphan</td>
+          <td>Boolean</td>
+          <td>Allow to show the step regardless whether its element is not set, is
+          not present in the page or is hidden. The step is fixed
+          positioned in the middle of the page.</td>
+          <td><code>false</code></td>
+        </tr>
+        <tr id="duration" class="success">
+          <td>duration <span class="label label-success">NEW</span></td>
+          <td>Boolean|Number</td>
+          <td>Set a expiration time for the steps. When the current step expires,
+          the next step is automatically shown. See it as a sort of guided, automatized tour
+          functionality. The value is specified in milliseconds</td>
+          <td><code>false</code></td>
+        </tr>
+        <tr id="delay" class="success">
+          <td>delay <span class="label label-success">NEW</span></td>
+          <td>Boolean|Number</td>
+          <td>Specifies a delay for the showing and hiding the tour steps.
+          It can be:
+          <ul>
+            <li>a falsy - there is no delay</li>
+            <li>a number - used as a delay for both showing and hiding. In milliseconds</li>
+            <li>a object containing optional <code>show</code> and <code>hide</code> numbers - defines the delays for showing and hiding respectively</li>
+          </ul>
+          <td><code>0</code></td>
+        </tr>
+        <tr>
+          <td>basePath</td>
+          <td>String</td>
+          <td>Specify a default base path prepended to the
+          <code>path</code> option of every single
+          step. Very useful if you need to reuse the same tour on different
+          environments or sub-projects.</td>
+          <td><code>''</code></td>
+        </tr>
+        <tr>
+          <td>template</td>
+          <td>String|Function</td>
+          <td>String or function that returns a string of the HTML template for
+          the popovers. If you pass a Function, two parameters are available:
+          <strong>i</strong> is the position of step in the tour and
+          <strong>step</strong> is the an object that contains all the other step
+          options.<br>
+          From version 0.5, the navigation template is included inside the
+          template so you can easily rewrite it. However, Bootstrap Tour maps the
+          <em>previous</em>, <em>next</em> and <em>end</em> logics to the elements
+          which have the related <code class="language-markup">data-role</code>
+          attribute. Therefore, you can also have multiple elements with the same
+          <code class="language-markup">data-role</code> attribute.
+          </td>
+          <td>
+{% highlight javascript %}
+"<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 btn-default' data-role='prev'>« Prev</button>
+    <span data-role='separator'>|</span>
+    <button class='btn btn-default' data-role='next'>Next »</button>
+    <button class='btn btn-default' data-role='end'>End tour</button>
+  </div>
+</div>"
+{% endhighlight %}
+          </td>
+        </tr>
+        <tr>
+          <td>afterGetState, afterSetState, afterRemoveState</td>
+          <td>Function</td>
+          <td>You may want to do something right after Bootstrap Tour read, write or remove
+          the state. Just pass functions to these.<br />
+          Your functions can have two parameters:
+          <ul class="unstyled">
+            <li>
+              <strong>key</strong>
+              Contains the name of the state being saved. It can be
+              <code>current_step</code> (for the state where the
+              latest step the visitor viewed is saved) or
+              <code>end</code> (for the state which is saved when
+              the user complete the tour). Note that Bootstrap Tour prepends the key with
+              <code>tour_</code> when saving the state.
+            </li>
+            <li>
+              <strong>value</strong>
+              The value of the state been saved. Can be the index of the
+              current step if the key is <code>current_step</code>, or
+              <code>yes</code> if the key is <code>end</code>.
+            </li>
+          </ul>
+          <p>A simple example if to send a post request to your server each
+          time there is a change:</p>
+{% highlight javascript %}
+var tour = new Tour({
+  afterSetState: function (key, value) {
+    $.post("/some/path", value);
+  }
+});
+{% endhighlight %}
+          </td>
+          <td><code>function (key, value) { }</code></td>
+        </tr>
+        <tr>
+          <td>onStart</td>
+          <td>Function</td>
+          <td>Function to execute when the tour starts.</td>
+          <td><code>function (tour) { }</code></td>
+        </tr>
+        <tr>
+          <td>onEnd</td>
+          <td>Function</td>
+          <td>Function to execute when the tour ends.</td>
+          <td><code>function (tour) { }</code></td>
+        </tr>
+        <tr>
+          <td>onShow</td>
+          <td>Function</td>
+          <td>Function to execute right before each step is shown.</td>
+          <td><code>function (tour) { }</code></td>
+        </tr>
+        <tr>
+          <td>onShown</td>
+          <td>Function</td>
+          <td>Function to execute right after each step is shown.</td>
+          <td><code>function (tour) { }</code></td>
+        </tr>
+        <tr>
+          <td>onHide</td>
+          <td>Function</td>
+          <td>Function to execute right before each step is hidden.</td>
+          <td><code>function (tour) { }</code></td>
+        </tr>
+        <tr>
+          <td>onHidden</td>
+          <td>Function</td>
+          <td>Function to execute right after each step is hidden.</td>
+          <td><code>function (tour) { }</code></td>
+        </tr>
+        <tr>
+          <td>onNext</td>
+          <td>Function</td>
+          <td>Function to execute when next step is called.</td>
+          <td><code>function (tour) { }</code></td>
+        </tr>
+        <tr>
+          <td>onPrev</td>
+          <td>Function</td>
+          <td>Function to execute when prev step is called.</td>
+          <td><code>function (tour) { }</code></td>
+        </tr>
+        <tr class="success">
+          <td>onPause <span class="label label-success">NEW</span></td>
+          <td>Function</td>
+          <td>Function to execute when pause is called. The second argument refers to the
+          remaining duration.</td>
+          <td><code>function (tour, duration) { }</code></td>
+        </tr>
+        <tr class="success">
+          <td>onResume <span class="label label-success">NEW</span></td>
+          <td>Function</td>
+          <td>Function to execute when resume is called. The second argument refers to the
+          remaining duration.</td>
+          <td><code>function (tour, duration) { }</code></td>
+        </tr>
+      </tbody>
+    </table>
+    <a id="step-options"></a>
+    <h3>Step Options</h3>
+{% highlight javascript %}
+tour.addStep({
+  path: "",
+  element: "",
+  placement: "right",
+  title: "",
+  content: "",
+  next: 0,
+  prev: 0,
+  animation: true,
+  container: "body",
+  backdrop: false,
+  backdropPadding: false,
+  redirect: true,
+  reflex: false,
+  orphan: false,
+  template: "",
+  onShow: function (tour) {},
+  onShown: function (tour) {},
+  onHide: function (tour) {},
+  onHidden: function (tour) {},
+  onNext: function (tour) {},
+  onPrev: function (tour) {},
+  onPause: function (tour) {},
+  onResume: function (tour) {}
+});
+{% endhighlight %}
+    <table class="table  table-bordered table-striped">
+      <thead>
+        <tr>
+          <th>Name</th>
+          <th>Type</th>
+          <th>Description</th>
+          <th width="50%">Default</th>
+        </tr>
+      </thead>
+      <tbody>
+        <tr>
+          <td>path</td>
+          <td>String or RegExp</td>
+          <td>Path to the page on which the step should be shown. This
+          allows you to build tours that span several pages!</td>
+          <td><code>''</code></td>
+        </tr>
+        <tr>
+          <td>element</td>
+          <td>String (jQuery selector)</td>
+          <td>HTML element on which the step popover should be shown.<br />
+          <em>If orphan is false, this option is required.</em></td>
+          <td><code>''</code></td>
+        </tr>
+        <tr>
+          <td>placement</td>
+          <td>String|Function</td>
+          <td>How to position the popover. Possible choices:
+          <code>'top'</code>,
+          <code>'bottom'</code>,
+          <code>'left'</code>,
+          <code>'right'</code>.
+          </td>
+          <td><code>'right'</code></td>
+        </tr>
+        <tr>
+          <td>title</td>
+          <td>String|Function</td>
+          <td>Step title</td>
+          <td><code>''</code></td>
+        </tr>
+        <tr>
+          <td>content</td>
+          <td>String|Function</td>
+          <td>Step content</td>
+          <td><code>''</code></td>
+        </tr>
+        <tr>
+          <td>next</td>
+          <td>Integer</td>
+          <td>Index of the step to show after this one, starting from
+          <code>0</code> for the first step of the
+          tour. <code>-1</code> to not show the link
+          to next step. By default, the next step (in the order you added
+          them) will be shown.<br />
+          <em>This option should be used in conjunction with
+          <code>prev</code>.</em></td>
+          <td><code>0</code></td>
+        </tr>
+        <tr>
+          <td>prev</td>
+          <td>Integer</td>
+          <td>Index of the step to show before this one, starting from
+          <code>0</code> for the first step of the
+          tour. <code>-1</code> to not show the link
+          to previous step. By default, the previous step (in the order you added
+          them) will be shown.<br />
+          <em>This option should be used in conjunction with
+          <code>next</code>.</em></td>
+          <td><code>0</code></td>
+        </tr>
+        <tr>
+          <td>animation</td>
+          <td>Boolean</td>
+          <td>Apply a css fade transition to the tooltip.</td>
+          <td><code>true</code></td>
+        </tr>
+        <tr>
+          <td>container</td>
+          <td>String (jQuery selector)</td>
+          <td>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.</td>
+          <td><code>'body'</code></td>
+        </tr>
+        <tr>
+          <td>backdrop</td>
+          <td>Boolean</td>
+          <td>Show a dark backdrop behind the popover and its element,
+          highlighting the current step.</td>
+          <td><code>false</code></td>
+        </tr>
+        <tr class="success">
+          <td>backdropPadding <span class="label label-success">NEW</span></td>
+          <td>Boolean|Object</td>
+          <td>Add padding to the backdrop element that highlights the step element.<br>
+          It can be a number or a object containing optional <code>top</code>, <code>right</code>, <code>bottom</code> and <code>left</code> numbers.</td>
+          <td><code>0</code></td>
+        </tr>
+        <tr>
+          <td>redirect</td>
+          <td>Boolean|Function</td>
+          <td>Set a custom function to execute as redirect function.
+          The default redirect relies on the traditional
+          <code class="language-javascript">document.location.href</code></td>
+          <td><code>true</code></td>
+        </tr>
+        <tr class="success">
+          <td id="reflex">reflex <span class="label label-warning">UPDATED</span></td>
+          <td>Boolean|String</td>
+          <td>Enable the reflex mode: attach an handler on <code>click</code> on the step element to continue the tour.<br>
+          In order to bind the handler to a custom event, you can pass a string with its name.<br>
+          Also, the class <code>tour-step-element-reflex</code> is added to the element, as hook for your custom style (e.g: cursor: pointer).</td>
+          <td><code>false</code></td>
+        </tr>
+        <tr>
+          <td>orphan</td>
+          <td>Boolean</td>
+          <td>Allow to show the step regardless whether its element is not set, is
+          not present in the page or is hidden. The step is fixed
+          positioned in the middle of the page.</td>
+          <td><code>false</code></td>
+        </tr>
+        <tr class="success">
+          <td>duration <span class="label label-success">NEW</span></td>
+          <td>Boolean|String</td>
+          <td>Set a expiration time for the steps. When the step expires,
+          the next step is automatically shown. See it as a sort of guided, automatized tour
+          functionality. The value is specified in milliseconds</td>
+          <td><code>false</code></td>
+        </tr>
+        <tr>
+          <td>template</td>
+          <td>String|Function</td>
+          <td>String or function that returns a string of the HTML template for
+          the popovers. If you pass a Function, two parameters are available:
+          <strong>i</strong> is the position of step in the tour and
+          <strong>step</strong> is the object that contains all the other step
+          options.<br>
+          From version 0.5, the navigation template is included inside the
+          template so you can easily rewrite it. However, Bootstrap Tour maps the
+          <em>previous</em>, <em>next</em> and <em>end</em> logics to the elements
+          which have the related <code class="language-markup">data-role</code>
+          attribute. Therefore, you can also have multiple elements with the same
+          <code class="language-markup">data-role</code> attribute.
+          </td>
+          <td>
+{% highlight javascript %}
+"<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 btn-default' data-role='prev'>« Prev</button>
+    <span data-role='separator'>|</span>
+    <button class='btn btn-default' data-role='next'>Next »</button>
+    <button class='btn btn-default' data-role='end'>End tour</button>
+  </div>
+</div>"
+{% endhighlight %}
+          </td>
+        </tr>
+        <tr>
+          <td>onShow</td>
+          <td>Function</td>
+          <td>Function to execute right before the step is shown. It overrides the
+          global <code>onShow</code> option.</td>
+          <td><code>function (tour) { }</code></td>
+        </tr>
+        <tr>
+          <td>onShown</td>
+          <td>Function</td>
+          <td>Function to execute right after the step is shown. It overrides the
+          global <code>onShown</code> option.</td>
+          <td><code>function (tour) { }</code></td>
+        </tr>
+        <tr>
+          <td>onHide</td>
+          <td>Function</td>
+          <td>Function to execute right before the step is hidden. It overrides
+          the global <code>onHide</code> option.</td>
+          <td><code>function (tour) { }</code></td>
+        </tr>
+        <tr>
+          <td>onHidden</td>
+          <td>Function</td>
+          <td>Function to execute right after the step is hidden. It overrides the
+          global <code>onHidden</code> option.</td>
+          <td><code>function (tour) { }</code></td>
+        </tr>
+        <tr>
+          <td>onNext</td>
+          <td>Function</td>
+          <td>Function to execute when next step is called. It overrides the
+          global <code>onNext</code> option.</td>
+          <td><code>function (tour) { }</code></td>
+        </tr>
+        <tr>
+          <td>onPrev</td>
+          <td>Function</td>
+          <td>Function to execute when prev step is called. It overrides the global
+          <code>onPrev</code> option.</td>
+          <td><code>function (tour) { }</code></td>
+        </tr>
+        <tr class="success">
+          <td>onPause <span class="label label-success">NEW</span></td>
+          <td>Function</td>
+          <td>Function to execute when pause is called. The second argument refers to the
+          remaining duration. It overrides the global the
+          <code>onPause</code> option</td>
+          <td><code>function (tour, duration) { }</code></td>
+        </tr>
+        <tr class="success">
+          <td>onResume <span class="label label-success">NEW</span></td>
+          <td>Function</td>
+          <td>Function to execute when resume is called. The second argument refers to the
+          remaining duration. It overrides the global
+          <code>onResume</code> option</td>
+          <td><code>function (tour, duration) { }</code></td>
+        </tr>
+      </tbody>
+    </table>
+  </div>
+</section>
+
+<section id="methods">
+  <div class="container">
+    <div class="page-header">
+      <h2>Methods <small>Always in control</small></h2>
+    </div>
+    <!--<p>If, for some reasons, you want to force the tour to be
+    displayed, pass <code>true</code> to the <code>start()</code>
+    method.</p>-->
+    <table class="table  table-bordered table-striped">
+      <thead>
+        <tr>
+          <th>Name</th>
+          <th>Description</th>
+        </tr>
+      </thead>
+      <tbody>
+        <tr>
+          <td>addSteps(<code>[]</code>)</td>
+          <td>Add multiple steps to the tour. Pass an array of objects.</td>
+        </tr>
+        <tr>
+          <td>addStep(<code>{}</code>)</td>
+          <td>Add single step to the tour. Pass an object.</td>
+        </tr>
+        <tr>
+          <td>init()</td>
+          <td>Initialize the tour. You must do it before calling start.</td>
+        </tr>
+        <tr>
+          <td>start(<code>true</code>)</td>
+          <td>Start the tour. Pass <code>true</code> to force the start.</td>
+        </tr>
+        <tr>
+          <td>restart()</td>
+          <td>Restart the tour after it ended.</td>
+        </tr>
+        <tr>
+          <td>end()</td>
+          <td>End the tour prematurely.</td>
+        </tr>
+        <tr>
+          <td>next()</td>
+          <td>Skip to the next step.</td>
+        </tr>
+        <tr>
+          <td>prev()</td>
+          <td>Go back to the previous step.</td>
+        </tr>
+        <tr class="warning">
+          <td>goTo(<code>i</code>)
+          <span class="label label-warning">UPDATED</span></td>
+          <td>Skip to a specific step. Pass <code>i</code> as the
+          index of the step in the tour (0-based).<br>
+          <em>From version 0.7.0, the method has been renamed since some Javascript compilers
+          are confused by the property name <strong>goto</strong>, which is a reserved word)
+          </em>.
+          </td>
+        </tr>
+        <tr>
+          <td>pause()</td>
+          <td>Pause the duration timer. It works only if tour or current step has duration.</td>
+        </tr>
+        <tr>
+          <td>resume()</td>
+          <td>Resume the duration timer. It works only if tour or current step has duration.</td>
+        </tr>
+        <tr>
+          <td>ended()</td>
+          <td>Verify if the tour ended. Returns boolean.</td>
+        </tr>
+        <tr>
+          <td>getStep(<code>i</code>)</td>
+          <td>Get the step object. Pass <code>i</code> as the index
+          of the step in the tour (0-based).</td>
+        </tr>
+        <tr>
+          <td>getCurrentStep()</td>
+          <td>Get the index of the current step.</td>
+        </tr>
+        <tr>
+          <td>setCurrentStep(<code>i</code>)</td>
+          <td>Override the current step. Pass <code>i</code>
+          as the index of the step in the tour (0-based).</td>
+        </tr>
+      </tbody>
+    </table>
+  </div>
+</section>
+
+<section id="multipage">
+    <div class="container">
+        <div class="page-header">
+            <h2>Multipage
+                <small>How to traverse across pages</small>
+            </h2>
+        </div>
+        <p>Bootstrap Tour can be used to create tours that span multiple pages. If you have URLs for each page that have
+            unique paths, and the dependencies are loaded on each page, you can easily create a tour like so:
+        </p>
+{% highlight javascript %}
+var tour = new Tour({
+  steps: [
+    {
+      element: "#my-element",
+      title: "Title of my step",
+      content: "Content of my step"
+    },
+    {
+      element: "#my-other-element",
+      title: "Title of my step",
+      content: "Content of my step",
+      path: "/url/to/go/to/"
+    }
+  ]
+});
+{% endhighlight %}
+
+        <p>It's that simple.</p>
+
+        <p>If you do not know the URL you wish to go to because it contains a different value per user or per
+            instance, you can use a regular expression as the <code>path</code> attribute and set the redirect
+            attribute to a function that performs the redirect.
+        </p>
+        <p>For example:</p>
+
+{% highlight javascript %}
+var tour = new Tour({
+  steps: [
+    {
+      element: "#my-element",
+      title: "Title of my step",
+      content: "Content of my step",
+      redirect: function(){
+        document.location.href = '/url/' + userId;
+      };
+    },
+    {
+      element: "#my-other-element",
+      title: "Title of my step",
+      content: "Content of my step",
+      path: Regexp("/\/url\/[^/]+/i")
+    }
+  ]
+});
+{% endhighlight %}
+
+        <p>Finally, if you are only using GET parameters to define different pages, and wish to redirect using those
+            parameters, you may run into the problem that Bootstrap Tour will consider the path of the two steps to be
+            identical. For example, you cannot use the path parameter to go from your homepage at <code>/</code> to a
+            search results page at <code>/?q=foo</code>, because from Bootstrap Tour's perspective, those are the same
+            location (<code>/</code>).
+        </p>
+        <p>To work around this limitation, you can set the <code>onNext</code> attribute a function that returns a
+            promise.</p>
+        <p>For example:</p>
+
+{% highlight javascript %}
+var tour = new Tour({
+  steps: [
+    {
+      element: "#my-element",
+      title: "Title of my step",
+      content: "Content of my step",
+      onNext: function(){
+        document.location.href = '/?q=foo';
+        return (new jQuery.Deferred()).promise();
+      };
+    },
+    {
+      element: "#my-other-element",
+      title: "Title of my step",
+      content: "Content of my step",
+    }
+  ]
+});
+{% endhighlight %}
+
+        <p>Doing this will prevent the next step from popping up while the redirect is being completed in the
+            <code>onNext</code> function.
+        </p>
+    </div>
+</section>
diff --git a/src/docs/assets/css/bootstrap-tour.css b/src/docs/assets/css/bootstrap-tour.css
new file mode 100644
index 0000000..b730758
--- /dev/null
+++ b/src/docs/assets/css/bootstrap-tour.css
@@ -0,0 +1,73 @@
+/* ========================================================================
+ * bootstrap-tour - v0.10.1
+ * http://bootstraptour.com
+ * ========================================================================
+ * Copyright 2012-2013 Ulrich Sossou
+ *
+ * ========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================================
+ */
+
+.tour-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1100;
+  background-color: #000;
+  opacity: 0.8;
+  filter: alpha(opacity=80);
+}
+.tour-step-backdrop {
+  position: relative;
+  z-index: 1101;
+  background: inherit;
+}
+.tour-step-backdrop > td {
+  position: relative;
+  z-index: 1101;
+}
+.tour-step-background {
+  position: absolute !important;
+  z-index: 1100;
+  background: inherit;
+  border-radius: 6px;
+}
+.popover[class*="tour-"] {
+  z-index: 1100;
+}
+.popover[class*="tour-"] .popover-navigation {
+  padding: 9px 14px;
+}
+.popover[class*="tour-"] .popover-navigation *[data-role="end"] {
+  float: right;
+}
+.popover[class*="tour-"] .popover-navigation *[data-role="prev"],
+.popover[class*="tour-"] .popover-navigation *[data-role="next"],
+.popover[class*="tour-"] .popover-navigation *[data-role="end"] {
+  cursor: pointer;
+}
+.popover[class*="tour-"] .popover-navigation *[data-role="prev"].disabled,
+.popover[class*="tour-"] .popover-navigation *[data-role="next"].disabled,
+.popover[class*="tour-"] .popover-navigation *[data-role="end"].disabled {
+  cursor: default;
+}
+.popover[class*="tour-"].orphan {
+  position: fixed;
+  margin-top: 0;
+}
+.popover[class*="tour-"].orphan .arrow {
+  display: none;
+}
diff --git a/src/docs/assets/css/bootstrap-tour.docs.css b/src/docs/assets/css/bootstrap-tour.docs.css
new file mode 100644
index 0000000..2c05e71
--- /dev/null
+++ b/src/docs/assets/css/bootstrap-tour.docs.css
@@ -0,0 +1,61 @@
+body {
+  padding-bottom: 50px;
+}
+
+#github {
+  display: block;
+  position: absolute;
+  width: 150px;
+  height: 150px;
+  top: 0;
+  right: 0;
+  z-index: 1050;
+}
+
+.navbar {
+  margin-bottom: 0;
+}
+
+.masthead {
+  position: relative;
+  padding: 30px 15px;
+  color: #fff;
+  text-align: center;
+  text-shadow: 0 1px 0 rgba(0,0,0,.1);
+  background-color: #3276b1;
+  background-image: -webkit-linear-gradient(top, #285e8e 0%, #3276b1 100%);
+  background-image: linear-gradient(to bottom, #285e8e 0%, #3276b1 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#285e8e', endColorstr='#3276b1', GradientType=0);
+}
+.masthead small {
+  font-size: 80%;
+  color: #ccc;
+}
+
+/*
+ * Social buttons
+ *
+ * Twitter and GitHub social action buttons (for homepage and footer).
+ */
+
+.social {
+  display: inline-block;
+  margin-top: 40px;
+  margin-bottom: 0;
+  padding-left: 0;
+  list-style: none;
+}
+.social li {
+  display: inline-block;
+  line-height: 1;
+  padding: 5px 8px;
+}
+.social .tweet-btn a {
+  width: 98px !important;
+}
+/* Style the GitHub buttons via CSS instead of inline attributes */
+.github-btn {
+  border: 0;
+  overflow: hidden;
+}
diff --git a/src/docs/assets/fonts/glyphicons-halflings-regular.eot b/src/docs/assets/fonts/glyphicons-halflings-regular.eot
new file mode 100644
index 0000000..87eaa43
Binary files /dev/null and b/src/docs/assets/fonts/glyphicons-halflings-regular.eot differ
diff --git a/src/docs/assets/fonts/glyphicons-halflings-regular.svg b/src/docs/assets/fonts/glyphicons-halflings-regular.svg
new file mode 100644
index 0000000..5fee068
--- /dev/null
+++ b/src/docs/assets/fonts/glyphicons-halflings-regular.svg
@@ -0,0 +1,228 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata></metadata>
+<defs>
+<font id="glyphicons_halflingsregular" horiz-adv-x="1200" >
+<font-face units-per-em="1200" ascent="960" descent="-240" />
+<missing-glyph horiz-adv-x="500" />
+<glyph />
+<glyph />
+<glyph unicode=" " />
+<glyph unicode="*" d="M1100 500h-259l183 -183l-141 -141l-183 183v-259h-200v259l-183 -183l-141 141l183 183h-259v200h259l-183 183l141 141l183 -183v259h200v-259l183 183l141 -141l-183 -183h259v-200z" />
+<glyph unicode="+" d="M1100 400h-400v-400h-300v400h-400v300h400v400h300v-400h400v-300z" />
+<glyph unicode="&#xa0;" />
+<glyph unicode="&#x2000;" horiz-adv-x="652" />
+<glyph unicode="&#x2001;" horiz-adv-x="1304" />
+<glyph unicode="&#x2002;" horiz-adv-x="652" />
+<glyph unicode="&#x2003;" horiz-adv-x="1304" />
+<glyph unicode="&#x2004;" horiz-adv-x="434" />
+<glyph unicode="&#x2005;" horiz-adv-x="326" />
+<glyph unicode="&#x2006;" horiz-adv-x="217" />
+<glyph unicode="&#x2007;" horiz-adv-x="217" />
+<glyph unicode="&#x2008;" horiz-adv-x="163" />
+<glyph unicode="&#x2009;" horiz-adv-x="260" />
+<glyph unicode="&#x200a;" horiz-adv-x="72" />
+<glyph unicode="&#x202f;" horiz-adv-x="260" />
+<glyph unicode="&#x205f;" horiz-adv-x="326" />
+<glyph unicode="&#x20ac;" d="M800 500h-300q9 -74 33 -132t52.5 -91t62 -54.5t59 -29t46.5 -7.5q29 0 66 13t75 37t63.5 67.5t25.5 96.5h174q-31 -172 -128 -278q-107 -117 -274 -117q-205 0 -324 158q-36 46 -69 131.5t-45 205.5h-217l100 100h113q0 47 5 100h-218l100 100h135q37 167 112 257 q117 141 297 141q242 0 354 -189q60 -103 66 -209h-181q0 55 -25.5 99t-63.5 68t-75 36.5t-67 12.5q-24 0 -52.5 -10t-62.5 -32t-65.5 -67t-50.5 -107h379l-100 -100h-300q-6 -46 -6 -100h406z" />
+<glyph unicode="&#x2212;" d="M1100 700h-900v-300h900v300z" />
+<glyph unicode="&#x2601;" d="M178 300h750q120 0 205 86t85 208q0 120 -85 206.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5q0 -80 56.5 -137t135.5 -57z" />
+<glyph unicode="&#x2709;" d="M1200 1100h-1200l600 -603zM300 600l-300 -300v600zM1200 900v-600l-300 300zM800 500l400 -400h-1200l400 400l200 -200z" />
+<glyph unicode="&#x270f;" d="M1101 889l99 92q13 13 13 32.5t-13 33.5l-153 153q-15 13 -33 13t-33 -13l-94 -97zM401 189l614 614l-214 214l-614 -614zM-13 -13l333 112l-223 223z" />
+<glyph unicode="&#xe000;" horiz-adv-x="500" d="M0 0z" />
+<glyph unicode="&#xe001;" d="M700 100h300v-100h-800v100h300v550l-500 550h1200l-500 -550v-550z" />
+<glyph unicode="&#xe002;" d="M1000 934v-521q-64 16 -138 -7q-79 -26 -122.5 -83t-25.5 -111q17 -55 85.5 -75.5t147.5 4.5q70 23 111.5 63.5t41.5 95.5v881q0 10 -7 15.5t-17 2.5l-752 -193q-10 -3 -17 -12.5t-7 -19.5v-689q-64 17 -138 -7q-79 -25 -122.5 -82t-25.5 -112t86 -75.5t147 5.5 q65 21 109 69t44 90v606z" />
+<glyph unicode="&#xe003;" d="M913 432l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342t142 342t342 142t342 -142t142 -342q0 -142 -78 -261zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233z" />
+<glyph unicode="&#xe005;" d="M649 949q48 69 109.5 105t121.5 38t118.5 -20.5t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-149.5 152.5t-126.5 127.5t-94 124.5t-33.5 117.5q0 64 28 123t73 100.5t104.5 64t119 20.5 t120 -38.5t104.5 -104.5z" />
+<glyph unicode="&#xe006;" d="M791 522l145 -449l-384 275l-382 -275l146 447l-388 280h479l146 400h2l146 -400h472zM168 71l2 1z" />
+<glyph unicode="&#xe007;" d="M791 522l145 -449l-384 275l-382 -275l146 447l-388 280h479l146 400h2l146 -400h472zM747 331l-74 229l193 140h-235l-77 211l-78 -211h-239l196 -142l-73 -226l192 140zM168 71l2 1z" />
+<glyph unicode="&#xe008;" d="M1200 143v-143h-1200v143l400 257v100q-37 0 -68.5 74.5t-31.5 125.5v200q0 124 88 212t212 88t212 -88t88 -212v-200q0 -51 -31.5 -125.5t-68.5 -74.5v-100z" />
+<glyph unicode="&#xe009;" d="M1200 1100v-1100h-1200v1100h1200zM200 1000h-100v-100h100v100zM900 1000h-600v-400h600v400zM1100 1000h-100v-100h100v100zM200 800h-100v-100h100v100zM1100 800h-100v-100h100v100zM200 600h-100v-100h100v100zM1100 600h-100v-100h100v100zM900 500h-600v-400h600 v400zM200 400h-100v-100h100v100zM1100 400h-100v-100h100v100zM200 200h-100v-100h100v100zM1100 200h-100v-100h100v100z" />
+<glyph unicode="&#xe010;" d="M500 1050v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5zM1100 1050v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h400 q21 0 35.5 -14.5t14.5 -35.5zM500 450v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5zM1100 450v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-40 [...]
+<glyph unicode="&#xe011;" d="M300 1050v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5zM700 1050v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h200 q21 0 35.5 -14.5t14.5 -35.5zM1100 1050v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5zM300 650v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-20 [...]
+<glyph unicode="&#xe012;" d="M300 1050v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5zM1200 1050v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h700 q21 0 35.5 -14.5t14.5 -35.5zM300 450v200q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5t-14.5 -35.5v-200q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5zM1200 650v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-70 [...]
+<glyph unicode="&#xe013;" d="M448 34l818 820l-212 212l-607 -607l-206 207l-212 -212z" />
+<glyph unicode="&#xe014;" d="M882 106l-282 282l-282 -282l-212 212l282 282l-282 282l212 212l282 -282l282 282l212 -212l-282 -282l282 -282z" />
+<glyph unicode="&#xe015;" d="M913 432l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342t142 342t342 142t342 -142t142 -342q0 -142 -78 -261zM507 363q137 0 233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5t-234 -97t-97 -233 t97 -233t234 -97zM600 800h100v-200h-100v-100h-200v100h-100v200h100v100h200v-100z" />
+<glyph unicode="&#xe016;" d="M913 432l300 -299q7 -7 7 -18t-7 -18l-109 -109q-8 -8 -18 -8t-18 8l-300 299q-120 -77 -261 -77q-200 0 -342 142t-142 342t142 342t342 142t342 -142t142 -342q0 -141 -78 -262zM176 694q0 -136 97 -233t234 -97t233.5 97t96.5 233t-96.5 233t-233.5 97t-234 -97 t-97 -233zM300 801v-200h400v200h-400z" />
+<glyph unicode="&#xe017;" d="M700 750v400q0 21 -14.5 35.5t-35.5 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-400q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5zM800 975v166q167 -62 272 -210t105 -331q0 -118 -45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123 t-123 184t-45.5 224.5q0 183 105 331t272 210v-166q-103 -55 -165 -155t-62 -220q0 -177 125 -302t302 -125t302 125t125 302q0 120 -62 220t-165 155z" />
+<glyph unicode="&#xe018;" d="M1200 1h-200v1200h200v-1200zM900 1h-200v800h200v-800zM600 1h-200v500h200v-500zM300 301h-200v-300h200v300z" />
+<glyph unicode="&#xe019;" d="M488 183l38 -151q40 -5 74 -5q27 0 74 5l38 151l6 2q46 13 93 39l5 3l134 -81q56 44 104 105l-80 134l3 5q24 44 39 93l1 6l152 38q5 40 5 74q0 28 -5 73l-152 38l-1 6q-16 51 -39 93l-3 5l80 134q-44 58 -104 105l-134 -81l-5 3q-45 25 -93 39l-6 1l-38 152q-40 5 -74 5 q-27 0 -74 -5l-38 -152l-5 -1q-50 -14 -94 -39l-5 -3l-133 81q-59 -47 -105 -105l80 -134l-3 -5q-25 -47 -38 -93l-2 -6l-151 -38q-6 -48 -6 -73q0 -33 6 -74l151 -38l2 -6q14 -49 38 -93l3 -5l-80 -134q45 -59 105 -105l133 81 [...]
+<glyph unicode="&#xe020;" d="M900 1100h275q10 0 17.5 -7.5t7.5 -17.5v-50q0 -11 -7 -18t-18 -7h-1050q-11 0 -18 7t-7 18v50q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5v-100zM800 1100v100h-300v-100h300zM200 900h900v-800q0 -41 -29.5 -71 t-70.5 -30h-700q-41 0 -70.5 30t-29.5 71v800zM300 100h100v700h-100v-700zM500 100h100v700h-100v-700zM700 100h100v700h-100v-700zM900 100h100v700h-100v-700z" />
+<glyph unicode="&#xe021;" d="M1301 601h-200v-600h-300v400h-300v-400h-300v600h-200l656 644z" />
+<glyph unicode="&#xe022;" d="M600 700h400v-675q0 -11 -7 -18t-18 -7h-850q-11 0 -18 7t-7 18v1150q0 11 7 18t18 7h475v-500zM1000 800h-300v300z" />
+<glyph unicode="&#xe023;" d="M600 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM600 1014q-171 0 -292.5 -121.5t-121.5 -292.5t121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5zM600 600h200 v-100h-300v400h100v-300z" />
+<glyph unicode="&#xe024;" d="M721 400h-242l-40 -400h-539l431 1200h209l-21 -300h162l-20 300h208l431 -1200h-538zM712 500l-27 300h-170l-27 -300h224z" />
+<glyph unicode="&#xe025;" d="M1100 400v-400h-1100v400h490l-290 300h200v500h300v-500h200l-290 -300h490zM988 300h-175v-100h175v100z" />
+<glyph unicode="&#xe026;" d="M600 1199q122 0 233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233t47.5 233t127.5 191t191 127.5t233 47.5zM600 1012q-170 0 -291 -121t-121 -291t121 -291t291 -121t291 121 t121 291t-121 291t-291 121zM700 600h150l-250 -300l-250 300h150v300h200v-300z" />
+<glyph unicode="&#xe027;" d="M600 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM600 1014q-171 0 -292.5 -121.5t-121.5 -292.5t121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5zM850 600h-150 v-300h-200v300h-150l250 300z" />
+<glyph unicode="&#xe028;" d="M0 500l200 700h800q199 -700 200 -700v-475q0 -11 -7 -18t-18 -7h-1150q-11 0 -18 7t-7 18v475zM903 1000h-606l-97 -500h200l50 -200h300l50 200h200z" />
+<glyph unicode="&#xe029;" d="M600 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM600 1014q-171 0 -292.5 -121.5t-121.5 -292.5q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5zM797 598 l-297 -201v401z" />
+<glyph unicode="&#xe030;" d="M1177 600h-150q0 -177 -125 -302t-302 -125t-302 125t-125 302t125 302t302 125q136 0 246 -81l-146 -146h400v400l-145 -145q-157 122 -355 122q-118 0 -224.5 -45.5t-184 -123t-123 -184t-45.5 -224.5t45.5 -224.5t123 -184t184 -123t224.5 -45.5t224.5 45.5t184 123 t123 184t45.5 224.5z" />
+<glyph unicode="&#xe031;" d="M700 800l147 147q-112 80 -247 80q-177 0 -302 -125t-125 -302h-150q0 118 45.5 224.5t123 184t184 123t224.5 45.5q198 0 355 -122l145 145v-400h-400zM500 400l-147 -147q112 -80 247 -80q177 0 302 125t125 302h150q0 -118 -45.5 -224.5t-123 -184t-184 -123 t-224.5 -45.5q-198 0 -355 122l-145 -145v400h400z" />
+<glyph unicode="&#xe032;" d="M100 1200v-1200h1100v1200h-1100zM1100 100h-900v900h900v-900zM400 800h-100v100h100v-100zM1000 800h-500v100h500v-100zM400 600h-100v100h100v-100zM1000 600h-500v100h500v-100zM400 400h-100v100h100v-100zM1000 400h-500v100h500v-100zM400 200h-100v100h100v-100 zM1000 300h-500v-100h500v100z" />
+<glyph unicode="&#xe034;" d="M200 0h-100v1100h100v-1100zM1100 600v500q-40 -81 -101.5 -115.5t-127.5 -29.5t-138 25t-139.5 40t-125.5 25t-103 -29.5t-65 -115.5v-500q60 60 127.5 84t127.5 17.5t122 -23t119 -30t110 -11t103 42t91 120.5z" />
+<glyph unicode="&#xe035;" d="M1200 275v300q0 116 -49.5 227t-131 192.5t-192.5 131t-227 49.5t-227 -49.5t-192.5 -131t-131 -192.5t-49.5 -227v-300q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 127 70.5 231.5t184.5 161.5t245 57t245 -57t184.5 -161.5t70.5 -231.5v-300q0 -11 7 -18t18 -7h50 q11 0 18 7t7 18zM400 480v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14zM1000 480v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14z" />
+<glyph unicode="&#xe036;" d="M0 800v-400h300l300 -200v800l-300 -200h-300zM971 600l141 -141l-71 -71l-141 141l-141 -141l-71 71l141 141l-141 141l71 71l141 -141l141 141l71 -71z" />
+<glyph unicode="&#xe037;" d="M0 800v-400h300l300 -200v800l-300 -200h-300zM700 857l69 53q111 -135 111 -310q0 -169 -106 -302l-67 54q86 110 86 248q0 146 -93 257z" />
+<glyph unicode="&#xe038;" d="M974 186l6 8q142 178 142 405q0 230 -144 408l-6 8l-83 -64l7 -8q123 -151 123 -344q0 -189 -119 -339l-7 -8zM300 801l300 200v-800l-300 200h-300v400h300zM702 858l69 53q111 -135 111 -310q0 -170 -106 -303l-67 55q86 110 86 248q0 145 -93 257z" />
+<glyph unicode="&#xe039;" d="M100 700h400v100h100v100h-100v300h-500v-600h100v100zM1200 700v500h-600v-200h100v-300h200v-300h300v200h-200v100h200zM100 1100h300v-300h-300v300zM800 800v300h300v-300h-300zM200 900h100v100h-100v-100zM900 1000h100v-100h-100v100zM300 600h-100v-100h-200 v-500h500v500h-200v100zM900 200v-100h-200v100h-100v100h100v200h-200v100h300v-300h200v-100h-100zM400 400v-300h-300v300h300zM300 200h-100v100h100v-100zM1100 300h100v-100h-100v100zM600 100h100v-100h-100v100zM1200 100v [...]
+<glyph unicode="&#xe040;" d="M100 1200h-100v-1000h100v1000zM300 200h-100v1000h100v-1000zM700 200h-200v1000h200v-1000zM900 200h-100v1000h100v-1000zM1200 1200v-1000h-200v1000h200zM400 100v-100h-300v100h300zM500 91h100v-91h-100v91zM700 91h100v-91h-100v91zM1100 91v-91h-200v91h200z " />
+<glyph unicode="&#xe041;" d="M1200 500l-500 -500l-699 700v475q0 10 7.5 17.5t17.5 7.5h474zM320 882q29 29 29 71t-29 71q-30 30 -71.5 30t-71.5 -30q-29 -29 -29 -71t29 -71q30 -30 71.5 -30t71.5 30z" />
+<glyph unicode="&#xe042;" d="M1201 500l-500 -500l-699 700v475q0 11 7 18t18 7h474zM1501 500l-500 -500l-50 50l450 450l-700 700h100zM320 882q30 29 30 71t-30 71q-29 30 -71 30t-71 -30q-30 -29 -30 -71t30 -71q29 -30 71 -30t71 30z" />
+<glyph unicode="&#xe043;" d="M1200 1200v-1000l-100 -100v1000h-750l-100 -100h750v-1000h-900v1025l175 175h925z" />
+<glyph unicode="&#xe045;" d="M947 829l-94 346q-2 11 -10 18t-18 7h-450q-10 0 -18 -7t-10 -18l-94 -346l40 -124h592zM1200 800v-700h-200v200h-800v-200h-200v700h200l100 -200h600l100 200h200zM881 176l38 -152q2 -10 -3.5 -17t-15.5 -7h-600q-10 0 -15.5 7t-3.5 17l38 152q2 10 11.5 17t19.5 7 h500q10 0 19.5 -7t11.5 -17z" />
+<glyph unicode="&#xe047;" d="M1200 0v66q-34 1 -74 43q-18 19 -33 42t-21 37l-6 13l-385 998h-93l-399 -1006q-24 -48 -52 -75q-12 -12 -33 -25t-36 -20l-15 -7v-66h365v66q-41 0 -72 11t-49 38t1 71l92 234h391l82 -222q16 -45 -5.5 -88.5t-74.5 -43.5v-66h417zM416 521l178 457l46 -140l116 -317 h-340z" />
+<glyph unicode="&#xe048;" d="M100 1199h471q120 0 213 -88t93 -228q0 -55 -11.5 -101.5t-28 -74t-33.5 -47.5t-28 -28l-12 -7q8 -3 21.5 -9t48 -31.5t60.5 -58t47.5 -91.5t21.5 -129q0 -84 -59 -156.5t-142 -111t-162 -38.5h-500v89q41 7 70.5 32.5t29.5 65.5v827q0 28 -1 39.5t-5.5 26t-15.5 21 t-29 14t-49 14.5v70zM400 1079v-379h139q76 0 130 61.5t54 138.5q0 82 -84 130.5t-239 48.5zM400 200h161q89 0 153 48.5t64 132.5q0 90 -62.5 154.5t-156.5 64.5h-159v-400z" />
+<glyph unicode="&#xe049;" d="M877 1200l2 -57q-33 -8 -62 -25.5t-46 -37t-29.5 -38t-17.5 -30.5l-5 -12l-128 -825q-10 -52 14 -82t95 -36v-57h-500v57q77 7 134.5 40.5t65.5 80.5l173 849q10 56 -10 74t-91 37q-6 1 -10.5 2.5t-9.5 2.5v57h425z" />
+<glyph unicode="&#xe050;" d="M1150 1200h150v-300h-50q0 29 -8 48.5t-18.5 30t-33.5 15t-39.5 5.5t-50.5 1h-200v-850l100 -50v-100h-400v100l100 50v850h-200q-34 0 -50.5 -1t-40 -5.5t-33.5 -15t-18.5 -30t-8.5 -48.5h-49v300h150h700zM100 1000v-800h75l-125 -167l-125 167h75v800h-75l125 167 l125 -167h-75z" />
+<glyph unicode="&#xe051;" d="M950 1201h150v-300h-50q0 29 -8 48.5t-18 30t-33.5 15t-40 5.5t-50.5 1h-200v-650l100 -50v-100h-400v100l100 50v650h-200q-34 0 -50.5 -1t-39.5 -5.5t-33.5 -15t-18.5 -30t-8 -48.5h-50v300h150h700zM200 101h800v75l167 -125l-167 -125v75h-800v-75l-167 125l167 125 v-75z" />
+<glyph unicode="&#xe052;" d="M700 950v100q0 21 -14.5 35.5t-35.5 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h600q21 0 35.5 15t14.5 35zM1100 650v100q0 21 -14.5 35.5t-35.5 14.5h-1000q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h1000 q21 0 35.5 15t14.5 35zM900 350v100q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35zM1200 50v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -3 [...]
+<glyph unicode="&#xe053;" d="M1000 950v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35zM1200 650v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h1100 q21 0 35.5 15t14.5 35zM1000 350v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35zM1200 50v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5  [...]
+<glyph unicode="&#xe054;" d="M500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-600q-21 0 -35.5 15t-14.5 35zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1000q-21 0 -35.5 15 t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 [...]
+<glyph unicode="&#xe055;" d="M0 950v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15 t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 - [...]
+<glyph unicode="&#xe056;" d="M0 950v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM300 950v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM300 650v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 [...]
+<glyph unicode="&#xe057;" d="M400 1100h-100v-1100h100v1100zM700 950v100q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35zM1100 650v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15 h500q20 0 35 15t15 35zM100 425v75h-201v100h201v75l166 -125zM900 350v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35zM1200 50v100q0 21 -15 35.5t-35  [...]
+<glyph unicode="&#xe058;" d="M201 950v100q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35zM801 1100h100v-1100h-100v1100zM601 650v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15 h500q20 0 35 15t15 35zM1101 425v75h200v100h-200v75l-167 -125zM401 350v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35zM701 50v100q0 21 -15 35.5t-35  [...]
+<glyph unicode="&#xe059;" d="M900 925v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53v650q0 31 22 53t53 22h750q31 0 53 -22t22 -53zM1200 300l-300 300l300 300v-600z" />
+<glyph unicode="&#xe060;" d="M1200 1056v-1012q0 -18 -12.5 -31t-31.5 -13h-1112q-18 0 -31 13t-13 31v1012q0 18 13 31t31 13h1112q19 0 31.5 -13t12.5 -31zM1100 1000h-1000v-737l247 182l298 -131l-74 156l293 318l236 -288v500zM476 750q0 -56 -39 -95t-95 -39t-95 39t-39 95t39 95t95 39t95 -39 t39 -95z" />
+<glyph unicode="&#xe062;" d="M600 1213q123 0 227 -63t164.5 -169.5t60.5 -229.5t-73 -272q-73 -114 -166.5 -237t-150.5 -189l-57 -66q-10 9 -27 26t-66.5 70.5t-96 109t-104 135.5t-100.5 155q-63 139 -63 262q0 124 60.5 231.5t165 172t226.5 64.5zM599 514q107 0 182.5 75.5t75.5 182.5t-75.5 182 t-182.5 75t-182 -75.5t-75 -181.5q0 -107 75.5 -182.5t181.5 -75.5z" />
+<glyph unicode="&#xe063;" d="M600 1199q122 0 233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233t47.5 233t127.5 191t191 127.5t233 47.5zM600 173v854q-176 0 -301.5 -125t-125.5 -302t125.5 -302t301.5 -125z " />
+<glyph unicode="&#xe064;" d="M554 1295q21 -71 57.5 -142.5t76 -130.5t83 -118.5t82 -117t70 -116t50 -125.5t18.5 -136q0 -89 -39 -165.5t-102 -126.5t-140 -79.5t-156 -33.5q-114 6 -211.5 53t-161.5 138.5t-64 210.5q0 94 34 186t88.5 172.5t112 159t115 177t87.5 194.5zM455 296q-7 6 -18 17 t-34 48t-33 77q-15 73 -14 143.5t10 122.5l9 51q-92 -110 -119.5 -185t-12.5 -156q14 -82 59.5 -136t136.5 -80z" />
+<glyph unicode="&#xe065;" d="M1108 902l113 113l-21 85l-92 28l-113 -113zM1100 625v-225q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5v300q0 165 117.5 282.5t282.5 117.5q366 -6 397 -14l-186 -186h-311q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5 t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v125zM436 341l161 50l412 412l-114 113l-405 -405z" />
+<glyph unicode="&#xe066;" d="M1100 453v-53q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5v300q0 165 117.5 282.5t282.5 117.5h261l2 -80q-133 -32 -218 -120h-145q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5z M813 431l360 324l-359 318v-216q-7 0 -19 -1t-48 -8t-69.5 -18.5t-76.5 -37t-76.5 -59t-62 -88t-39.5 -121.5q30 38 81.5 64t103 35.5t99 14t77.5 3.5l29 -1v-209z" />
+<glyph unicode="&#xe067;" d="M1100 569v-169q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5v300q0 165 117.5 282.5t282.5 117.5h300q60 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69z M625 348l566 567l-136 137l-430 -431l-147 147l-136 -136z" />
+<glyph unicode="&#xe068;" d="M900 303v198h-200v-200h195l-295 -300l-300 300h200v200h-200v-198l-300 300l300 296v-198h200v200h-200l300 300l295 -300h-195v-200h200v198l300 -296z" />
+<glyph unicode="&#xe069;" d="M900 0l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-1100z" />
+<glyph unicode="&#xe070;" d="M1200 0l-500 488v-488l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-487l500 487v-1100z" />
+<glyph unicode="&#xe071;" d="M1200 0l-500 488v-488l-564 550l564 550v-487l500 487v-1100z" />
+<glyph unicode="&#xe072;" d="M1100 550l-900 550v-1100z" />
+<glyph unicode="&#xe073;" d="M500 150v800q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5t-14.5 -35.5v-800q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5zM900 150v800q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5t-14.5 -35.5v-800q0 -21 14.5 -35.5t35.5 -14.5h200 q21 0 35.5 14.5t14.5 35.5z" />
+<glyph unicode="&#xe074;" d="M1100 150v800q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5v-800q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35z" />
+<glyph unicode="&#xe075;" d="M500 0v488l-500 -488v1100l500 -487v487l564 -550z" />
+<glyph unicode="&#xe076;" d="M1050 1100h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-500 -488v488l-500 -488v1100l500 -487v487l500 -487v437q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe077;" d="M850 1100h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-500 -488v1100l500 -487v437q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="&#xe078;" d="M650 1064l-550 -564h1100zM1200 350v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5z" />
+<glyph unicode="&#xe079;" d="M777 7l240 240l-353 353l353 353l-240 240l-592 -594z" />
+<glyph unicode="&#xe080;" d="M513 -46l-241 240l353 353l-353 353l241 240l572 -571l21 -22l-1 -1v-1z" />
+<glyph unicode="&#xe081;" d="M600 1197q162 0 299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5t80 299.5t217.5 217.5t299.5 80zM500 900v-200h-200v-200h200v-200h200v200h200v200h-200v200h-200z" />
+<glyph unicode="&#xe082;" d="M600 1197q162 0 299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5t80 299.5t217.5 217.5t299.5 80zM300 700v-200h600v200h-600z" />
+<glyph unicode="&#xe083;" d="M600 1197q162 0 299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5t80 299.5t217.5 217.5t299.5 80zM247 741l141 -141l-142 -141l213 -213l141 142l141 -142l213 213l-142 141l142 141l-213 212l-141 -141 l-141 142z" />
+<glyph unicode="&#xe084;" d="M600 1197q162 0 299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5t80 299.5t217.5 217.5t299.5 80zM546 623l-102 102l-174 -174l276 -277l411 411l-175 174z" />
+<glyph unicode="&#xe085;" d="M600 1197q162 0 299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5t80 299.5t217.5 217.5t299.5 80zM500 500h200q5 3 14 8t31.5 25.5t39.5 45.5t31 69t14 94q0 51 -17.5 89t-42 58t-58.5 32t-58.5 15t-51.5 3 q-105 0 -172 -56t-67 -183h144q4 0 11.5 -1t11 -1t6.5 3t3 9t1 11t3.5 8.5t3.5 6t5.5 4t6.5 2.5t9 1.5t9 0.5h11.5h12.5q19 0 30 -10t11 -26q0 -22 -4 -28t-27 -22q-5 -1 -12.5 -3t-27 -13.5t-34 -27t-26.5 -46t-11 -68.5zM500 400 [...]
+<glyph unicode="&#xe086;" d="M600 1197q162 0 299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5t80 299.5t217.5 217.5t299.5 80zM500 900v-100h200v100h-200zM400 700v-100h100v-200h-100v-100h400v100h-100v300h-300z" />
+<glyph unicode="&#xe087;" d="M1200 700v-200h-203q-25 -102 -116.5 -186t-180.5 -117v-197h-200v197q-140 27 -208 102.5t-98 200.5h-194v200h194q15 60 36 104.5t55.5 86t88 69t126.5 40.5v200h200v-200q54 -20 113 -60t112.5 -105.5t71.5 -134.5h203zM700 500v-206q149 48 201 206h-201v200h200 q-25 74 -76 127.5t-124 76.5v-204h-200v203q-75 -24 -130 -77.5t-79 -125.5h209v-200h-210q24 -73 79.5 -127.5t130.5 -78.5v206h200z" />
+<glyph unicode="&#xe088;" d="M600 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM600 1014q-171 0 -292.5 -121.5t-121.5 -292.5t121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5zM844 735 l-135 -135l135 -135l-109 -109l-135 135l-135 -135l-109 109l135 135l-135 135l109 109l135 -135l135 135z" />
+<glyph unicode="&#xe089;" d="M600 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM600 1014q-171 0 -292.5 -121.5t-121.5 -292.5t121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5zM896 654 l-346 -345l-228 228l141 141l87 -87l204 205z" />
+<glyph unicode="&#xe090;" d="M600 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM248 385l568 567q-100 62 -216 62q-171 0 -292.5 -121.5t-121.5 -292.5q0 -115 62 -215zM955 809l-564 -564q97 -59 209 -59q171 0 292.5 121.5 t121.5 292.5q0 112 -59 209z" />
+<glyph unicode="&#xe091;" d="M1200 400h-600v-301l-600 448l600 453v-300h600v-300z" />
+<glyph unicode="&#xe092;" d="M600 400h-600v300h600v300l600 -453l-600 -448v301z" />
+<glyph unicode="&#xe093;" d="M1098 600h-298v-600h-300v600h-296l450 600z" />
+<glyph unicode="&#xe094;" d="M998 600l-449 -600l-445 600h296v600h300v-600h298z" />
+<glyph unicode="&#xe095;" d="M600 199v301q-95 -2 -183 -20t-170 -52t-147 -92.5t-100 -135.5q6 132 41 238.5t103.5 193t184 138t271.5 59.5v271l600 -453z" />
+<glyph unicode="&#xe096;" d="M1200 1200h-400l129 -129l-294 -294l142 -142l294 294l129 -129v400zM565 423l-294 -294l129 -129h-400v400l129 -129l294 294z" />
+<glyph unicode="&#xe097;" d="M871 730l129 -130h-400v400l129 -129l295 295l142 -141zM200 600h400v-400l-129 130l-295 -295l-142 141l295 295z" />
+<glyph unicode="&#xe101;" d="M600 1177q118 0 224.5 -45.5t184 -123t123 -184t45.5 -224.5t-45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5t45.5 224.5t123 184t184 123t224.5 45.5zM686 549l58 302q4 20 -8 34.5t-33 14.5h-207q-20 0 -32 -14.5t-8 -34.5 l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5zM700 400h-200v-100h200v100z" />
+<glyph unicode="&#xe102;" d="M1200 900h-111v6t-1 15t-3 18l-34 172q-11 39 -41.5 63t-69.5 24q-32 0 -61 -17l-239 -144q-22 -13 -40 -35q-19 24 -40 36l-238 144q-33 18 -62 18q-39 0 -69.5 -23t-40.5 -61l-35 -177q-2 -8 -3 -18t-1 -15v-6h-111v-100h100v-200h400v300h200v-300h400v200h100v100z M731 900l202 197q5 -12 12 -32.5t23 -64t25 -72t7 -28.5h-269zM481 900h-281q-3 0 14 48t35 96l18 47zM100 0h400v400h-400v-400zM700 400h400v-400h-400v400z" />
+<glyph unicode="&#xe103;" d="M0 121l216 193q-9 53 -13 83t-5.5 94t9 113t38.5 114t74 124q47 60 99.5 102.5t103 68t127.5 48t145.5 37.5t184.5 43.5t220 58.5q0 -189 -22 -343t-59 -258t-89 -181.5t-108.5 -120t-122 -68t-125.5 -30t-121.5 -1.5t-107.5 12.5t-87.5 17t-56.5 7.5l-99 -55l-201 -202 v143zM692 611q70 38 118.5 69.5t102 79t99 111.5t86.5 148q22 50 24 60t-6 19q-7 5 -17 5t-26.5 -14.5t-33.5 -39.5q-35 -51 -113.5 -108.5t-139.5 -89.5l-61 -32q-369 -197 -458 -401q-48 -111 -28.5 -117.5t86.5 76.5q55 66 36 [...]
+<glyph unicode="&#xe105;" d="M1261 600l-26 -40q-6 -10 -20 -30t-49 -63.5t-74.5 -85.5t-97 -90t-116.5 -83.5t-132.5 -59t-145.5 -23.5t-145.5 23.5t-132.5 59t-116.5 83.5t-97 90t-74.5 85.5t-49 63.5t-20 30l-26 40l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5 t145.5 -23.5t132.5 -59t116.5 -83.5t97 -90t74.5 -85.5t49 -63.5t20 -30zM600 240q64 0 123.5 20t100.5 45.5t85.5 71.5t66.5 75.5t58 81.5t47 66q-1 1 -28.5 37.5t-42 55t-43.5 53t-57.5 63.5t-58.5 54q49 -74 49 -163q0 -124 -88 - [...]
+<glyph unicode="&#xe106;" d="M906 1200l-314 -1200h-148l37 143q-82 21 -165 71.5t-140 102t-109.5 112t-72 88.5t-29.5 43l-26 40l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5q61 0 121 -17l37 142h148zM1261 600l-26 -40q-7 -12 -25.5 -38t-63.5 -79.5t-95.5 -102.5 t-124 -100t-146.5 -79l38 145q22 15 44.5 34t46 44t40.5 44t41 50.5t33.5 43.5t33 44t24.5 34q-97 127 -140 175l39 146q67 -54 131.5 -125.5t87.5 -103.5t36 -52zM513 264l37 141q-107 18 -178.5 101.5t-71.5 193.5q0 85 46 158 [...]
+<glyph unicode="&#xe107;" d="M-47 0h1294q37 0 50.5 35.5t-7.5 67.5l-642 1056q-20 33 -48 36t-48 -29l-642 -1066q-21 -32 -7.5 -66t50.5 -34zM700 200v100h-200v-100h-345l445 723l445 -723h-345zM700 700h-200v-100l100 -300l100 300v100z" />
+<glyph unicode="&#xe108;" d="M800 711l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -91 100 -113v-64q0 -21 -13 -29t-32 1l-94 78h-222l-94 -78q-19 -9 -32 -1t-13 29v64q0 22 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5v41q0 20 11 44.5t26 38.5 l363 325v339q0 62 44 106t106 44t106 -44t44 -106v-339z" />
+<glyph unicode="&#xe110;" d="M941 800l-600 -600h-341v200h259l600 600h241v198l300 -295l-300 -300v197h-159zM381 678l141 142l-181 180h-341v-200h259zM1100 598l300 -295l-300 -300v197h-241l-181 181l141 142l122 -123h159v198z" />
+<glyph unicode="&#xe111;" d="M100 1100h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5z" />
+<glyph unicode="&#xe112;" d="M400 900h-300v300h300v-300zM1100 900h-300v300h300v-300zM1100 800v-200q0 -42 -3 -83t-15 -104t-31.5 -116t-58 -109.5t-89 -96.5t-129 -65.5t-174.5 -25.5t-174.5 25.5t-129 65.5t-89 96.5t-58 109.5t-31.5 116t-15 104t-3 83v200h300v-250q0 -113 6 -145 q17 -92 102 -117q39 -11 92 -11q37 0 66.5 5.5t50 15.5t36 24t24 31.5t14 37.5t7 42t2.5 45t0 47v25v250h300z" />
+<glyph unicode="&#xe113;" d="M902 184l226 227l-578 579l-580 -579l227 -227l352 353z" />
+<glyph unicode="&#xe114;" d="M650 218l578 579l-226 227l-353 -353l-352 353l-227 -227z" />
+<glyph unicode="&#xe115;" d="M1198 400v600h-796l215 -200h381v-400h-198l299 -283l299 283h-200zM-198 700l299 283l300 -283h-203v-400h385l215 -200h-800v600h-196z" />
+<glyph unicode="&#xe116;" d="M1050 1200h94q20 0 35 -14.5t15 -35.5t-15 -35.5t-35 -14.5h-54l-201 -961q-2 -4 -6 -10.5t-19 -17.5t-33 -11h-31v-50q0 -20 -14.5 -35t-35.5 -15t-35.5 15t-14.5 35v50h-300v-50q0 -20 -14.5 -35t-35.5 -15t-35.5 15t-14.5 35v50h-50q-21 0 -35.5 15t-14.5 35 q0 21 14.5 35.5t35.5 14.5h535l48 200h-633q-32 0 -54.5 21t-27.5 43l-100 475q-5 24 10 42q14 19 39 19h896l38 162q5 17 18.5 27.5t30.5 10.5z" />
+<glyph unicode="&#xe117;" d="M1200 1000v-100h-1200v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500zM0 800h1200v-800h-1200v800z" />
+<glyph unicode="&#xe118;" d="M201 800l-200 -400v600h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-200h-1000zM1501 700l-300 -700h-1200l300 700h1200z" />
+<glyph unicode="&#xe119;" d="M302 300h198v600h-198l298 300l298 -300h-198v-600h198l-298 -300z" />
+<glyph unicode="&#xe120;" d="M900 303v197h-600v-197l-300 297l300 298v-198h600v198l300 -298z" />
+<glyph unicode="&#xe121;" d="M31 400l172 739q5 22 23 41.5t38 19.5h672q19 0 37.5 -22.5t23.5 -45.5l172 -732h-1138zM100 300h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM900 200h-100v-100h100v100z M1100 200h-100v-100h100v100z" />
+<glyph unicode="&#xe122;" d="M1100 200v850q0 21 14.5 35.5t35.5 14.5q20 0 35 -14.5t15 -35.5v-850q0 -20 -15 -35t-35 -15q-21 0 -35.5 15t-14.5 35zM325 800l675 250v-850l-675 200h-38l47 -276q2 -12 -3 -17.5t-11 -6t-21 -0.5h-8h-83q-20 0 -34.5 14t-18.5 35q-56 337 -56 351v250v5 q0 13 0.5 18.5t2.5 13t8 10.5t15 3h200zM-101 600v50q0 24 25 49t50 38l25 13v-250l-11 5.5t-24 14t-30 21.5t-24 27.5t-11 31.5z" />
+<glyph unicode="&#xe124;" d="M445 1180l-45 -233l-224 78l78 -225l-233 -44l179 -156l-179 -155l233 -45l-78 -224l224 78l45 -233l155 179l155 -179l45 233l224 -78l-78 224l234 45l-180 155l180 156l-234 44l78 225l-224 -78l-45 233l-155 -180z" />
+<glyph unicode="&#xe125;" d="M700 1200h-50q-27 0 -51 -20t-38 -48l-96 -198l-145 -196q-20 -26 -20 -63v-400q0 -75 100 -75h61q123 -100 139 -100h250q46 0 83 57l238 344q29 31 29 74v100q0 44 -30.5 84.5t-69.5 40.5h-328q28 118 28 125v150q0 44 -30.5 84.5t-69.5 40.5zM700 925l-50 -225h450 v-125l-250 -375h-214l-136 100h-100v375l150 212l100 213h50v-175zM0 800v-600h200v600h-200z" />
+<glyph unicode="&#xe126;" d="M700 0h-50q-27 0 -51 20t-38 48l-96 198l-145 196q-20 26 -20 63v400q0 75 100 75h61q123 100 139 100h250q46 0 83 -57l238 -344q29 -31 29 -74v-100q0 -44 -30.5 -84.5t-69.5 -40.5h-328q28 -118 28 -125v-150q0 -44 -30.5 -84.5t-69.5 -40.5zM200 400h-200v600h200 v-600zM700 275l-50 225h450v125l-250 375h-214l-136 -100h-100v-375l150 -212l100 -213h50v175z" />
+<glyph unicode="&#xe127;" d="M364 873l362 230q14 6 25 6q17 0 29 -12l109 -112q14 -14 14 -34q0 -18 -11 -32l-85 -121h302q85 0 138.5 -38t53.5 -110t-54.5 -111t-138.5 -39h-107l-130 -339q-7 -22 -20.5 -41.5t-28.5 -19.5h-341q-7 0 -90 81t-83 94v525q0 17 14 35.5t28 28.5zM408 792v-503 l100 -89h293l131 339q6 21 19.5 41t28.5 20h203q16 0 25 15t9 36q0 20 -9 34.5t-25 14.5h-457h-6.5h-7.5t-6.5 0.5t-6 1t-5 1.5t-5.5 2.5t-4 4t-4 5.5q-5 12 -5 20q0 14 10 27l147 183l-86 83zM208 200h-200v600h200v-600z" />
+<glyph unicode="&#xe128;" d="M475 1104l365 -230q7 -4 16.5 -10.5t26 -26t16.5 -36.5v-526q0 -13 -85.5 -93.5t-93.5 -80.5h-342q-15 0 -28.5 20t-19.5 41l-131 339h-106q-84 0 -139 39t-55 111t54 110t139 37h302l-85 121q-11 16 -11 32q0 21 14 34l109 113q13 12 29 12q11 0 25 -6zM370 946 l145 -184q10 -11 10 -26q0 -11 -5 -20q-1 -3 -3.5 -5.5l-4 -4t-5 -2.5t-5.5 -1.5t-6.5 -1t-6.5 -0.5h-7.5h-6.5h-476v-100h222q15 0 28.5 -20.5t19.5 -40.5l131 -339h293l106 89v502l-342 237zM1199 201h-200v600h200v-600z" />
+<glyph unicode="&#xe129;" d="M1100 473v342q0 15 -20 28.5t-41 19.5l-339 131v106q0 84 -39 139t-111 55t-110 -53.5t-38 -138.5v-302l-121 84q-15 12 -33.5 11.5t-32.5 -13.5l-112 -110q-22 -22 -6 -53l230 -363q4 -6 10.5 -15.5t26 -25t36.5 -15.5h525q13 0 94 83t81 90zM911 400h-503l-236 339 l83 86l183 -146q22 -18 47 -5q3 1 5.5 3.5l4 4t2.5 5t1.5 5.5t1 6.5t0.5 6v7.5v7v456q0 22 25 31t50 -0.5t25 -30.5v-202q0 -16 20 -29.5t41 -19.5l339 -130v-294zM1000 200v-200h-600v200h600z" />
+<glyph unicode="&#xe130;" d="M305 1104v200h600v-200h-600zM605 310l339 131q20 6 40.5 19.5t20.5 28.5v342q0 7 -81 90t-94 83h-525q-17 0 -35.5 -14t-28.5 -28l-10 -15l-230 -362q-15 -31 7 -53l112 -110q13 -13 32 -13.5t34 10.5l121 85l-1 -302q0 -84 38.5 -138t110.5 -54t111 55t39 139v106z M905 804v-294l-340 -130q-20 -6 -40 -20t-20 -29v-202q0 -22 -25 -31t-50 0t-25 31v456v14.5t-1.5 11.5t-5 12t-9.5 7q-24 13 -46 -5l-184 -146l-83 86l237 339h503z" />
+<glyph unicode="&#xe131;" d="M603 1195q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5zM598 701h-298v-201h300l-2 -194l402 294l-402 298v-197z" />
+<glyph unicode="&#xe132;" d="M597 1195q122 0 232.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-218 -217.5t-300 -80t-299.5 80t-217.5 217.5t-80 299.5q0 122 47.5 232.5t127.5 190.5t190.5 127.5t231.5 47.5zM200 600l400 -294v194h302v201h-300v197z" />
+<glyph unicode="&#xe133;" d="M603 1195q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5zM300 600h200v-300h200v300h200l-300 400z" />
+<glyph unicode="&#xe134;" d="M603 1195q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5zM500 900v-300h-200l300 -400l300 400h-200v300h-200z" />
+<glyph unicode="&#xe135;" d="M603 1195q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5zM627 1101q-15 -12 -36.5 -21t-34.5 -12t-44 -8t-39 -6 q-15 -3 -45.5 0.5t-45.5 -2.5q-21 -7 -52 -26.5t-34 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -90.5t-29.5 -79.5q-8 -33 5.5 -92.5t7.5 -87.5q0 -9 17 -44t16 -60q12 0 23 -5.5t23 -15t20 -13.5q24 -12 108 -42q22 -8 53 -31.5t59 [...]
+<glyph unicode="&#xe137;" horiz-adv-x="1220" d="M100 1196h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 1096h-200v-100h200v100zM100 796h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 696h-500v-100h500v100zM100 396h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70 [...]
+<glyph unicode="&#xe138;" d="M1100 1200v-100h-1000v100h1000zM150 1000h900l-350 -500v-300l-200 -200v500z" />
+<glyph unicode="&#xe140;" d="M329 729l142 142l-200 200l129 129h-400v-400l129 129zM1200 1200v-400l-129 129l-200 -200l-142 142l200 200l-129 129h400zM271 129l129 -129h-400v400l129 -129l200 200l142 -142zM1071 271l129 129v-400h-400l129 129l-200 200l142 142z" />
+<glyph unicode="&#xe141;" d="M596 1192q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM596 1010q-171 0 -292.5 -121.5t-121.5 -292.5q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5zM455 905 q22 0 38 -16t16 -39t-16 -39t-38 -16q-23 0 -39 16.5t-16 38.5t16 38.5t39 16.5zM708 821l1 1q-9 14 -9 28q0 22 16 38.5t39 16.5q22 0 38 -16t16 -39t-16 -39t-38 -16q-14 0 -29 10l-55 -145q17 -22 17 -51q0 -36 -25.5 -61.5t- [...]
+<glyph unicode="&#xe143;" d="M649 54l-16 22q-90 125 -293 323q-71 70 -104.5 105.5t-77 89.5t-61 99t-17.5 91q0 131 98.5 229.5t230.5 98.5q143 0 241 -129q103 129 246 129q129 0 226 -98.5t97 -229.5q0 -46 -17.5 -91t-61 -99t-77 -89.5t-104.5 -105.5q-203 -198 -293 -323zM844 524l12 12 q64 62 97.5 97t64.5 79t31 72q0 71 -48 119t-105 48q-74 0 -132 -82l-118 -171l-114 174q-51 79 -123 79q-60 0 -109.5 -49t-49.5 -118q0 -27 30.5 -70t61.5 -75.5t95 -94.5l22 -22q93 -90 190 -201q82 92 195 203z" />
+<glyph unicode="&#xe144;" d="M476 406l19 -17l105 105l-212 212l389 389l247 -247l-95 -96l18 -18q46 -46 77 -99l29 29q35 35 62.5 88t27.5 96q0 93 -66 159l-141 141q-66 66 -159 66q-95 0 -159 -66l-283 -283q-66 -64 -66 -159q0 -93 66 -159zM123 193l141 -141q66 -66 159 -66q95 0 159 66 l283 283q66 66 66 159t-66 159l-141 141q-12 12 -19 17l-105 -105l212 -212l-389 -389l-247 248l95 95l-18 18q-46 45 -75 101l-55 -55q-66 -66 -66 -159q0 -94 66 -160z" />
+<glyph unicode="&#xe145;" d="M200 100v953q0 21 30 46t81 48t129 38t163 15t162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5zM900 1000h-600v-700h600v700zM600 46q43 0 73.5 30.5t30.5 73.5t-30.5 73.5t-73.5 30.5t-73.5 -30.5t-30.5 -73.5 t30.5 -73.5t73.5 -30.5z" />
+<glyph unicode="&#xe148;" d="M700 1029v-307l64 -14q34 -7 64 -16.5t70 -31.5t67.5 -52t47.5 -80.5t20 -112.5q0 -139 -89 -224t-244 -96v-77h-100v78q-152 17 -237 104q-40 40 -52.5 93.5t-15.5 139.5h139q5 -77 48.5 -126.5t117.5 -64.5v335l-27 7q-46 14 -79 26.5t-72 36t-62.5 52t-40 72.5 t-16.5 99q0 92 44 159.5t109 101t144 40.5v78h100v-79q38 -4 72.5 -13.5t75.5 -31.5t71 -53.5t51.5 -84t24.5 -118.5h-159q-8 72 -35 109.5t-101 50.5zM600 755v274q-61 -8 -97.5 -37.5t-36.5 -102.5q0 -29 8 -51t16.5 -34t29.5 -22.5t [...]
+<glyph unicode="&#xe149;" d="M866 300l50 -147q-41 -25 -80.5 -36.5t-59 -13t-61.5 -1.5q-23 0 -128 33t-155 29q-39 -4 -82 -17t-66 -25l-24 -11l-55 145l16.5 11t15.5 10t13.5 9.5t14.5 12t14.5 14t17.5 18.5q48 55 54 126.5t-30 142.5h-221v100h166q-24 49 -44 104q-10 26 -14.5 55.5t-3 72.5 t25 90t68.5 87q97 88 263 88q129 0 230 -89t101 -208h-153q0 52 -34 89.5t-74 51.5t-76 14q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -11 2.5 -24.5t5.5 -24t9.5 -26.5t10.5 -25t14 -27.5t14 -25.5t15.5 -27t13.5 -24h242v-100 [...]
+<glyph unicode="&#xe150;" d="M300 0l298 300h-198v900h-200v-900h-198zM900 1200l298 -300h-198v-900h-200v900h-198z" />
+<glyph unicode="&#xe151;" d="M400 300h198l-298 -300l-298 300h198v900h200v-900zM1000 1200v-500h-100v100h-100v-100h-100v500h300zM901 1100h-100v-200h100v200zM700 500h300v-200h-99v-100h-100v100h99v100h-200v100zM800 100h200v-100h-300v200h100v-100z" />
+<glyph unicode="&#xe152;" d="M400 300h198l-298 -300l-298 300h198v900h200v-900zM1000 1200v-200h-99v-100h-100v100h99v100h-200v100h300zM800 800h200v-100h-300v200h100v-100zM700 500h300v-500h-100v100h-100v-100h-100v500zM801 200h100v200h-100v-200z" />
+<glyph unicode="&#xe153;" d="M300 0l298 300h-198v900h-200v-900h-198zM900 1100h-100v100h200v-500h-100v400zM1100 500v-500h-100v100h-200v400h300zM1001 400h-100v-200h100v200z" />
+<glyph unicode="&#xe154;" d="M300 0l298 300h-198v900h-200v-900h-198zM1100 1200v-500h-100v100h-200v400h300zM1001 1100h-100v-200h100v200zM900 400h-100v100h200v-500h-100v400z" />
+<glyph unicode="&#xe155;" d="M300 0l298 300h-198v900h-200v-900h-198zM900 1000h-200v200h200v-200zM1000 700h-300v200h300v-200zM1100 400h-400v200h400v-200zM1200 100h-500v200h500v-200z" />
+<glyph unicode="&#xe156;" d="M300 0l298 300h-198v900h-200v-900h-198zM1200 1000h-500v200h500v-200zM1100 700h-400v200h400v-200zM1000 400h-300v200h300v-200zM900 100h-200v200h200v-200z" />
+<glyph unicode="&#xe157;" d="M400 1100h300q162 0 281 -118.5t119 -281.5v-300q0 -165 -118.5 -282.5t-281.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5v300q0 165 117.5 282.5t282.5 117.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5 t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5z" />
+<glyph unicode="&#xe158;" d="M700 0h-300q-163 0 -281.5 117.5t-118.5 282.5v300q0 163 119 281.5t281 118.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5 t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5zM400 800v-500l333 250z" />
+<glyph unicode="&#xe159;" d="M0 400v300q0 163 117.5 281.5t282.5 118.5h300q163 0 281.5 -119t118.5 -281v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM900 300v500q0 41 -29.5 70.5t-70.5 29.5h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5 t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5zM800 700h-500l250 -333z" />
+<glyph unicode="&#xe160;" d="M1100 700v-300q0 -162 -118.5 -281t-281.5 -119h-300q-165 0 -282.5 118.5t-117.5 281.5v300q0 165 117.5 282.5t282.5 117.5h300q165 0 282.5 -117.5t117.5 -282.5zM900 300v500q0 41 -29.5 70.5t-70.5 29.5h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5 t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5zM550 733l-250 -333h500z" />
+<glyph unicode="&#xe161;" d="M500 1100h400q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-400v200h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-500v200zM700 550l-400 -350v200h-300v300h300v200z" />
+<glyph unicode="&#xe162;" d="M403 2l9 -1q13 0 26 16l538 630q15 19 6 36q-8 18 -32 16h-300q1 4 78 219.5t79 227.5q2 17 -6 27l-8 8h-9q-16 0 -25 -15q-4 -5 -98.5 -111.5t-228 -257t-209.5 -238.5q-17 -19 -7 -40q10 -19 32 -19h302q-155 -438 -160 -458q-5 -21 4 -32z" />
+<glyph unicode="&#xe163;" d="M800 200h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h500v185q-14 4 -114 7.5t-193 5.5l-93 2q-165 0 -282.5 -117.5t-117.5 -282.5v-300q0 -165 117.5 -282.5t282.5 -117.5h300q47 0 100 15v185zM900 200v200h-300v300h300v200l400 -350z" />
+<glyph unicode="&#xe164;" d="M1200 700l-149 149l-342 -353l-213 213l353 342l-149 149h500v-500zM1022 571l-122 -123v-148q0 -41 -29.5 -70.5t-70.5 -29.5h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h156l118 122l-74 78h-100q-165 0 -282.5 -117.5t-117.5 -282.5v-300 q0 -165 117.5 -282.5t282.5 -117.5h300q163 0 281.5 117.5t118.5 282.5v98z" />
+<glyph unicode="&#xe165;" d="M600 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM600 1014q-171 0 -292.5 -121.5t-121.5 -292.5t121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5zM600 794 q80 0 137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137t57 137t137 57z" />
+<glyph unicode="&#xe166;" d="M700 800v400h-300v-400h-300l445 -500l450 500h-295zM25 300h1048q11 0 19 -7.5t8 -17.5v-275h-1100v275q0 11 7 18t18 7zM1000 200h-100v-50h100v50z" />
+<glyph unicode="&#xe167;" d="M400 700v-300h300v300h295l-445 500l-450 -500h300zM25 300h1048q11 0 19 -7.5t8 -17.5v-275h-1100v275q0 11 7 18t18 7zM1000 200h-100v-50h100v50z" />
+<glyph unicode="&#xe168;" d="M405 400l596 596l-154 155l-442 -442l-150 151l-155 -155zM25 300h1048q11 0 19 -7.5t8 -17.5v-275h-1100v275q0 11 7 18t18 7zM1000 200h-100v-50h100v50z" />
+<glyph unicode="&#xe169;" d="M409 1103l-97 97l-212 -212l97 -98zM650 861l-149 149l-212 -212l149 -149l-238 -248h700v699zM25 300h1048q11 0 19 -7.5t8 -17.5v-275h-1100v275q0 11 7 18t18 7zM1000 200h-100v-50h100v50z" />
+<glyph unicode="&#xe170;" d="M539 950l-149 -149l212 -212l149 148l248 -237v700h-699zM297 709l-97 -97l212 -212l98 97zM25 300h1048q11 0 19 -7.5t8 -17.5v-275h-1100v275q0 11 7 18t18 7zM1000 200h-100v-50h100v50z" />
+<glyph unicode="&#xe171;" d="M1200 1199v-1079l-475 272l-310 -393v416h-392zM1166 1148l-672 -712v-226z" />
+<glyph unicode="&#xe172;" d="M1100 1000v-850q0 -21 -15 -35.5t-35 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1200h-100v-200h100v200z" />
+<glyph unicode="&#xe173;" d="M578 500h-378v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-218l-276 -275l-120 120zM700 1200h-100v-200h100v200zM1300 538l-475 -476l-244 244l123 123l120 -120l353 352z" />
+<glyph unicode="&#xe174;" d="M529 500h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-269l-103 -103l-170 170zM700 1200h-100v-200h100v200zM1167 6l-170 170l-170 -170l-127 127l170 170l-170 170l127 127l170 -170l170 170l127 -128 l-170 -169l170 -170z" />
+<glyph unicode="&#xe175;" d="M700 500h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-300h-400v-200zM700 1000h-100v200h100v-200zM1000 600h-200v-300h-200l300 -300l300 300h-200v300z" />
+<glyph unicode="&#xe176;" d="M602 500h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-402l-200 200zM700 1000h-100v200h100v-200zM1000 300h200l-300 300l-300 -300h200v-300h200v300z" />
+<glyph unicode="&#xe177;" d="M1200 900v150q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-150h1200zM0 800v-550q0 -21 14.5 -35.5t35.5 -14.5h1100q21 0 35.5 14.5t14.5 35.5v550h-1200zM100 500h400v-200h-400v200z" />
+<glyph unicode="&#xe178;" d="M500 1000h400v198l300 -298l-300 -298v198h-400v200zM100 800v200h100v-200h-100zM400 800h-100v200h100v-200zM700 300h-400v-198l-300 298l300 298v-198h400v-200zM800 500h100v-200h-100v200zM1000 500v-200h100v200h-100z" />
+<glyph unicode="&#xe179;" d="M1200 50v1106q0 31 -18 40.5t-44 -7.5l-276 -117q-25 -16 -43.5 -50.5t-18.5 -65.5v-359q0 -29 10.5 -55.5t25 -43t29 -28.5t25.5 -18l10 -5v-397q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5zM550 1200l50 -100v-400l-100 -203v-447q0 -21 -14.5 -35.5 t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447l-100 203v400l50 100l50 -100v-300h100v300l50 100l50 -100v-300h100v300z" />
+<glyph unicode="&#xe180;" d="M1100 106v888q0 22 25 34.5t50 13.5l25 2v56h-400v-56q75 0 87.5 -6t12.5 -44v-394h-500v394q0 38 12.5 44t87.5 6v56h-400v-56q4 0 11 -0.5t24 -3t30 -7t24 -15t11 -24.5v-888q0 -22 -25 -34.5t-50 -13.5l-25 -2v-56h400v56q-75 0 -87.5 6t-12.5 44v394h500v-394 q0 -38 -12.5 -44t-87.5 -6v-56h400v56q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5z" />
+<glyph unicode="&#xe181;" d="M675 1000l-100 100h-375l-100 -100h400l200 -200v-98l295 98h105v200h-425zM500 300v500q0 41 -29.5 70.5t-70.5 29.5h-300q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h300q41 0 70.5 29.5t29.5 70.5zM100 800h300v-200h-300v200zM700 565l400 133 v-163l-400 -133v163zM100 500h300v-200h-300v200zM805 300l295 98v-298h-425l-100 -100h-375l-100 100h400l200 200h105z" />
+<glyph unicode="&#xe182;" d="M179 1169l-162 -162q-1 -11 -0.5 -32.5t16 -90t46.5 -140t104 -177.5t175 -208q103 -103 207.5 -176t180 -103.5t137 -47t92.5 -16.5l31 1l163 162q16 17 13 40.5t-22 37.5l-192 136q-19 14 -45 12t-42 -19l-119 -118q-143 103 -267 227q-126 126 -227 268l118 118 q17 17 20 41.5t-11 44.5l-139 194q-14 19 -36.5 22t-40.5 -14z" />
+<glyph unicode="&#xe183;" d="M1200 712v200q-6 8 -19 20.5t-63 45t-112 57t-171 45t-235 20.5q-92 0 -175 -10.5t-141.5 -27t-108.5 -36.5t-81.5 -40t-53.5 -36.5t-31 -27.5l-9 -10v-200q0 -21 14.5 -33.5t34.5 -8.5l202 33q20 4 34.5 21t14.5 38v146q141 24 300 24t300 -24v-146q0 -21 14.5 -38 t34.5 -21l202 -33q20 -4 34.5 8.5t14.5 33.5zM800 650l365 -303q14 -14 24.5 -39.5t10.5 -45.5v-212q0 -21 -15 -35.5t-35 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v212q0 20 10.5 45.5t24.5 39.5l365 303v50q0 4 1 10.5t12 22.5t30 [...]
+<glyph unicode="&#xe184;" d="M175 200h950l-125 150v250l100 100v400h-100v-200h-100v200h-200v-200h-100v200h-200v-200h-100v200h-100v-400l100 -100v-250zM1200 100v-100h-1100v100h1100z" />
+<glyph unicode="&#xe185;" d="M600 1100h100q41 0 70.5 -29.5t29.5 -70.5v-1000h-300v1000q0 41 29.5 70.5t70.5 29.5zM1000 800h100q41 0 70.5 -29.5t29.5 -70.5v-700h-300v700q0 41 29.5 70.5t70.5 29.5zM400 0v400q0 41 -29.5 70.5t-70.5 29.5h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-400h300z" />
+<glyph unicode="&#xe186;" d="M1200 800v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212zM1000 900h-900v-700h900v700zM200 800v-300h200v-100h-200v-100h300v300h-200v100h200v100h-300zM800 800h-200v-500h200v100h100v300h-100 v100zM800 700v-300h-100v300h100z" />
+<glyph unicode="&#xe187;" d="M1200 800v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212zM1000 900h-900v-700h900v700zM400 600h-100v200h-100v-500h100v200h100v-200h100v500h-100v-200zM800 800h-200v-500h200v100h100v300h-100 v100zM800 700v-300h-100v300h100z" />
+<glyph unicode="&#xe188;" d="M1200 800v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212zM1000 900h-900v-700h900v700zM200 800v-500h300v100h-200v300h200v100h-300zM600 800v-500h300v100h-200v300h200v100h-300z" />
+<glyph unicode="&#xe189;" d="M1200 800v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212zM1000 900h-900v-700h900v700zM500 700l-300 -150l300 -150v300zM600 400l300 150l-300 150v-300z" />
+<glyph unicode="&#xe190;" d="M1200 800v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212zM1000 900h-900v-700h900v700zM900 800v-500h-700v500h700zM300 400h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130v-300zM800 700h-130 q-38 0 -66.5 -43t-28.5 -108t27 -107t68 -42h130v300z" />
+<glyph unicode="&#xe191;" d="M1200 800v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212zM1000 900h-900v-700h900v700zM200 800v-300h200v-100h-200v-100h300v300h-200v100h200v100h-300zM800 300h100v500h-200v-100h100v-400z M601 300h100v100h-100v-100z" />
+<glyph unicode="&#xe192;" d="M1200 800v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212zM1000 900h-900v-700h900v700zM300 700v100h-100v-500h300v400h-200zM800 300h100v500h-200v-100h100v-400zM401 400h-100v200h100v-200z M601 300h100v100h-100v-100z" />
+<glyph unicode="&#xe193;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM1000 900h-900v-700h900v700zM400 700h-200v100h300v-300h-99v-100h-100v100h99v200zM800 700h-100v100h200v-500h-100v400zM201 400h100v-100 h-100v100zM701 300h-100v100h100v-100z" />
+<glyph unicode="&#xe194;" d="M600 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM600 1014q-171 0 -292.5 -121.5t-121.5 -292.5t121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5zM800 700h-300 v-200h300v-100h-300l-100 100v200l100 100h300v-100z" />
+<glyph unicode="&#xe195;" d="M596 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM596 1014q-171 0 -292.5 -121.5t-121.5 -292.5t121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5zM800 700v-100 h-100v100h-200v-100h200v-100h-200v-100h-100v400h300zM800 400h-100v100h100v-100z" />
+<glyph unicode="&#xe197;" d="M800 300h128q120 0 205 86t85 208q0 120 -85 206.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5q0 -80 56.5 -137t135.5 -57h222v300h400v-300zM700 200h200l-300 -300 l-300 300h200v300h200v-300z" />
+<glyph unicode="&#xe198;" d="M600 714l403 -403q94 26 154.5 104t60.5 178q0 121 -85 207.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5q0 -80 56.5 -137t135.5 -57h8zM700 -100h-200v300h-200l300 300 l300 -300h-200v-300z" />
+<glyph unicode="&#xe199;" d="M700 200h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170l-270 -300h400v-155l-75 -45h350l-75 45v155z" />
+<glyph unicode="&#xe200;" d="M700 45v306q46 -30 100 -30q74 0 126.5 52.5t52.5 126.5q0 24 -9 55q50 32 79.5 83t29.5 112q0 90 -61.5 155.5t-150.5 71.5q-26 89 -99.5 145.5t-167.5 56.5q-116 0 -197.5 -81.5t-81.5 -197.5q0 -4 1 -12t1 -11q-14 2 -23 2q-74 0 -126.5 -52.5t-52.5 -126.5 q0 -53 28.5 -97t75.5 -65q-4 -16 -4 -38q0 -74 52.5 -126.5t126.5 -52.5q56 0 100 30v-306l-75 -45h350z" />
+<glyph unicode="&#x1f4bc;" d="M800 1000h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5h200q41 0 70.5 -29.5t29.5 -70.5v-100zM500 1000h200v100h-200v-100zM1200 400v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v200h1200z" />
+<glyph unicode="&#x1f4c5;" d="M1100 900v150q0 21 -14.5 35.5t-35.5 14.5h-150v100h-100v-100h-500v100h-100v-100h-150q-21 0 -35.5 -14.5t-14.5 -35.5v-150h1100zM0 800v-750q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v750h-1100zM100 600h100v-100h-100v100zM300 600h100v-100h-100v100z M500 600h100v-100h-100v100zM700 600h100v-100h-100v100zM900 600h100v-100h-100v100zM100 400h100v-100h-100v100zM300 400h100v-100h-100v100zM500 400h100v-100h-100v100zM700 400h100v-100h-100v100zM900 400h100v-100h-100 [...]
+<glyph unicode="&#x1f4cc;" d="M902 1185l283 -282q15 -15 15 -36t-15 -35q-14 -15 -35 -15t-35 15l-36 35l-279 -267v-300l-212 210l-208 -207l-380 -303l303 380l207 208l-210 212h300l267 279l-35 36q-15 14 -15 35t15 35q14 15 35 15t35 -15z" />
+<glyph unicode="&#x1f4ce;" d="M518 119l69 -60l517 511q67 67 95 157t11 183q-16 87 -67 154t-130 103q-69 33 -152 33q-107 0 -197 -55q-40 -24 -111 -95l-512 -512q-68 -68 -81 -163t35 -173q35 -57 94 -89t129 -32q63 0 119 28q33 16 65 40.5t52.5 45.5t59.5 64q40 44 57 61l394 394q35 35 47 84 t-3 96q-27 87 -117 104q-20 2 -29 2q-46 0 -79.5 -17t-67.5 -51l-388 -396l-7 -7l69 -67l377 373q20 22 39 38q23 23 50 23q38 0 53 -36q16 -39 -20 -75l-547 -547q-52 -52 -125 -52q-55 0 -100 33t-54 96q-5 35 2.5 66t31.5 63t4 [...]
+<glyph unicode="&#x1f4f7;" d="M1200 200v600q0 41 -29.5 70.5t-70.5 29.5h-150q-4 8 -11.5 21.5t-33 48t-53 61t-69 48t-83.5 21.5h-200q-41 0 -82 -20.5t-70 -50t-52 -59t-34 -50.5l-12 -20h-150q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5z M1000 700h-100v100h100v-100zM844 500q0 -100 -72 -172t-172 -72t-172 72t-72 172t72 172t172 72t172 -72t72 -172zM706 500q0 44 -31 75t-75 31t-75 -31t-31 -75t31 -75t75 -31t75 31t31 75z" />
+<glyph unicode="&#x1f512;" d="M900 800h100q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-900q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5h100v200q0 82 59 141t141 59h300q82 0 141 -59t59 -141v-200zM400 800h300v150q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-150z" />
+<glyph unicode="&#x1f514;" d="M1062 400h17q20 0 33.5 -14.5t13.5 -35.5q0 -20 -13 -40t-31 -27q-22 -9 -63 -23t-167.5 -37t-251.5 -23t-245.5 20.5t-178.5 41.5l-58 20q-18 7 -31 27.5t-13 40.5q0 21 13.5 35.5t33.5 14.5h17l118 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3 32t29 13h94 q20 0 29 -10.5t3 -29.5l-18 -37q83 -19 144 -82.5t76 -140.5l63 -327zM600 104q-54 0 -103 6q12 -49 40 -79.5t63 -30.5t63 30.5t39 79.5q-48 -6 -102 -6z" />
+<glyph unicode="&#x1f516;" d="M200 0l450 444l450 -443v1150q0 20 -14.5 35t-35.5 15h-800q-21 0 -35.5 -15t-14.5 -35v-1151z" />
+<glyph unicode="&#x1f525;" d="M400 755q2 -12 8 -41.5t8 -43t6 -39.5t3.5 -39.5t-1 -33.5t-6 -31.5t-13.5 -24t-21 -20.5t-31 -12q-38 -10 -67 13t-40.5 61.5t-15 81.5t10.5 75q-52 -46 -83.5 -101t-39 -107t-7.5 -85t5 -63q9 -56 44 -119.5t105 -108.5q31 -21 64 -16t62 23.5t57 49.5t48 61.5t35 60.5 q32 66 39 184.5t-13 157.5q79 -80 122 -164t26 -184q-5 -33 -20.5 -69.5t-37.5 -80.5q-10 -19 -14.5 -29t-12 -26t-9 -23.5t-3 -19t2.5 -15.5t11 -9.5t19.5 -5t30.5 2.5t42 8q57 20 91 34t87.5 44.5t87 64t65.5 88.5t47 122q38 [...]
+<glyph unicode="&#x1f527;" d="M948 778l251 126q13 -175 -151 -267q-123 -70 -253 -23l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5t15 37.5l600 599q-33 101 6 201.5t135 154.5q164 92 306 -9l-259 -138z" />
+</font>
+</defs></svg> 
\ No newline at end of file
diff --git a/src/docs/assets/fonts/glyphicons-halflings-regular.ttf b/src/docs/assets/fonts/glyphicons-halflings-regular.ttf
new file mode 100644
index 0000000..be784dc
Binary files /dev/null and b/src/docs/assets/fonts/glyphicons-halflings-regular.ttf differ
diff --git a/src/docs/assets/fonts/glyphicons-halflings-regular.woff b/src/docs/assets/fonts/glyphicons-halflings-regular.woff
new file mode 100644
index 0000000..2cc3e48
Binary files /dev/null and b/src/docs/assets/fonts/glyphicons-halflings-regular.woff differ
diff --git a/src/docs/assets/img/apple-touch-icon-144-precomposed.png b/src/docs/assets/img/apple-touch-icon-144-precomposed.png
new file mode 100644
index 0000000..622a865
Binary files /dev/null and b/src/docs/assets/img/apple-touch-icon-144-precomposed.png differ
diff --git a/src/docs/assets/img/favicon.png b/src/docs/assets/img/favicon.png
new file mode 100644
index 0000000..4e4560f
Binary files /dev/null and b/src/docs/assets/img/favicon.png differ
diff --git a/src/docs/assets/img/masthead-pattern.png b/src/docs/assets/img/masthead-pattern.png
new file mode 100644
index 0000000..75c46a1
Binary files /dev/null and b/src/docs/assets/img/masthead-pattern.png differ
diff --git a/src/docs/assets/js/bootstrap-tour.js b/src/docs/assets/js/bootstrap-tour.js
new file mode 100644
index 0000000..1874061
--- /dev/null
+++ b/src/docs/assets/js/bootstrap-tour.js
@@ -0,0 +1,802 @@
+/* ========================================================================
+ * bootstrap-tour - v0.10.1
+ * http://bootstraptour.com
+ * ========================================================================
+ * Copyright 2012-2013 Ulrich Sossou
+ *
+ * ========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================================
+ */
+
+(function($, window) {
+  var Tour, document;
+  document = window.document;
+  Tour = (function() {
+    function Tour(options) {
+      var storage;
+      try {
+        storage = window.localStorage;
+      } catch (_error) {
+        storage = false;
+      }
+      this._options = $.extend({
+        name: 'tour',
+        steps: [],
+        container: 'body',
+        autoscroll: true,
+        keyboard: true,
+        storage: storage,
+        debug: false,
+        backdrop: false,
+        backdropPadding: 0,
+        redirect: true,
+        orphan: false,
+        duration: false,
+        delay: false,
+        basePath: '',
+        template: '<div class="popover" role="tooltip"> <div class="arrow"></div> <h3 class="popover-title"></h3> <div class="popover-content"></div> <div class="popover-navigation"> <div class="btn-group"> <button class="btn btn-sm btn-default" data-role="prev">« Prev</button> <button class="btn btn-sm btn-default" data-role="next">Next »</button> <button class="btn btn-sm btn-default" data-role="pause-resume" data-pause-text="Pause" data-resume-text="Resume">Pause</button>  [...]
+        afterSetState: function(key, value) {},
+        afterGetState: function(key, value) {},
+        afterRemoveState: function(key) {},
+        onStart: function(tour) {},
+        onEnd: function(tour) {},
+        onShow: function(tour) {},
+        onShown: function(tour) {},
+        onHide: function(tour) {},
+        onHidden: function(tour) {},
+        onNext: function(tour) {},
+        onPrev: function(tour) {},
+        onPause: function(tour, duration) {},
+        onResume: function(tour, duration) {}
+      }, options);
+      this._force = false;
+      this._inited = false;
+      this.backdrop = {
+        overlay: null,
+        $element: null,
+        $background: null,
+        backgroundShown: false,
+        overlayElementShown: false
+      };
+      this;
+    }
+
+    Tour.prototype.addSteps = function(steps) {
+      var step, _i, _len;
+      for (_i = 0, _len = steps.length; _i < _len; _i++) {
+        step = steps[_i];
+        this.addStep(step);
+      }
+      return this;
+    };
+
+    Tour.prototype.addStep = function(step) {
+      this._options.steps.push(step);
+      return this;
+    };
+
+    Tour.prototype.getStep = function(i) {
+      if (this._options.steps[i] != null) {
+        return $.extend({
+          id: "step-" + i,
+          path: '',
+          placement: 'right',
+          title: '',
+          content: '<p></p>',
+          next: i === this._options.steps.length - 1 ? -1 : i + 1,
+          prev: i - 1,
+          animation: true,
+          container: this._options.container,
+          autoscroll: this._options.autoscroll,
+          backdrop: this._options.backdrop,
+          backdropPadding: this._options.backdropPadding,
+          redirect: this._options.redirect,
+          orphan: this._options.orphan,
+          duration: this._options.duration,
+          delay: this._options.delay,
+          template: this._options.template,
+          onShow: this._options.onShow,
+          onShown: this._options.onShown,
+          onHide: this._options.onHide,
+          onHidden: this._options.onHidden,
+          onNext: this._options.onNext,
+          onPrev: this._options.onPrev,
+          onPause: this._options.onPause,
+          onResume: this._options.onResume
+        }, this._options.steps[i]);
+      }
+    };
+
+    Tour.prototype.init = function(force) {
+      this._force = force;
+      if (this.ended()) {
+        this._debug('Tour ended, init prevented.');
+        return this;
+      }
+      this.setCurrentStep();
+      this._initMouseNavigation();
+      this._initKeyboardNavigation();
+      this._onResize((function(_this) {
+        return function() {
+          return _this.showStep(_this._current);
+        };
+      })(this));
+      if (this._current !== null) {
+        this.showStep(this._current);
+      }
+      this._inited = true;
+      return this;
+    };
+
+    Tour.prototype.start = function(force) {
+      var promise;
+      if (force == null) {
+        force = false;
+      }
+      if (!this._inited) {
+        this.init(force);
+      }
+      if (this._current === null) {
+        promise = this._makePromise(this._options.onStart != null ? this._options.onStart(this) : void 0);
+        this._callOnPromiseDone(promise, this.showStep, 0);
+      }
+      return this;
+    };
+
+    Tour.prototype.next = function() {
+      var promise;
+      promise = this.hideStep(this._current);
+      return this._callOnPromiseDone(promise, this._showNextStep);
+    };
+
+    Tour.prototype.prev = function() {
+      var promise;
+      promise = this.hideStep(this._current);
+      return this._callOnPromiseDone(promise, this._showPrevStep);
+    };
+
+    Tour.prototype.goTo = function(i) {
+      var promise;
+      promise = this.hideStep(this._current);
+      return this._callOnPromiseDone(promise, this.showStep, i);
+    };
+
+    Tour.prototype.end = function() {
+      var endHelper, promise;
+      endHelper = (function(_this) {
+        return function(e) {
+          $(document).off("click.tour-" + _this._options.name);
+          $(document).off("keyup.tour-" + _this._options.name);
+          $(window).off("resize.tour-" + _this._options.name);
+          _this._setState('end', 'yes');
+          _this._inited = false;
+          _this._force = false;
+          _this._clearTimer();
+          if (_this._options.onEnd != null) {
+            return _this._options.onEnd(_this);
+          }
+        };
+      })(this);
+      promise = this.hideStep(this._current);
+      return this._callOnPromiseDone(promise, endHelper);
+    };
+
+    Tour.prototype.ended = function() {
+      return !this._force && !!this._getState('end');
+    };
+
+    Tour.prototype.restart = function() {
+      this._removeState('current_step');
+      this._removeState('end');
+      return this.start();
+    };
+
+    Tour.prototype.pause = function() {
+      var step;
+      step = this.getStep(this._current);
+      if (!(step && step.duration)) {
+        return this;
+      }
+      this._paused = true;
+      this._duration -= new Date().getTime() - this._start;
+      window.clearTimeout(this._timer);
+      this._debug("Paused/Stopped step " + (this._current + 1) + " timer (" + this._duration + " remaining).");
+      if (step.onPause != null) {
+        return step.onPause(this, this._duration);
+      }
+    };
+
+    Tour.prototype.resume = function() {
+      var step;
+      step = this.getStep(this._current);
+      if (!(step && step.duration)) {
+        return this;
+      }
+      this._paused = false;
+      this._start = new Date().getTime();
+      this._duration = this._duration || step.duration;
+      this._timer = window.setTimeout((function(_this) {
+        return function() {
+          if (_this._isLast()) {
+            return _this.next();
+          } else {
+            return _this.end();
+          }
+        };
+      })(this), this._duration);
+      this._debug("Started step " + (this._current + 1) + " timer with duration " + this._duration);
+      if ((step.onResume != null) && this._duration !== step.duration) {
+        return step.onResume(this, this._duration);
+      }
+    };
+
+    Tour.prototype.hideStep = function(i) {
+      var hideStepHelper, promise, step;
+      step = this.getStep(i);
+      if (!step) {
+        return;
+      }
+      this._clearTimer();
+      promise = this._makePromise(step.onHide != null ? step.onHide(this, i) : void 0);
+      hideStepHelper = (function(_this) {
+        return function(e) {
+          var $element;
+          $element = $(step.element);
+          if (!($element.data('bs.popover') || $element.data('popover'))) {
+            $element = $('body');
+          }
+          $element.popover('destroy').removeClass("tour-" + _this._options.name + "-element tour-" + _this._options.name + "-" + i + "-element");
+          if (step.reflex) {
+            $element.removeClass('tour-step-element-reflex').off("" + (_this._reflexEvent(step.reflex)) + ".tour-" + _this._options.name);
+          }
+          if (step.backdrop) {
+            _this._hideBackdrop();
+          }
+          if (step.onHidden != null) {
+            return step.onHidden(_this);
+          }
+        };
+      })(this);
+      this._callOnPromiseDone(promise, hideStepHelper);
+      return promise;
+    };
+
+    Tour.prototype.showStep = function(i) {
+      var promise, showStepHelper, skipToPrevious, step;
+      if (this.ended()) {
+        this._debug('Tour ended, showStep prevented.');
+        return this;
+      }
+      step = this.getStep(i);
+      if (!step) {
+        return;
+      }
+      skipToPrevious = i < this._current;
+      promise = this._makePromise(step.onShow != null ? step.onShow(this, i) : void 0);
+      showStepHelper = (function(_this) {
+        return function(e) {
+          var current_path, path, showPopoverAndOverlay;
+          _this.setCurrentStep(i);
+          path = (function() {
+            switch ({}.toString.call(step.path)) {
+              case '[object Function]':
+                return step.path();
+              case '[object String]':
+                return this._options.basePath + step.path;
+              default:
+                return step.path;
+            }
+          }).call(_this);
+          current_path = [document.location.pathname, document.location.hash].join('');
+          if (_this._isRedirect(path, current_path)) {
+            _this._redirect(step, path);
+            return;
+          }
+          if (_this._isOrphan(step)) {
+            if (!step.orphan) {
+              _this._debug("Skip the orphan step " + (_this._current + 1) + ".\nOrphan option is false and the element does not exist or is hidden.");
+              if (skipToPrevious) {
+                _this._showPrevStep();
+              } else {
+                _this._showNextStep();
+              }
+              return;
+            }
+            _this._debug("Show the orphan step " + (_this._current + 1) + ". Orphans option is true.");
+          }
+          if (step.backdrop) {
+            _this._showBackdrop(!_this._isOrphan(step) ? step.element : void 0);
+          }
+          showPopoverAndOverlay = function() {
+            if (_this.getCurrentStep() !== i) {
+              return;
+            }
+            if ((step.element != null) && step.backdrop) {
+              _this._showOverlayElement(step);
+            }
+            _this._showPopover(step, i);
+            if (step.onShown != null) {
+              step.onShown(_this);
+            }
+            return _this._debug("Step " + (_this._current + 1) + " of " + _this._options.steps.length);
+          };
+          if (step.autoscroll) {
+            _this._scrollIntoView(step.element, showPopoverAndOverlay);
+          } else {
+            showPopoverAndOverlay();
+          }
+          if (step.duration) {
+            return _this.resume();
+          }
+        };
+      })(this);
+      if (step.delay) {
+        this._debug("Wait " + step.delay + " milliseconds to show the step " + (this._current + 1));
+        window.setTimeout((function(_this) {
+          return function() {
+            return _this._callOnPromiseDone(promise, showStepHelper);
+          };
+        })(this), step.delay);
+      } else {
+        this._callOnPromiseDone(promise, showStepHelper);
+      }
+      return promise;
+    };
+
+    Tour.prototype.getCurrentStep = function() {
+      return this._current;
+    };
+
+    Tour.prototype.setCurrentStep = function(value) {
+      if (value != null) {
+        this._current = value;
+        this._setState('current_step', value);
+      } else {
+        this._current = this._getState('current_step');
+        this._current = this._current === null ? null : parseInt(this._current, 10);
+      }
+      return this;
+    };
+
+    Tour.prototype._setState = function(key, value) {
+      var e, keyName;
+      if (this._options.storage) {
+        keyName = "" + this._options.name + "_" + key;
+        try {
+          this._options.storage.setItem(keyName, value);
+        } catch (_error) {
+          e = _error;
+          if (e.code === DOMException.QUOTA_EXCEEDED_ERR) {
+            this._debug('LocalStorage quota exceeded. State storage failed.');
+          }
+        }
+        return this._options.afterSetState(keyName, value);
+      } else {
+        if (this._state == null) {
+          this._state = {};
+        }
+        return this._state[key] = value;
+      }
+    };
+
+    Tour.prototype._removeState = function(key) {
+      var keyName;
+      if (this._options.storage) {
+        keyName = "" + this._options.name + "_" + key;
+        this._options.storage.removeItem(keyName);
+        return this._options.afterRemoveState(keyName);
+      } else {
+        if (this._state != null) {
+          return delete this._state[key];
+        }
+      }
+    };
+
+    Tour.prototype._getState = function(key) {
+      var keyName, value;
+      if (this._options.storage) {
+        keyName = "" + this._options.name + "_" + key;
+        value = this._options.storage.getItem(keyName);
+      } else {
+        if (this._state != null) {
+          value = this._state[key];
+        }
+      }
+      if (value === void 0 || value === 'null') {
+        value = null;
+      }
+      this._options.afterGetState(key, value);
+      return value;
+    };
+
+    Tour.prototype._showNextStep = function() {
+      var promise, showNextStepHelper, step;
+      step = this.getStep(this._current);
+      showNextStepHelper = (function(_this) {
+        return function(e) {
+          return _this.showStep(step.next);
+        };
+      })(this);
+      promise = this._makePromise(step.onNext != null ? step.onNext(this) : void 0);
+      return this._callOnPromiseDone(promise, showNextStepHelper);
+    };
+
+    Tour.prototype._showPrevStep = function() {
+      var promise, showPrevStepHelper, step;
+      step = this.getStep(this._current);
+      showPrevStepHelper = (function(_this) {
+        return function(e) {
+          return _this.showStep(step.prev);
+        };
+      })(this);
+      promise = this._makePromise(step.onPrev != null ? step.onPrev(this) : void 0);
+      return this._callOnPromiseDone(promise, showPrevStepHelper);
+    };
+
+    Tour.prototype._debug = function(text) {
+      if (this._options.debug) {
+        return window.console.log("Bootstrap Tour '" + this._options.name + "' | " + text);
+      }
+    };
+
+    Tour.prototype._isRedirect = function(path, currentPath) {
+      return (path != null) && path !== '' && (({}.toString.call(path) === '[object RegExp]' && !path.test(currentPath)) || ({}.toString.call(path) === '[object String]' && path.replace(/\?.*$/, '').replace(/\/?$/, '') !== currentPath.replace(/\/?$/, '')));
+    };
+
+    Tour.prototype._redirect = function(step, path) {
+      if ($.isFunction(step.redirect)) {
+        return step.redirect.call(this, path);
+      } else if (step.redirect === true) {
+        this._debug("Redirect to " + path);
+        return document.location.href = path;
+      }
+    };
+
+    Tour.prototype._isOrphan = function(step) {
+      return (step.element == null) || !$(step.element).length || $(step.element).is(':hidden') && ($(step.element)[0].namespaceURI !== 'http://www.w3.org/2000/svg');
+    };
+
+    Tour.prototype._isLast = function() {
+      return this._current < this._options.steps.length - 1;
+    };
+
+    Tour.prototype._showPopover = function(step, i) {
+      var $element, $tip, isOrphan, options;
+      $(".tour-" + this._options.name).remove();
+      options = $.extend({}, this._options);
+      isOrphan = this._isOrphan(step);
+      step.template = this._template(step, i);
+      if (isOrphan) {
+        step.element = 'body';
+        step.placement = 'top';
+      }
+      $element = $(step.element);
+      $element.addClass("tour-" + this._options.name + "-element tour-" + this._options.name + "-" + i + "-element");
+      if (step.options) {
+        $.extend(options, step.options);
+      }
+      if (step.reflex && !isOrphan) {
+        $element.addClass('tour-step-element-reflex');
+        $element.off("" + (this._reflexEvent(step.reflex)) + ".tour-" + this._options.name);
+        $element.on("" + (this._reflexEvent(step.reflex)) + ".tour-" + this._options.name, (function(_this) {
+          return function() {
+            if (_this._isLast()) {
+              return _this.next();
+            } else {
+              return _this.end();
+            }
+          };
+        })(this));
+      }
+      $element.popover({
+        placement: step.placement,
+        trigger: 'manual',
+        title: step.title,
+        content: step.content,
+        html: true,
+        animation: step.animation,
+        container: step.container,
+        template: step.template,
+        selector: step.element
+      }).popover('show');
+      $tip = $element.data('bs.popover') ? $element.data('bs.popover').tip() : $element.data('popover').tip();
+      $tip.attr('id', step.id);
+      this._reposition($tip, step);
+      if (isOrphan) {
+        return this._center($tip);
+      }
+    };
+
+    Tour.prototype._template = function(step, i) {
+      var $navigation, $next, $prev, $resume, $template;
+      $template = $.isFunction(step.template) ? $(step.template(i, step)) : $(step.template);
+      $navigation = $template.find('.popover-navigation');
+      $prev = $navigation.find('[data-role="prev"]');
+      $next = $navigation.find('[data-role="next"]');
+      $resume = $navigation.find('[data-role="pause-resume"]');
+      if (this._isOrphan(step)) {
+        $template.addClass('orphan');
+      }
+      $template.addClass("tour-" + this._options.name + " tour-" + this._options.name + "-" + i);
+      if (step.prev < 0) {
+        $prev.addClass('disabled');
+      }
+      if (step.next < 0) {
+        $next.addClass('disabled');
+      }
+      if (!step.duration) {
+        $resume.remove();
+      }
+      return $template.clone().wrap('<div>').parent().html();
+    };
+
+    Tour.prototype._reflexEvent = function(reflex) {
+      if ({}.toString.call(reflex) === '[object Boolean]') {
+        return 'click';
+      } else {
+        return reflex;
+      }
+    };
+
+    Tour.prototype._reposition = function($tip, step) {
+      var offsetBottom, offsetHeight, offsetRight, offsetWidth, originalLeft, originalTop, tipOffset;
+      offsetWidth = $tip[0].offsetWidth;
+      offsetHeight = $tip[0].offsetHeight;
+      tipOffset = $tip.offset();
+      originalLeft = tipOffset.left;
+      originalTop = tipOffset.top;
+      offsetBottom = $(document).outerHeight() - tipOffset.top - $tip.outerHeight();
+      if (offsetBottom < 0) {
+        tipOffset.top = tipOffset.top + offsetBottom;
+      }
+      offsetRight = $('html').outerWidth() - tipOffset.left - $tip.outerWidth();
+      if (offsetRight < 0) {
+        tipOffset.left = tipOffset.left + offsetRight;
+      }
+      if (tipOffset.top < 0) {
+        tipOffset.top = 0;
+      }
+      if (tipOffset.left < 0) {
+        tipOffset.left = 0;
+      }
+      $tip.offset(tipOffset);
+      if (step.placement === 'bottom' || step.placement === 'top') {
+        if (originalLeft !== tipOffset.left) {
+          return this._replaceArrow($tip, (tipOffset.left - originalLeft) * 2, offsetWidth, 'left');
+        }
+      } else {
+        if (originalTop !== tipOffset.top) {
+          return this._replaceArrow($tip, (tipOffset.top - originalTop) * 2, offsetHeight, 'top');
+        }
+      }
+    };
+
+    Tour.prototype._center = function($tip) {
+      return $tip.css('top', $(window).outerHeight() / 2 - $tip.outerHeight() / 2);
+    };
+
+    Tour.prototype._replaceArrow = function($tip, delta, dimension, position) {
+      return $tip.find('.arrow').css(position, delta ? 50 * (1 - delta / dimension) + '%' : '');
+    };
+
+    Tour.prototype._scrollIntoView = function(element, callback) {
+      var $element, $window, counter, offsetTop, scrollTop, windowHeight;
+      $element = $(element);
+      if (!$element.length) {
+        return callback();
+      }
+      $window = $(window);
+      offsetTop = $element.offset().top;
+      windowHeight = $window.height();
+      scrollTop = Math.max(0, offsetTop - (windowHeight / 2));
+      this._debug("Scroll into view. ScrollTop: " + scrollTop + ". Element offset: " + offsetTop + ". Window height: " + windowHeight + ".");
+      counter = 0;
+      return $('body, html').stop(true, true).animate({
+        scrollTop: Math.ceil(scrollTop)
+      }, (function(_this) {
+        return function() {
+          if (++counter === 2) {
+            callback();
+            return _this._debug("Scroll into view.\nAnimation end element offset: " + ($element.offset().top) + ".\nWindow height: " + ($window.height()) + ".");
+          }
+        };
+      })(this));
+    };
+
+    Tour.prototype._onResize = function(callback, timeout) {
+      return $(window).on("resize.tour-" + this._options.name, function() {
+        clearTimeout(timeout);
+        return timeout = setTimeout(callback, 100);
+      });
+    };
+
+    Tour.prototype._initMouseNavigation = function() {
+      var _this;
+      _this = this;
+      return $(document).off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='prev']").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='next']").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='end']").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='pause-resume']").on("click.tour-" + this._options.name, ".pop [...]
+        return function(e) {
+          e.preventDefault();
+          return _this.next();
+        };
+      })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='prev']", (function(_this) {
+        return function(e) {
+          e.preventDefault();
+          return _this.prev();
+        };
+      })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='end']", (function(_this) {
+        return function(e) {
+          e.preventDefault();
+          return _this.end();
+        };
+      })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='pause-resume']", function(e) {
+        var $this;
+        e.preventDefault();
+        $this = $(this);
+        $this.text(_this._paused ? $this.data('pause-text') : $this.data('resume-text'));
+        if (_this._paused) {
+          return _this.resume();
+        } else {
+          return _this.pause();
+        }
+      });
+    };
+
+    Tour.prototype._initKeyboardNavigation = function() {
+      if (!this._options.keyboard) {
+        return;
+      }
+      return $(document).on("keyup.tour-" + this._options.name, (function(_this) {
+        return function(e) {
+          if (!e.which) {
+            return;
+          }
+          switch (e.which) {
+            case 39:
+              e.preventDefault();
+              if (_this._isLast()) {
+                return _this.next();
+              } else {
+                return _this.end();
+              }
+              break;
+            case 37:
+              e.preventDefault();
+              if (_this._current > 0) {
+                return _this.prev();
+              }
+              break;
+            case 27:
+              e.preventDefault();
+              return _this.end();
+          }
+        };
+      })(this));
+    };
+
+    Tour.prototype._makePromise = function(result) {
+      if (result && $.isFunction(result.then)) {
+        return result;
+      } else {
+        return null;
+      }
+    };
+
+    Tour.prototype._callOnPromiseDone = function(promise, cb, arg) {
+      if (promise) {
+        return promise.then((function(_this) {
+          return function(e) {
+            return cb.call(_this, arg);
+          };
+        })(this));
+      } else {
+        return cb.call(this, arg);
+      }
+    };
+
+    Tour.prototype._showBackdrop = function(element) {
+      if (this.backdrop.backgroundShown) {
+        return;
+      }
+      this.backdrop = $('<div>', {
+        "class": 'tour-backdrop'
+      });
+      this.backdrop.backgroundShown = true;
+      return $('body').append(this.backdrop);
+    };
+
+    Tour.prototype._hideBackdrop = function() {
+      this._hideOverlayElement();
+      return this._hideBackground();
+    };
+
+    Tour.prototype._hideBackground = function() {
+      if (this.backdrop) {
+        this.backdrop.remove();
+        this.backdrop.overlay = null;
+        return this.backdrop.backgroundShown = false;
+      }
+    };
+
+    Tour.prototype._showOverlayElement = function(step) {
+      var $element, elementData;
+      $element = $(step.element);
+      if (!$element || $element.length === 0 || this.backdrop.overlayElementShown) {
+        return;
+      }
+      this.backdrop.overlayElementShown = true;
+      this.backdrop.$element = $element.addClass('tour-step-backdrop');
+      this.backdrop.$background = $('<div>', {
+        "class": 'tour-step-background'
+      });
+      elementData = {
+        width: $element.innerWidth(),
+        height: $element.innerHeight(),
+        offset: $element.offset()
+      };
+      this.backdrop.$background.appendTo('body');
+      if (step.backdropPadding) {
+        elementData = this._applyBackdropPadding(step.backdropPadding, elementData);
+      }
+      return this.backdrop.$background.width(elementData.width).height(elementData.height).offset(elementData.offset);
+    };
+
+    Tour.prototype._hideOverlayElement = function() {
+      if (!this.backdrop.overlayElementShown) {
+        return;
+      }
+      this.backdrop.$element.removeClass('tour-step-backdrop');
+      this.backdrop.$background.remove();
+      this.backdrop.$element = null;
+      this.backdrop.$background = null;
+      return this.backdrop.overlayElementShown = false;
+    };
+
+    Tour.prototype._applyBackdropPadding = function(padding, data) {
+      if (typeof padding === 'object') {
+        if (padding.top == null) {
+          padding.top = 0;
+        }
+        if (padding.right == null) {
+          padding.right = 0;
+        }
+        if (padding.bottom == null) {
+          padding.bottom = 0;
+        }
+        if (padding.left == null) {
+          padding.left = 0;
+        }
+        data.offset.top = data.offset.top - padding.top;
+        data.offset.left = data.offset.left - padding.left;
+        data.width = data.width + padding.left + padding.right;
+        data.height = data.height + padding.top + padding.bottom;
+      } else {
+        data.offset.top = data.offset.top - padding;
+        data.offset.left = data.offset.left - padding;
+        data.width = data.width + (padding * 2);
+        data.height = data.height + (padding * 2);
+      }
+      return data;
+    };
+
+    Tour.prototype._clearTimer = function() {
+      window.clearTimeout(this._timer);
+      this._timer = null;
+      return this._duration = null;
+    };
+
+    return Tour;
+
+  })();
+  return window.Tour = Tour;
+})(jQuery, window);
diff --git a/src/docs/assets/vendor/bootstrap.min.css b/src/docs/assets/vendor/bootstrap.min.css
new file mode 100644
index 0000000..a553c4f
--- /dev/null
+++ b/src/docs/assets/vendor/bootstrap.min.css
@@ -0,0 +1,9 @@
+/*!
+ * Bootstrap v3.0.0
+ *
+ * Copyright 2013 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world by @mdo and @fat.
+ *//*! normalize.css v2.1.0 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden]{display:none}html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{margin:.67em 0;font-size:2em}abbr[title]{border-bottom:1px dotted}b [...]
\ No newline at end of file
diff --git a/src/docs/assets/vendor/jquery.smoothscroll.js b/src/docs/assets/vendor/jquery.smoothscroll.js
new file mode 100644
index 0000000..9c71e50
--- /dev/null
+++ b/src/docs/assets/vendor/jquery.smoothscroll.js
@@ -0,0 +1,47 @@
+/*! http://mths.be/smoothscroll v1.5.2 by @mathias */
+;
+(function(document, $) {
+
+  var $scrollElement = (function() {
+    // Find out what to scroll (html or body)
+    var $html = $(document.documentElement),
+      $body = $(document.body),
+      bodyScrollTop;
+    if ($html.scrollTop()) {
+      return $html;
+    } else {
+      bodyScrollTop = $body.scrollTop();
+      // If scrolling the body doesn’t do anything
+      if ($body.scrollTop(bodyScrollTop + 1).scrollTop() == bodyScrollTop) {
+        return $html;
+      } else {
+        // We actually scrolled, so undo it
+        return $body.scrollTop(bodyScrollTop);
+      }
+    }
+  }());
+
+  $.fn.smoothScroll = function(speed) {
+    speed = ~~speed || 400;
+    // Look for links to anchors (on any page)
+    return this.find('a[href*="#"]').click(function(event) {
+      var hash = this.hash,
+        $hash = $(hash); // The in-document element the link points to
+      // If it’s a link to an anchor in the same document
+      if (location.pathname.replace(/^\//, '') === this.pathname.replace(/^\//, '') && location.hostname === this.hostname) {
+        // If the anchor actually exists…
+        if ($hash.length) {
+          // …don’t jump to the link right away…
+          event.preventDefault();
+          // …and smoothly scroll to it
+          $scrollElement.stop().animate({
+            'scrollTop': $hash.offset().top
+          }, speed, function() {
+            location.hash = hash;
+          });
+        }
+      }
+    }).end();
+  };
+
+}(document, jQuery));
\ No newline at end of file
diff --git a/src/docs/assets/vendor/pygments-manni.css b/src/docs/assets/vendor/pygments-manni.css
new file mode 100644
index 0000000..1264b87
--- /dev/null
+++ b/src/docs/assets/vendor/pygments-manni.css
@@ -0,0 +1,66 @@
+.hll { background-color: #ffffcc }
+ /*{ background: #f0f3f3; }*/
+.c { color: #999; } /* Comment */
+.err { color: #AA0000; background-color: #FFAAAA } /* Error */
+.k { color: #006699; } /* Keyword */
+.o { color: #555555 } /* Operator */
+.cm { color: #0099FF; font-style: italic } /* Comment.Multiline */
+.cp { color: #009999 } /* Comment.Preproc */
+.c1 { color: #999; } /* Comment.Single */
+.cs { color: #999; } /* Comment.Special */
+.gd { background-color: #FFCCCC; border: 1px solid #CC0000 } /* Generic.Deleted */
+.ge { font-style: italic } /* Generic.Emph */
+.gr { color: #FF0000 } /* Generic.Error */
+.gh { color: #003300; } /* Generic.Heading */
+.gi { background-color: #CCFFCC; border: 1px solid #00CC00 } /* Generic.Inserted */
+.go { color: #AAAAAA } /* Generic.Output */
+.gp { color: #000099; } /* Generic.Prompt */
+.gs { } /* Generic.Strong */
+.gu { color: #003300; } /* Generic.Subheading */
+.gt { color: #99CC66 } /* Generic.Traceback */
+.kc { color: #006699; } /* Keyword.Constant */
+.kd { color: #006699; } /* Keyword.Declaration */
+.kn { color: #006699; } /* Keyword.Namespace */
+.kp { color: #006699 } /* Keyword.Pseudo */
+.kr { color: #006699; } /* Keyword.Reserved */
+.kt { color: #007788; } /* Keyword.Type */
+.m { color: #FF6600 } /* Literal.Number */
+.s { color: #d44950 } /* Literal.String */
+.na { color: #4f9fcf } /* Name.Attribute */
+.nb { color: #336666 } /* Name.Builtin */
+.nc { color: #00AA88; } /* Name.Class */
+.no { color: #336600 } /* Name.Constant */
+.nd { color: #9999FF } /* Name.Decorator */
+.ni { color: #999999; } /* Name.Entity */
+.ne { color: #CC0000; } /* Name.Exception */
+.nf { color: #CC00FF } /* Name.Function */
+.nl { color: #9999FF } /* Name.Label */
+.nn { color: #00CCFF; } /* Name.Namespace */
+.nt { color: #2f6f9f; } /* Name.Tag */
+.nv { color: #003333 } /* Name.Variable */
+.ow { color: #000000; } /* Operator.Word */
+.w { color: #bbbbbb } /* Text.Whitespace */
+.mf { color: #FF6600 } /* Literal.Number.Float */
+.mh { color: #FF6600 } /* Literal.Number.Hex */
+.mi { color: #FF6600 } /* Literal.Number.Integer */
+.mo { color: #FF6600 } /* Literal.Number.Oct */
+.sb { color: #CC3300 } /* Literal.String.Backtick */
+.sc { color: #CC3300 } /* Literal.String.Char */
+.sd { color: #CC3300; font-style: italic } /* Literal.String.Doc */
+.s2 { color: #CC3300 } /* Literal.String.Double */
+.se { color: #CC3300; } /* Literal.String.Escape */
+.sh { color: #CC3300 } /* Literal.String.Heredoc */
+.si { color: #AA0000 } /* Literal.String.Interpol */
+.sx { color: #CC3300 } /* Literal.String.Other */
+.sr { color: #33AAAA } /* Literal.String.Regex */
+.s1 { color: #CC3300 } /* Literal.String.Single */
+.ss { color: #FFCC33 } /* Literal.String.Symbol */
+.bp { color: #336666 } /* Name.Builtin.Pseudo */
+.vc { color: #003333 } /* Name.Variable.Class */
+.vg { color: #003333 } /* Name.Variable.Global */
+.vi { color: #003333 } /* Name.Variable.Instance */
+.il { color: #FF6600 } /* Literal.Number.Integer.Long */
+
+.css .o,
+.css .o + .nt,
+.css .nt + .nt { color: #999; }
diff --git a/src/docs/index.html b/src/docs/index.html
new file mode 100644
index 0000000..18ad4ed
--- /dev/null
+++ b/src/docs/index.html
@@ -0,0 +1,107 @@
+---
+layout: default
+title: Bootstrap Tour
+slug: home
+---
+
+<header id="home">
+  <div class="jumbotron masthead">
+    <h1>Bootstrap Tour</h1>
+    <p class="lead">
+      The easiest way to show people how to use your website.
+      <br><small>Not using Bootstrap? It works anyway!</small>
+    </p>
+    <p>
+      <button type="button" id="demo" class="btn btn-default btn-lg" data-demo>
+        <span class="glyphicon glyphicon-play"></span>
+        Start the demo
+      </button>
+    </p>
+    <ul class="social">
+      <li>
+        <iframe class="github-btn" src="http://ghbtns.com/github-btn.html?user=sorich87&repo=bootstrap-tour&type=watch&count=true" width="100" height="20" title="Star on GitHub"></iframe>
+      </li>
+      <li>
+        <iframe class="github-btn" src="http://ghbtns.com/github-btn.html?user=sorich87&repo=bootstrap-tour&type=fork&count=true" width="102" height="20" title="Fork on GitHub"></iframe>
+      </li>
+      <li class="tweet-btn">
+        <a href="https://twitter.com/share" class="twitter-share-button" data-url="http://bootstraptour.com/" data-count="horizontal">Tweet</a>
+      </li>
+    </ul>
+  </div>
+</header>
+<section id="usage">
+  <div class="container">
+    <div class="page-header">
+      <h2>The How-to <small>It's simple!</small></h2>
+    </div>
+    <h3>Add the dependencies</h3>
+    <p>If you are using Bootstrap, include <code>bootstrap-tour.min.css</code> and <code>bootstrap-tour.min.js</code>:</p>
+{% highlight html %}
+<link href="bootstrap.min.css" rel="stylesheet">
+<link href="bootstrap-tour.min.css" rel="stylesheet">
+...
+<script src="jquery.min.js"></script>
+<script src="bootstrap.min.js"></script>
+<script src="bootstrap-tour.min.js"></script>
+{% endhighlight %}
+    <p>Otherwise, just include <code>bootstrap-tour-standalone.min.css</code> and <code>bootstrap-tour-standalone.min.js</code>:</p>
+{% highlight html %}
+<link href="bootstrap-tour-standalone.min.css" rel="stylesheet">
+...
+<script src="jquery.min.js"></script>
+<script src="bootstrap-tour-standalone.min.js"></script>
+{% endhighlight %}
+    <h3>Setup your tour:</h3>
+{% highlight javascript %}
+// Instance the tour
+var tour = new Tour({
+  steps: [
+  {
+    element: "#my-element",
+    title: "Title of my step",
+    content: "Content of my step"
+  },
+  {
+    element: "#my-other-element",
+    title: "Title of my step",
+    content: "Content of my step"
+  }
+]});
+
+// Initialize the tour
+tour.init();
+
+// Start the tour
+tour.start();
+{% endhighlight %}
+    <p>Do you want to do more? <a href="api">Read the full documentation.</a></p>
+  </div>
+</section>
+<section id="contributing">
+  <div class="container">
+    <div class="page-header">
+      <h2>The Team <small>It's handmade!</small></h2>
+    </div>
+    <div class="row">
+      <div class="col-sm-4">
+        <a href="https://github.com/sorich87"><img src="" class="gravatar img-circle" data-email="sorich87 at gmail.com"> Ulrich Sossou</a>
+      </div>
+      <div class="col-sm-4">
+        <a href="https://github.com/LostCrew"><img src="" class="gravatar img-circle" data-email="emanuele at lostcrew.it"> Emanuele Marchi</a>
+      </div>
+      <div class="col-sm-4">
+        <a href="https://github.com/emmenko"><img src="" class="gravatar img-circle" data-email="emmenko at gmail.com"> Nicola Molinari</a>
+      </div>
+    </div>
+  </div>
+</section>
+<section id="license">
+  <div class="container">
+    <div class="page-header">
+      <h2>The License <small>It's free!</small></h2>
+    </div>
+    <p>Code licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0" target="_blank">Apache License v2.0</a>.<br>
+    Documentation licensed under <a href="http://creativecommons.org/licenses/by/3.0/">CC BY 3.0</a>.</p>
+  </div>
+</section>
diff --git a/src/less/bootstrap-tour-standalone.less b/src/less/bootstrap-tour-standalone.less
new file mode 100644
index 0000000..b09d3ba
--- /dev/null
+++ b/src/less/bootstrap-tour-standalone.less
@@ -0,0 +1,15 @@
+/*!
+ * Bootstrap v3.1.0 (http://getbootstrap.com)
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+// Core variables and mixins
+ at bootstrap-path: "../../bower_components/bootstrap/less/";
+
+ at import "@{bootstrap-path}variables.less";
+ at import "@{bootstrap-path}mixins.less";
+ at import "@{bootstrap-path}buttons.less";
+ at import "@{bootstrap-path}button-groups.less";
+ at import "@{bootstrap-path}popovers.less";
+ at import "bootstrap-tour.less";
diff --git a/src/less/bootstrap-tour.less b/src/less/bootstrap-tour.less
new file mode 100644
index 0000000..4292840
--- /dev/null
+++ b/src/less/bootstrap-tour.less
@@ -0,0 +1,60 @@
+.tour-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1100;
+  background-color: #000;
+  opacity: 0.8;
+  filter: alpha(opacity=80);
+}
+
+.tour-step-backdrop {
+  position: relative;
+  z-index: 1101;
+  background: inherit;
+
+  > td {
+    position: relative;
+    z-index: 1101;
+  }
+}
+
+.tour-step-background {
+  position: absolute !important;
+  z-index: 1100;
+  background: inherit;
+  border-radius: 6px;
+}
+
+.popover[class*="tour-"] {
+  z-index: 1100;
+
+  .popover-navigation {
+    padding: 9px 14px;
+
+    *[data-role="end"] {
+      float: right;
+    }
+
+    *[data-role="prev"],
+    *[data-role="next"],
+    *[data-role="end"] {
+      cursor: pointer;
+
+      &.disabled {
+        cursor: default;
+      }
+    }
+  }
+
+  &.orphan {
+    position: fixed;
+    margin-top: 0;
+
+    .arrow {
+      display: none;
+    }
+  }
+}
diff --git a/test/bootstrap-tour.js b/test/bootstrap-tour.js
new file mode 100644
index 0000000..1874061
--- /dev/null
+++ b/test/bootstrap-tour.js
@@ -0,0 +1,802 @@
+/* ========================================================================
+ * bootstrap-tour - v0.10.1
+ * http://bootstraptour.com
+ * ========================================================================
+ * Copyright 2012-2013 Ulrich Sossou
+ *
+ * ========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================================
+ */
+
+(function($, window) {
+  var Tour, document;
+  document = window.document;
+  Tour = (function() {
+    function Tour(options) {
+      var storage;
+      try {
+        storage = window.localStorage;
+      } catch (_error) {
+        storage = false;
+      }
+      this._options = $.extend({
+        name: 'tour',
+        steps: [],
+        container: 'body',
+        autoscroll: true,
+        keyboard: true,
+        storage: storage,
+        debug: false,
+        backdrop: false,
+        backdropPadding: 0,
+        redirect: true,
+        orphan: false,
+        duration: false,
+        delay: false,
+        basePath: '',
+        template: '<div class="popover" role="tooltip"> <div class="arrow"></div> <h3 class="popover-title"></h3> <div class="popover-content"></div> <div class="popover-navigation"> <div class="btn-group"> <button class="btn btn-sm btn-default" data-role="prev">« Prev</button> <button class="btn btn-sm btn-default" data-role="next">Next »</button> <button class="btn btn-sm btn-default" data-role="pause-resume" data-pause-text="Pause" data-resume-text="Resume">Pause</button>  [...]
+        afterSetState: function(key, value) {},
+        afterGetState: function(key, value) {},
+        afterRemoveState: function(key) {},
+        onStart: function(tour) {},
+        onEnd: function(tour) {},
+        onShow: function(tour) {},
+        onShown: function(tour) {},
+        onHide: function(tour) {},
+        onHidden: function(tour) {},
+        onNext: function(tour) {},
+        onPrev: function(tour) {},
+        onPause: function(tour, duration) {},
+        onResume: function(tour, duration) {}
+      }, options);
+      this._force = false;
+      this._inited = false;
+      this.backdrop = {
+        overlay: null,
+        $element: null,
+        $background: null,
+        backgroundShown: false,
+        overlayElementShown: false
+      };
+      this;
+    }
+
+    Tour.prototype.addSteps = function(steps) {
+      var step, _i, _len;
+      for (_i = 0, _len = steps.length; _i < _len; _i++) {
+        step = steps[_i];
+        this.addStep(step);
+      }
+      return this;
+    };
+
+    Tour.prototype.addStep = function(step) {
+      this._options.steps.push(step);
+      return this;
+    };
+
+    Tour.prototype.getStep = function(i) {
+      if (this._options.steps[i] != null) {
+        return $.extend({
+          id: "step-" + i,
+          path: '',
+          placement: 'right',
+          title: '',
+          content: '<p></p>',
+          next: i === this._options.steps.length - 1 ? -1 : i + 1,
+          prev: i - 1,
+          animation: true,
+          container: this._options.container,
+          autoscroll: this._options.autoscroll,
+          backdrop: this._options.backdrop,
+          backdropPadding: this._options.backdropPadding,
+          redirect: this._options.redirect,
+          orphan: this._options.orphan,
+          duration: this._options.duration,
+          delay: this._options.delay,
+          template: this._options.template,
+          onShow: this._options.onShow,
+          onShown: this._options.onShown,
+          onHide: this._options.onHide,
+          onHidden: this._options.onHidden,
+          onNext: this._options.onNext,
+          onPrev: this._options.onPrev,
+          onPause: this._options.onPause,
+          onResume: this._options.onResume
+        }, this._options.steps[i]);
+      }
+    };
+
+    Tour.prototype.init = function(force) {
+      this._force = force;
+      if (this.ended()) {
+        this._debug('Tour ended, init prevented.');
+        return this;
+      }
+      this.setCurrentStep();
+      this._initMouseNavigation();
+      this._initKeyboardNavigation();
+      this._onResize((function(_this) {
+        return function() {
+          return _this.showStep(_this._current);
+        };
+      })(this));
+      if (this._current !== null) {
+        this.showStep(this._current);
+      }
+      this._inited = true;
+      return this;
+    };
+
+    Tour.prototype.start = function(force) {
+      var promise;
+      if (force == null) {
+        force = false;
+      }
+      if (!this._inited) {
+        this.init(force);
+      }
+      if (this._current === null) {
+        promise = this._makePromise(this._options.onStart != null ? this._options.onStart(this) : void 0);
+        this._callOnPromiseDone(promise, this.showStep, 0);
+      }
+      return this;
+    };
+
+    Tour.prototype.next = function() {
+      var promise;
+      promise = this.hideStep(this._current);
+      return this._callOnPromiseDone(promise, this._showNextStep);
+    };
+
+    Tour.prototype.prev = function() {
+      var promise;
+      promise = this.hideStep(this._current);
+      return this._callOnPromiseDone(promise, this._showPrevStep);
+    };
+
+    Tour.prototype.goTo = function(i) {
+      var promise;
+      promise = this.hideStep(this._current);
+      return this._callOnPromiseDone(promise, this.showStep, i);
+    };
+
+    Tour.prototype.end = function() {
+      var endHelper, promise;
+      endHelper = (function(_this) {
+        return function(e) {
+          $(document).off("click.tour-" + _this._options.name);
+          $(document).off("keyup.tour-" + _this._options.name);
+          $(window).off("resize.tour-" + _this._options.name);
+          _this._setState('end', 'yes');
+          _this._inited = false;
+          _this._force = false;
+          _this._clearTimer();
+          if (_this._options.onEnd != null) {
+            return _this._options.onEnd(_this);
+          }
+        };
+      })(this);
+      promise = this.hideStep(this._current);
+      return this._callOnPromiseDone(promise, endHelper);
+    };
+
+    Tour.prototype.ended = function() {
+      return !this._force && !!this._getState('end');
+    };
+
+    Tour.prototype.restart = function() {
+      this._removeState('current_step');
+      this._removeState('end');
+      return this.start();
+    };
+
+    Tour.prototype.pause = function() {
+      var step;
+      step = this.getStep(this._current);
+      if (!(step && step.duration)) {
+        return this;
+      }
+      this._paused = true;
+      this._duration -= new Date().getTime() - this._start;
+      window.clearTimeout(this._timer);
+      this._debug("Paused/Stopped step " + (this._current + 1) + " timer (" + this._duration + " remaining).");
+      if (step.onPause != null) {
+        return step.onPause(this, this._duration);
+      }
+    };
+
+    Tour.prototype.resume = function() {
+      var step;
+      step = this.getStep(this._current);
+      if (!(step && step.duration)) {
+        return this;
+      }
+      this._paused = false;
+      this._start = new Date().getTime();
+      this._duration = this._duration || step.duration;
+      this._timer = window.setTimeout((function(_this) {
+        return function() {
+          if (_this._isLast()) {
+            return _this.next();
+          } else {
+            return _this.end();
+          }
+        };
+      })(this), this._duration);
+      this._debug("Started step " + (this._current + 1) + " timer with duration " + this._duration);
+      if ((step.onResume != null) && this._duration !== step.duration) {
+        return step.onResume(this, this._duration);
+      }
+    };
+
+    Tour.prototype.hideStep = function(i) {
+      var hideStepHelper, promise, step;
+      step = this.getStep(i);
+      if (!step) {
+        return;
+      }
+      this._clearTimer();
+      promise = this._makePromise(step.onHide != null ? step.onHide(this, i) : void 0);
+      hideStepHelper = (function(_this) {
+        return function(e) {
+          var $element;
+          $element = $(step.element);
+          if (!($element.data('bs.popover') || $element.data('popover'))) {
+            $element = $('body');
+          }
+          $element.popover('destroy').removeClass("tour-" + _this._options.name + "-element tour-" + _this._options.name + "-" + i + "-element");
+          if (step.reflex) {
+            $element.removeClass('tour-step-element-reflex').off("" + (_this._reflexEvent(step.reflex)) + ".tour-" + _this._options.name);
+          }
+          if (step.backdrop) {
+            _this._hideBackdrop();
+          }
+          if (step.onHidden != null) {
+            return step.onHidden(_this);
+          }
+        };
+      })(this);
+      this._callOnPromiseDone(promise, hideStepHelper);
+      return promise;
+    };
+
+    Tour.prototype.showStep = function(i) {
+      var promise, showStepHelper, skipToPrevious, step;
+      if (this.ended()) {
+        this._debug('Tour ended, showStep prevented.');
+        return this;
+      }
+      step = this.getStep(i);
+      if (!step) {
+        return;
+      }
+      skipToPrevious = i < this._current;
+      promise = this._makePromise(step.onShow != null ? step.onShow(this, i) : void 0);
+      showStepHelper = (function(_this) {
+        return function(e) {
+          var current_path, path, showPopoverAndOverlay;
+          _this.setCurrentStep(i);
+          path = (function() {
+            switch ({}.toString.call(step.path)) {
+              case '[object Function]':
+                return step.path();
+              case '[object String]':
+                return this._options.basePath + step.path;
+              default:
+                return step.path;
+            }
+          }).call(_this);
+          current_path = [document.location.pathname, document.location.hash].join('');
+          if (_this._isRedirect(path, current_path)) {
+            _this._redirect(step, path);
+            return;
+          }
+          if (_this._isOrphan(step)) {
+            if (!step.orphan) {
+              _this._debug("Skip the orphan step " + (_this._current + 1) + ".\nOrphan option is false and the element does not exist or is hidden.");
+              if (skipToPrevious) {
+                _this._showPrevStep();
+              } else {
+                _this._showNextStep();
+              }
+              return;
+            }
+            _this._debug("Show the orphan step " + (_this._current + 1) + ". Orphans option is true.");
+          }
+          if (step.backdrop) {
+            _this._showBackdrop(!_this._isOrphan(step) ? step.element : void 0);
+          }
+          showPopoverAndOverlay = function() {
+            if (_this.getCurrentStep() !== i) {
+              return;
+            }
+            if ((step.element != null) && step.backdrop) {
+              _this._showOverlayElement(step);
+            }
+            _this._showPopover(step, i);
+            if (step.onShown != null) {
+              step.onShown(_this);
+            }
+            return _this._debug("Step " + (_this._current + 1) + " of " + _this._options.steps.length);
+          };
+          if (step.autoscroll) {
+            _this._scrollIntoView(step.element, showPopoverAndOverlay);
+          } else {
+            showPopoverAndOverlay();
+          }
+          if (step.duration) {
+            return _this.resume();
+          }
+        };
+      })(this);
+      if (step.delay) {
+        this._debug("Wait " + step.delay + " milliseconds to show the step " + (this._current + 1));
+        window.setTimeout((function(_this) {
+          return function() {
+            return _this._callOnPromiseDone(promise, showStepHelper);
+          };
+        })(this), step.delay);
+      } else {
+        this._callOnPromiseDone(promise, showStepHelper);
+      }
+      return promise;
+    };
+
+    Tour.prototype.getCurrentStep = function() {
+      return this._current;
+    };
+
+    Tour.prototype.setCurrentStep = function(value) {
+      if (value != null) {
+        this._current = value;
+        this._setState('current_step', value);
+      } else {
+        this._current = this._getState('current_step');
+        this._current = this._current === null ? null : parseInt(this._current, 10);
+      }
+      return this;
+    };
+
+    Tour.prototype._setState = function(key, value) {
+      var e, keyName;
+      if (this._options.storage) {
+        keyName = "" + this._options.name + "_" + key;
+        try {
+          this._options.storage.setItem(keyName, value);
+        } catch (_error) {
+          e = _error;
+          if (e.code === DOMException.QUOTA_EXCEEDED_ERR) {
+            this._debug('LocalStorage quota exceeded. State storage failed.');
+          }
+        }
+        return this._options.afterSetState(keyName, value);
+      } else {
+        if (this._state == null) {
+          this._state = {};
+        }
+        return this._state[key] = value;
+      }
+    };
+
+    Tour.prototype._removeState = function(key) {
+      var keyName;
+      if (this._options.storage) {
+        keyName = "" + this._options.name + "_" + key;
+        this._options.storage.removeItem(keyName);
+        return this._options.afterRemoveState(keyName);
+      } else {
+        if (this._state != null) {
+          return delete this._state[key];
+        }
+      }
+    };
+
+    Tour.prototype._getState = function(key) {
+      var keyName, value;
+      if (this._options.storage) {
+        keyName = "" + this._options.name + "_" + key;
+        value = this._options.storage.getItem(keyName);
+      } else {
+        if (this._state != null) {
+          value = this._state[key];
+        }
+      }
+      if (value === void 0 || value === 'null') {
+        value = null;
+      }
+      this._options.afterGetState(key, value);
+      return value;
+    };
+
+    Tour.prototype._showNextStep = function() {
+      var promise, showNextStepHelper, step;
+      step = this.getStep(this._current);
+      showNextStepHelper = (function(_this) {
+        return function(e) {
+          return _this.showStep(step.next);
+        };
+      })(this);
+      promise = this._makePromise(step.onNext != null ? step.onNext(this) : void 0);
+      return this._callOnPromiseDone(promise, showNextStepHelper);
+    };
+
+    Tour.prototype._showPrevStep = function() {
+      var promise, showPrevStepHelper, step;
+      step = this.getStep(this._current);
+      showPrevStepHelper = (function(_this) {
+        return function(e) {
+          return _this.showStep(step.prev);
+        };
+      })(this);
+      promise = this._makePromise(step.onPrev != null ? step.onPrev(this) : void 0);
+      return this._callOnPromiseDone(promise, showPrevStepHelper);
+    };
+
+    Tour.prototype._debug = function(text) {
+      if (this._options.debug) {
+        return window.console.log("Bootstrap Tour '" + this._options.name + "' | " + text);
+      }
+    };
+
+    Tour.prototype._isRedirect = function(path, currentPath) {
+      return (path != null) && path !== '' && (({}.toString.call(path) === '[object RegExp]' && !path.test(currentPath)) || ({}.toString.call(path) === '[object String]' && path.replace(/\?.*$/, '').replace(/\/?$/, '') !== currentPath.replace(/\/?$/, '')));
+    };
+
+    Tour.prototype._redirect = function(step, path) {
+      if ($.isFunction(step.redirect)) {
+        return step.redirect.call(this, path);
+      } else if (step.redirect === true) {
+        this._debug("Redirect to " + path);
+        return document.location.href = path;
+      }
+    };
+
+    Tour.prototype._isOrphan = function(step) {
+      return (step.element == null) || !$(step.element).length || $(step.element).is(':hidden') && ($(step.element)[0].namespaceURI !== 'http://www.w3.org/2000/svg');
+    };
+
+    Tour.prototype._isLast = function() {
+      return this._current < this._options.steps.length - 1;
+    };
+
+    Tour.prototype._showPopover = function(step, i) {
+      var $element, $tip, isOrphan, options;
+      $(".tour-" + this._options.name).remove();
+      options = $.extend({}, this._options);
+      isOrphan = this._isOrphan(step);
+      step.template = this._template(step, i);
+      if (isOrphan) {
+        step.element = 'body';
+        step.placement = 'top';
+      }
+      $element = $(step.element);
+      $element.addClass("tour-" + this._options.name + "-element tour-" + this._options.name + "-" + i + "-element");
+      if (step.options) {
+        $.extend(options, step.options);
+      }
+      if (step.reflex && !isOrphan) {
+        $element.addClass('tour-step-element-reflex');
+        $element.off("" + (this._reflexEvent(step.reflex)) + ".tour-" + this._options.name);
+        $element.on("" + (this._reflexEvent(step.reflex)) + ".tour-" + this._options.name, (function(_this) {
+          return function() {
+            if (_this._isLast()) {
+              return _this.next();
+            } else {
+              return _this.end();
+            }
+          };
+        })(this));
+      }
+      $element.popover({
+        placement: step.placement,
+        trigger: 'manual',
+        title: step.title,
+        content: step.content,
+        html: true,
+        animation: step.animation,
+        container: step.container,
+        template: step.template,
+        selector: step.element
+      }).popover('show');
+      $tip = $element.data('bs.popover') ? $element.data('bs.popover').tip() : $element.data('popover').tip();
+      $tip.attr('id', step.id);
+      this._reposition($tip, step);
+      if (isOrphan) {
+        return this._center($tip);
+      }
+    };
+
+    Tour.prototype._template = function(step, i) {
+      var $navigation, $next, $prev, $resume, $template;
+      $template = $.isFunction(step.template) ? $(step.template(i, step)) : $(step.template);
+      $navigation = $template.find('.popover-navigation');
+      $prev = $navigation.find('[data-role="prev"]');
+      $next = $navigation.find('[data-role="next"]');
+      $resume = $navigation.find('[data-role="pause-resume"]');
+      if (this._isOrphan(step)) {
+        $template.addClass('orphan');
+      }
+      $template.addClass("tour-" + this._options.name + " tour-" + this._options.name + "-" + i);
+      if (step.prev < 0) {
+        $prev.addClass('disabled');
+      }
+      if (step.next < 0) {
+        $next.addClass('disabled');
+      }
+      if (!step.duration) {
+        $resume.remove();
+      }
+      return $template.clone().wrap('<div>').parent().html();
+    };
+
+    Tour.prototype._reflexEvent = function(reflex) {
+      if ({}.toString.call(reflex) === '[object Boolean]') {
+        return 'click';
+      } else {
+        return reflex;
+      }
+    };
+
+    Tour.prototype._reposition = function($tip, step) {
+      var offsetBottom, offsetHeight, offsetRight, offsetWidth, originalLeft, originalTop, tipOffset;
+      offsetWidth = $tip[0].offsetWidth;
+      offsetHeight = $tip[0].offsetHeight;
+      tipOffset = $tip.offset();
+      originalLeft = tipOffset.left;
+      originalTop = tipOffset.top;
+      offsetBottom = $(document).outerHeight() - tipOffset.top - $tip.outerHeight();
+      if (offsetBottom < 0) {
+        tipOffset.top = tipOffset.top + offsetBottom;
+      }
+      offsetRight = $('html').outerWidth() - tipOffset.left - $tip.outerWidth();
+      if (offsetRight < 0) {
+        tipOffset.left = tipOffset.left + offsetRight;
+      }
+      if (tipOffset.top < 0) {
+        tipOffset.top = 0;
+      }
+      if (tipOffset.left < 0) {
+        tipOffset.left = 0;
+      }
+      $tip.offset(tipOffset);
+      if (step.placement === 'bottom' || step.placement === 'top') {
+        if (originalLeft !== tipOffset.left) {
+          return this._replaceArrow($tip, (tipOffset.left - originalLeft) * 2, offsetWidth, 'left');
+        }
+      } else {
+        if (originalTop !== tipOffset.top) {
+          return this._replaceArrow($tip, (tipOffset.top - originalTop) * 2, offsetHeight, 'top');
+        }
+      }
+    };
+
+    Tour.prototype._center = function($tip) {
+      return $tip.css('top', $(window).outerHeight() / 2 - $tip.outerHeight() / 2);
+    };
+
+    Tour.prototype._replaceArrow = function($tip, delta, dimension, position) {
+      return $tip.find('.arrow').css(position, delta ? 50 * (1 - delta / dimension) + '%' : '');
+    };
+
+    Tour.prototype._scrollIntoView = function(element, callback) {
+      var $element, $window, counter, offsetTop, scrollTop, windowHeight;
+      $element = $(element);
+      if (!$element.length) {
+        return callback();
+      }
+      $window = $(window);
+      offsetTop = $element.offset().top;
+      windowHeight = $window.height();
+      scrollTop = Math.max(0, offsetTop - (windowHeight / 2));
+      this._debug("Scroll into view. ScrollTop: " + scrollTop + ". Element offset: " + offsetTop + ". Window height: " + windowHeight + ".");
+      counter = 0;
+      return $('body, html').stop(true, true).animate({
+        scrollTop: Math.ceil(scrollTop)
+      }, (function(_this) {
+        return function() {
+          if (++counter === 2) {
+            callback();
+            return _this._debug("Scroll into view.\nAnimation end element offset: " + ($element.offset().top) + ".\nWindow height: " + ($window.height()) + ".");
+          }
+        };
+      })(this));
+    };
+
+    Tour.prototype._onResize = function(callback, timeout) {
+      return $(window).on("resize.tour-" + this._options.name, function() {
+        clearTimeout(timeout);
+        return timeout = setTimeout(callback, 100);
+      });
+    };
+
+    Tour.prototype._initMouseNavigation = function() {
+      var _this;
+      _this = this;
+      return $(document).off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='prev']").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='next']").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='end']").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='pause-resume']").on("click.tour-" + this._options.name, ".pop [...]
+        return function(e) {
+          e.preventDefault();
+          return _this.next();
+        };
+      })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='prev']", (function(_this) {
+        return function(e) {
+          e.preventDefault();
+          return _this.prev();
+        };
+      })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='end']", (function(_this) {
+        return function(e) {
+          e.preventDefault();
+          return _this.end();
+        };
+      })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='pause-resume']", function(e) {
+        var $this;
+        e.preventDefault();
+        $this = $(this);
+        $this.text(_this._paused ? $this.data('pause-text') : $this.data('resume-text'));
+        if (_this._paused) {
+          return _this.resume();
+        } else {
+          return _this.pause();
+        }
+      });
+    };
+
+    Tour.prototype._initKeyboardNavigation = function() {
+      if (!this._options.keyboard) {
+        return;
+      }
+      return $(document).on("keyup.tour-" + this._options.name, (function(_this) {
+        return function(e) {
+          if (!e.which) {
+            return;
+          }
+          switch (e.which) {
+            case 39:
+              e.preventDefault();
+              if (_this._isLast()) {
+                return _this.next();
+              } else {
+                return _this.end();
+              }
+              break;
+            case 37:
+              e.preventDefault();
+              if (_this._current > 0) {
+                return _this.prev();
+              }
+              break;
+            case 27:
+              e.preventDefault();
+              return _this.end();
+          }
+        };
+      })(this));
+    };
+
+    Tour.prototype._makePromise = function(result) {
+      if (result && $.isFunction(result.then)) {
+        return result;
+      } else {
+        return null;
+      }
+    };
+
+    Tour.prototype._callOnPromiseDone = function(promise, cb, arg) {
+      if (promise) {
+        return promise.then((function(_this) {
+          return function(e) {
+            return cb.call(_this, arg);
+          };
+        })(this));
+      } else {
+        return cb.call(this, arg);
+      }
+    };
+
+    Tour.prototype._showBackdrop = function(element) {
+      if (this.backdrop.backgroundShown) {
+        return;
+      }
+      this.backdrop = $('<div>', {
+        "class": 'tour-backdrop'
+      });
+      this.backdrop.backgroundShown = true;
+      return $('body').append(this.backdrop);
+    };
+
+    Tour.prototype._hideBackdrop = function() {
+      this._hideOverlayElement();
+      return this._hideBackground();
+    };
+
+    Tour.prototype._hideBackground = function() {
+      if (this.backdrop) {
+        this.backdrop.remove();
+        this.backdrop.overlay = null;
+        return this.backdrop.backgroundShown = false;
+      }
+    };
+
+    Tour.prototype._showOverlayElement = function(step) {
+      var $element, elementData;
+      $element = $(step.element);
+      if (!$element || $element.length === 0 || this.backdrop.overlayElementShown) {
+        return;
+      }
+      this.backdrop.overlayElementShown = true;
+      this.backdrop.$element = $element.addClass('tour-step-backdrop');
+      this.backdrop.$background = $('<div>', {
+        "class": 'tour-step-background'
+      });
+      elementData = {
+        width: $element.innerWidth(),
+        height: $element.innerHeight(),
+        offset: $element.offset()
+      };
+      this.backdrop.$background.appendTo('body');
+      if (step.backdropPadding) {
+        elementData = this._applyBackdropPadding(step.backdropPadding, elementData);
+      }
+      return this.backdrop.$background.width(elementData.width).height(elementData.height).offset(elementData.offset);
+    };
+
+    Tour.prototype._hideOverlayElement = function() {
+      if (!this.backdrop.overlayElementShown) {
+        return;
+      }
+      this.backdrop.$element.removeClass('tour-step-backdrop');
+      this.backdrop.$background.remove();
+      this.backdrop.$element = null;
+      this.backdrop.$background = null;
+      return this.backdrop.overlayElementShown = false;
+    };
+
+    Tour.prototype._applyBackdropPadding = function(padding, data) {
+      if (typeof padding === 'object') {
+        if (padding.top == null) {
+          padding.top = 0;
+        }
+        if (padding.right == null) {
+          padding.right = 0;
+        }
+        if (padding.bottom == null) {
+          padding.bottom = 0;
+        }
+        if (padding.left == null) {
+          padding.left = 0;
+        }
+        data.offset.top = data.offset.top - padding.top;
+        data.offset.left = data.offset.left - padding.left;
+        data.width = data.width + padding.left + padding.right;
+        data.height = data.height + padding.top + padding.bottom;
+      } else {
+        data.offset.top = data.offset.top - padding;
+        data.offset.left = data.offset.left - padding;
+        data.width = data.width + (padding * 2);
+        data.height = data.height + (padding * 2);
+      }
+      return data;
+    };
+
+    Tour.prototype._clearTimer = function() {
+      window.clearTimeout(this._timer);
+      this._timer = null;
+      return this._duration = null;
+    };
+
+    return Tour;
+
+  })();
+  return window.Tour = Tour;
+})(jQuery, window);

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-bootstrap-tour.git



More information about the Pkg-javascript-commits mailing list