bootstrap-tour-0.10.2/000077500000000000000000000000001246560743700146145ustar00rootroot00000000000000bootstrap-tour-0.10.2/.editorconfig000066400000000000000000000006351246560743700172750ustar00rootroot00000000000000EditorConfig 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 bootstrap-tour-0.10.2/.gitignore000066400000000000000000000002351246560743700166040ustar00rootroot00000000000000node_modules bower_components bootstrap-tour.sublime-project bootstrap-tour.sublime-workspace npm-debug.log test docs _SpecRunner.html *.DS_Store smart.lock bootstrap-tour-0.10.2/.travis.yml000066400000000000000000000003631246560743700167270ustar00rootroot00000000000000language: 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 bootstrap-tour-0.10.2/CNAME000066400000000000000000000000221246560743700153540ustar00rootroot00000000000000bootstraptour.com bootstrap-tour-0.10.2/LICENSE000066400000000000000000000236741246560743700156350ustar00rootroot00000000000000 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 CONDITIONSbootstrap-tour-0.10.2/README.md000066400000000000000000000047201246560743700160760ustar00rootroot00000000000000# 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/). bootstrap-tour-0.10.2/_config.yml000066400000000000000000000002031246560743700167360ustar00rootroot00000000000000markdown: rdiscount permalink: pretty source: ./src/docs destination: ./docs encoding: UTF-8 bootstrap-tour-0.10.2/bower.json000066400000000000000000000007031246560743700166250ustar00rootroot00000000000000{ "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" } } bootstrap-tour-0.10.2/build/000077500000000000000000000000001246560743700157135ustar00rootroot00000000000000bootstrap-tour-0.10.2/build/css/000077500000000000000000000000001246560743700165035ustar00rootroot00000000000000bootstrap-tour-0.10.2/build/css/bootstrap-tour-standalone.css000066400000000000000000000413221246560743700243510ustar00rootroot00000000000000/* ======================================================================== * 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; } bootstrap-tour-0.10.2/build/css/bootstrap-tour.css000066400000000000000000000042341246560743700222240ustar00rootroot00000000000000/* ======================================================================== * 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; } bootstrap-tour-0.10.2/build/js/000077500000000000000000000000001246560743700163275ustar00rootroot00000000000000bootstrap-tour-0.10.2/build/js/bootstrap-tour-standalone.js000066400000000000000000001314511246560743700240240ustar00rootroot00000000000000/* ======================================================================== * 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: '', 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: '' }) // 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: '', 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: '

', 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('
').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, ".popover.tour-" + this._options.name + " *[data-role='next']", (function(_this) { 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 = $('
', { "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 = $('
', { "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); bootstrap-tour-0.10.2/coffeelint.json000066400000000000000000000060431246560743700176300ustar00rootroot00000000000000{ "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" } } bootstrap-tour-0.10.2/composer.json000066400000000000000000000006361246560743700173430ustar00rootroot00000000000000{ "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" } bootstrap-tour-0.10.2/gulpfile.coffee000066400000000000000000000141121246560743700175730ustar00rootroot00000000000000gulp = 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'] bootstrap-tour-0.10.2/gulpfile.js000066400000000000000000000001011246560743700167510ustar00rootroot00000000000000require('coffee-script/register'); require('./gulpfile.coffee'); bootstrap-tour-0.10.2/karma.json000066400000000000000000000006421246560743700166040ustar00rootroot00000000000000{ "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" ] } bootstrap-tour-0.10.2/package.js000066400000000000000000000001541246560743700165450ustar00rootroot00000000000000Package.describe({ summary: "Quick and easy way to build your product tours with Bootstrap Popovers." }); bootstrap-tour-0.10.2/package.json000066400000000000000000000036451246560743700171120ustar00rootroot00000000000000{ "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@gmail.com", "url": "http://ulrichsossou.com" }, "contributors": [ { "name": "Emanuele Marchi", "email": "emanuele@lostcrew.it", "url": "http://lostcrew.it" }, { "name": "Nicola Molinari", "email": "emmenko@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" } } bootstrap-tour-0.10.2/smart.json000066400000000000000000000005251246560743700166370ustar00rootroot00000000000000{ "name": "bootstrap-tour", "description": "Quick and easy way to build your product tours with Bootstrap Popovers.", "homepage": "http://bootstraptour.com", "author": "Ulrich Sossou (http://ulrichsossou.com)", "version": "0.10.2", "git": "https://github.com/sorich87/bootstrap-tour.git", "packages": {} } bootstrap-tour-0.10.2/src/000077500000000000000000000000001246560743700154035ustar00rootroot00000000000000bootstrap-tour-0.10.2/src/coffee/000077500000000000000000000000001246560743700166325ustar00rootroot00000000000000bootstrap-tour-0.10.2/src/coffee/bootstrap-tour.coffee000066400000000000000000000517651246560743700230250ustar00rootroot00000000000000(($, 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: '' 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: '

' # 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('
').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 = $ '
', 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 = $ '
', 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 bootstrap-tour-0.10.2/src/coffee/bootstrap-tour.docs.coffee000066400000000000000000000055421246560743700237440ustar00rootroot00000000000000$ -> $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.
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 5 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() $('
You ended the demo tour. Restart the demo tour.
').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" bootstrap-tour-0.10.2/src/coffee/bootstrap-tour.spec.coffee000066400000000000000000000677401246560743700237560ustar00rootroot00000000000000describe '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: $('
').appendTo('body') @tour.addStep(step) expect(@tour._options.steps).toEqual [step] it '`addSteps` should add multiple step', -> @tour = new Tour firstStep = element: $('
').appendTo('body') secondStep = element: $('
').appendTo('body') @tour.addSteps([firstStep, secondStep]) expect(@tour._options.steps).toEqual [firstStep, secondStep] it 'step should have an id', -> @tour = new Tour $element = $('
').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: $('
').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: $('
').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: $('
').appendTo('body')) @tour.addStep(element: $('
').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: $('
').appendTo('body')) @tour.addStep(element: $('
').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: $('
').appendTo('body')) @tour.addStep(element: $('
').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: $('
').appendTo('body')) @tour.addStep(element: $('
').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: $('
').appendTo('body')) @tour.addStep element: $('
').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: $('
').appendTo('body')) @tour.addStep element: $('
').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: $('
').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: '

' 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: $('
').appendTo('body')) @tour.start() expect($('.popover').length).toBe 1 it '`init` should continue a tour', -> @tour = new Tour @tour.addStep(element: $('
').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: $('
').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: $('
').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: $('
').appendTo('body')) @tour.addStep(element: $('
').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: $('
').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: $('
').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: $('
').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: $('
').appendTo('body')) @tour.addStep(element: $('
').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: $('
').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: $('
').appendTo('body')) @tour.addStep(element: $('
').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: $('
').appendTo('body')) @tour.addStep(element: $('
').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: $('
').appendTo('body') template: -> '
' @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: $('
').appendTo('body')) @tour.addStep(element: $('
').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: $('
').appendTo('body')}) @tour.addStep({element: $('
').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: $('
').appendTo('body')) @tour.addStep(element: $('
').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: $('
').appendTo('body')}) @tour.addStep({element: $('
').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: $('
').appendTo('body')) @tour.addStep(element: $('
').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: $('
').appendTo('body')) @tour.addStep element: $('
').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: $('
').appendTo('body') onHide: -> return deferred @tour.addStep(element: $('
').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: $('
').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 = $('
').appendTo('body') @tour.addStep element: $element reflex: true @tour.addStep(element: $('
').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: $('
').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: $('
').appendTo('body') backdrop: false @tour.addStep element: $('
').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 = $('
', width: 10, height: 10).appendTo('body') $secondElement = $('
', 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: $('
').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: $('
').appendTo('body')) @tour.addStep(element: $('
').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: $('
').appendTo('body')) @tour.addStep(element: $('
').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: $('
').appendTo('body') onNext: -> tour_test = 2 @tour.addStep(element: $('
').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: $('
').appendTo('body')) @tour.addStep(element: $('
').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: $('
').appendTo('body')) @tour.addStep element: $('
').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: '

' @tour.addStep(element: $('
').appendTo('body')) @tour.addStep(element: $('
').appendTo('body')) @tour.addStep(element: $('
').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 = $('
').appendTo('body') @tour = new Tour @tour.addStep element: $element reflex: true @tour.addStep(element: $('
').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: $('
').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 = $ '
' @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: $('
').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: $('
').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: $('
').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: $('
').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: $('
').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: $('
').appendTo('body') @tour.addStep element: $('
').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 ### bootstrap-tour-0.10.2/src/docs/000077500000000000000000000000001246560743700163335ustar00rootroot00000000000000bootstrap-tour-0.10.2/src/docs/CNAME000066400000000000000000000000221246560743700170730ustar00rootroot00000000000000bootstraptour.com bootstrap-tour-0.10.2/src/docs/_includes/000077500000000000000000000000001246560743700203005ustar00rootroot00000000000000bootstrap-tour-0.10.2/src/docs/_includes/footer.html000066400000000000000000000020371246560743700224660ustar00rootroot00000000000000 bootstrap-tour-0.10.2/src/docs/_includes/header.html000066400000000000000000000030611246560743700224160ustar00rootroot00000000000000 {% if page.title == "Bootstrap Tour" %} {{ page.title }} {% else %} {{ page.title }} · Bootstrap Tour {% endif %} bootstrap-tour-0.10.2/src/docs/_includes/nav.html000066400000000000000000000017051246560743700217550ustar00rootroot00000000000000 bootstrap-tour-0.10.2/src/docs/_layouts/000077500000000000000000000000001246560743700201725ustar00rootroot00000000000000bootstrap-tour-0.10.2/src/docs/_layouts/default.html000066400000000000000000000005561246560743700225120ustar00rootroot00000000000000 {% include header.html %} Fork me on GitHub {% include nav.html %} {{ content }} {% include footer.html %} bootstrap-tour-0.10.2/src/docs/api.html000066400000000000000000000656321246560743700200060ustar00rootroot00000000000000--- layout: default title: API Documentation slug: api ---

Global options

{% 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: "

|
", 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 %}
Name Type Description Default
name String 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. 'tour'
steps Array A list of object representing the steps to be included in the tour. Jump to Step options for the single step API. []
container String Appends the step popover to a specific element.
See Usage section of Popover.
'body'
autoscroll Boolean Autoscrolls the window when the step popover is out of view. true
keyboard Boolean This option set the left and right arrow navigation. true
storage Object The storage system you want to use. Could be the objects window.localStorage, window.sessionStorage or your own object.
You can set this option as false to disable storage persistence (the tour starts from beginning every time the page is loaded).
Read more about DOM Storage interfaces.
window.localStorage
debug Boolean Set this option to true to have some useful informations printed in the console. false
backdrop Boolean Show a dark backdrop behind the popover and its element, highlighting the current step. false
backdropPadding NEW Number|Object Add padding to the backdrop element that highlights the step element.
It can be a number or a object containing optional top, right, bottom and left numbers.
0
redirect Boolean|Function Set a custom function to execute as redirect function. The default redirect relies on the traditional document.location.href true
orphan Boolean 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. false
duration NEW Boolean|Number 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 false
delay NEW Boolean|Number Specifies a delay for the showing and hiding the tour steps. It can be:
  • a falsy - there is no delay
  • a number - used as a delay for both showing and hiding. In milliseconds
  • a object containing optional show and hide numbers - defines the delays for showing and hiding respectively
0
basePath String Specify a default base path prepended to the path option of every single step. Very useful if you need to reuse the same tour on different environments or sub-projects. ''
template String|Function String or function that returns a string of the HTML template for the popovers. If you pass a Function, two parameters are available: i is the position of step in the tour and step is the an object that contains all the other step options.
From version 0.5, the navigation template is included inside the template so you can easily rewrite it. However, Bootstrap Tour maps the previous, next and end logics to the elements which have the related data-role attribute. Therefore, you can also have multiple elements with the same data-role attribute.
{% highlight javascript %} "

|
" {% endhighlight %}
afterGetState, afterSetState, afterRemoveState Function You may want to do something right after Bootstrap Tour read, write or remove the state. Just pass functions to these.
Your functions can have two parameters:
  • key Contains the name of the state being saved. It can be current_step (for the state where the latest step the visitor viewed is saved) or end (for the state which is saved when the user complete the tour). Note that Bootstrap Tour prepends the key with tour_ when saving the state.
  • value The value of the state been saved. Can be the index of the current step if the key is current_step, or yes if the key is end.

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

{% highlight javascript %} var tour = new Tour({ afterSetState: function (key, value) { $.post("/some/path", value); } }); {% endhighlight %}
function (key, value) { }
onStart Function Function to execute when the tour starts. function (tour) { }
onEnd Function Function to execute when the tour ends. function (tour) { }
onShow Function Function to execute right before each step is shown. function (tour) { }
onShown Function Function to execute right after each step is shown. function (tour) { }
onHide Function Function to execute right before each step is hidden. function (tour) { }
onHidden Function Function to execute right after each step is hidden. function (tour) { }
onNext Function Function to execute when next step is called. function (tour) { }
onPrev Function Function to execute when prev step is called. function (tour) { }
onPause NEW Function Function to execute when pause is called. The second argument refers to the remaining duration. function (tour, duration) { }
onResume NEW Function Function to execute when resume is called. The second argument refers to the remaining duration. function (tour, duration) { }

Step Options

{% 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 %}
Name Type Description Default
path String or RegExp Path to the page on which the step should be shown. This allows you to build tours that span several pages! ''
element String (jQuery selector) HTML element on which the step popover should be shown.
If orphan is false, this option is required.
''
placement String|Function How to position the popover. Possible choices: 'top', 'bottom', 'left', 'right'. 'right'
title String|Function Step title ''
content String|Function Step content ''
next Integer Index of the step to show after this one, starting from 0 for the first step of the tour. -1 to not show the link to next step. By default, the next step (in the order you added them) will be shown.
This option should be used in conjunction with prev.
0
prev Integer Index of the step to show before this one, starting from 0 for the first step of the tour. -1 to not show the link to previous step. By default, the previous step (in the order you added them) will be shown.
This option should be used in conjunction with next.
0
animation Boolean Apply a css fade transition to the tooltip. true
container String (jQuery selector) Attachment of popover. Pass an element to append the popover to. By default the popover is appended after the 'element' above. This option is particularly helpful for Internet Explorer. 'body'
backdrop Boolean Show a dark backdrop behind the popover and its element, highlighting the current step. false
backdropPadding NEW Boolean|Object Add padding to the backdrop element that highlights the step element.
It can be a number or a object containing optional top, right, bottom and left numbers.
0
redirect Boolean|Function Set a custom function to execute as redirect function. The default redirect relies on the traditional document.location.href true
reflex UPDATED Boolean|String Enable the reflex mode: attach an handler on click on the step element to continue the tour.
In order to bind the handler to a custom event, you can pass a string with its name.
Also, the class tour-step-element-reflex is added to the element, as hook for your custom style (e.g: cursor: pointer).
false
orphan Boolean 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. false
duration NEW Boolean|String 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 false
template String|Function String or function that returns a string of the HTML template for the popovers. If you pass a Function, two parameters are available: i is the position of step in the tour and step is the object that contains all the other step options.
From version 0.5, the navigation template is included inside the template so you can easily rewrite it. However, Bootstrap Tour maps the previous, next and end logics to the elements which have the related data-role attribute. Therefore, you can also have multiple elements with the same data-role attribute.
{% highlight javascript %} "

|
" {% endhighlight %}
onShow Function Function to execute right before the step is shown. It overrides the global onShow option. function (tour) { }
onShown Function Function to execute right after the step is shown. It overrides the global onShown option. function (tour) { }
onHide Function Function to execute right before the step is hidden. It overrides the global onHide option. function (tour) { }
onHidden Function Function to execute right after the step is hidden. It overrides the global onHidden option. function (tour) { }
onNext Function Function to execute when next step is called. It overrides the global onNext option. function (tour) { }
onPrev Function Function to execute when prev step is called. It overrides the global onPrev option. function (tour) { }
onPause NEW Function Function to execute when pause is called. The second argument refers to the remaining duration. It overrides the global the onPause option function (tour, duration) { }
onResume NEW Function Function to execute when resume is called. The second argument refers to the remaining duration. It overrides the global onResume option function (tour, duration) { }
Name Description
addSteps([]) Add multiple steps to the tour. Pass an array of objects.
addStep({}) Add single step to the tour. Pass an object.
init() Initialize the tour. You must do it before calling start.
start(true) Start the tour. Pass true to force the start.
restart() Restart the tour after it ended.
end() End the tour prematurely.
next() Skip to the next step.
prev() Go back to the previous step.
goTo(i) UPDATED Skip to a specific step. Pass i as the index of the step in the tour (0-based).
From version 0.7.0, the method has been renamed since some Javascript compilers are confused by the property name goto, which is a reserved word) .
pause() Pause the duration timer. It works only if tour or current step has duration.
resume() Resume the duration timer. It works only if tour or current step has duration.
ended() Verify if the tour ended. Returns boolean.
getStep(i) Get the step object. Pass i as the index of the step in the tour (0-based).
getCurrentStep() Get the index of the current step.
setCurrentStep(i) Override the current step. Pass i as the index of the step in the tour (0-based).

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:

{% 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 %}

It's that simple.

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 path attribute and set the redirect attribute to a function that performs the redirect.

For example:

{% 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 %}

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 / to a search results page at /?q=foo, because from Bootstrap Tour's perspective, those are the same location (/).

To work around this limitation, you can set the onNext attribute a function that returns a promise.

For example:

{% 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 %}

Doing this will prevent the next step from popping up while the redirect is being completed in the onNext function.

bootstrap-tour-0.10.2/src/docs/assets/000077500000000000000000000000001246560743700176355ustar00rootroot00000000000000bootstrap-tour-0.10.2/src/docs/assets/css/000077500000000000000000000000001246560743700204255ustar00rootroot00000000000000bootstrap-tour-0.10.2/src/docs/assets/css/bootstrap-tour.css000066400000000000000000000042341246560743700241460ustar00rootroot00000000000000/* ======================================================================== * 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; } bootstrap-tour-0.10.2/src/docs/assets/css/bootstrap-tour.docs.css000066400000000000000000000022221246560743700250700ustar00rootroot00000000000000body { 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; } bootstrap-tour-0.10.2/src/docs/assets/fonts/000077500000000000000000000000001246560743700207665ustar00rootroot00000000000000bootstrap-tour-0.10.2/src/docs/assets/fonts/glyphicons-halflings-regular.eot000066400000000000000000000333771246560743700272770ustar00rootroot0000000000000065LP(GLYPHICONS HalflingsRegularxVersion 1.001;PS 001.001;hotconv 1.0.70;makeotf.lib2.5.583298GLYPHICONS Halflings RegularBSGPw5s5y-՟(tۊKD'P M BjbeJ2ccLF1+WEeuJe~m%W*IzI€sL x 4xїPS-UuT EF?ͬ ԯ4 ʨgq e${-+1u{S"!EB&/ LEK7fҮ|'=jpEA_B@*?~ 9&Iv@er>Mo˒ jp?P;_iƶ <}LbXUe1L !;  D ^% PPA@5KalӴğa!|ZhFFI0EF"đ'Mո9@) 1Aȶр< ,@A pACϲ\.mȤIxsS "rr}nN~lQo`>t鰅׶5 X` ­g9K g]s zT0%jkTg̙0"YVg@)>aFc!tz=Vk@op^v?J=f0[7@}t\}v\|f{y?=1"fxHxxi8kPY8~Ú7@(:3vXX+( F j19'(m} e CŒ=& e yEB(2E?xv5ki{P"IGkXLPŀE>G[|q!c+o0 a~\;!!+uX1H"U94%`)y1*/:>\g@xZ.]AҁK/ {[8]b.q~2DoRzKoGl{E 9 E ZR}3QOЕ6C).R%Oyr #QV?lGIV T.Rt ދmݯmbvvtOn#)aQy}vb2'*bG ~ 5s'åvx8)#7J @IƠ `S(E˖B!$<sm{э !`x뚢"ZaB3xW[׃jƃh%ptK[dC$UC@\)A~q/@zn2e?9ڟNظQ91Baa0#ژ.3+z%ԆEڔsA U|h@إs5S8*v0DUYmIs:DtXr/0[L N IĊ$appMNʢ7tDI'alY"4X r[{_MW X1bm]55N=G#r96#R Yi + f'F5 8@x4K.- 2:Q 4܏5 2XC7`M-j >;~L5nHHF4K߹Yprws4݌F۝F:0ӢL[f|J֠:h$Iry(*u&~Ke` 73)W$ %ضp@C\r|S"E"0irODhmd#$4E@J"T(L9ٴNCxM }D-BIrx)\)gUJiuO1T>|>JDbs-@E@]8B𴼅ږ X_3U  dDǁ_  tK4n,D"6@뇂 Fm`Y6'3¨2lpM`2"d[ ( /uҏbSL˳.":AU@pֽRE{BHƥ!Ia -w")w%᜙rwͳr6!1Y˘LTpxr8]>҈S"#^mꤾB\ i&U=Q1ğ,?t&r,@l5AیJ6\wx7I\`nsKpʴ݀׼ 2 L'M3Ki[v&VtFTH rxTUYEe}$W=X/}%KD*:D=K_`D#[JQl$ zs/qJI+X,$ gf`%Q6"@tN"9()y.B L*6o^44Ye-ҫz_|~nM7ڌTg `΋dkbrؐfv/$}%)-ėR & H|&X$ ;c+s-AЈ>>;_?-1hG*@Urȳˊ736h) O.M2>jj=B¦1MXB`LѰ >x dbN XKn,ཫW{퓙;ߴp[j)^`zWI֮ph4?ͿeSڃ 4+v{1XPBX qEsGp?gi{ӘMtꛖ c8;$<\3QZ ldvf܆"cž\"ZT)UZlUA'hE,ԁ.A=tFDRls )ș`/"; .2]bPcBro*[ B K|e40M 2Bf11yR<"FI'VPNɣ PF8`j"jm gxDA ڝHu*WX_9q[Liu N9v@pkvmRsS(@ص ۙbqL$ Ũ!gXYd ?ȩD|'C#ru*(no5"xc!Bi2쫳D\CE=zJk)gY]e0#`P"{Q]bڝPbjB!Zlv;"禥N[",0yԺ#u-  G!.nbFX &t!2]6HGH<hCK4N"7 |2~'hA$ VTvY =<I##!L$[%'RF!.Ŝ|m9('% tP+lw8D1g WޏY1lb (5Vzk1mֻ- I6 A9x?;gHɬ{) G) NpȀ O9•S%Ly|wx.3#"VʵKIZ ah[PȂ=̘Aa%[(P'RD8c PMn+jc̛3sh[t8(C3<#`ehup#5Aa υ)&DO֐/ޘZ)=)D'n_߼BGY\lZ@0!ӕ!CDFi`("ؽ59ZGG4?WあM'i?9l*FVH}P׊JMΗ[|bdML(Lԕ(И_\.2 B I?wTw2g`:kQ}$Uz>/H P@f}2(A  ߚ%ꑓ,q3)ΊjhhwVvVQ\!` tX5^B/')0t3~ $ 4wV 2(5[ Ru ſ[s~-b|PQ{?˺JT1[5k> ZNw&|r>d;Ũ8^V 0úZ"d&[,nY"}|)n6(4Su|[‚L6tc DDKi Kt2* 2eZ ͗74 QMiqHTyY(9Ta-kpxd [ Ny~Oq^lqQ0Z da-1s ##̨g |]6$dnj?~tM 褺ܵ6cƳ5eXU8GEv?chVK'C$ΧSA`nJwZ''ztOGlĈ[DQ+q B 9Ô<?l\幠$ssb'<W1Œ0DL6+Ak=m _Gv5p,sn.QaRPD+<3lM5_BԆANpH <.|[P ZmX%-6tg@@z&mL3't]]iulz$|H n30v?yUt{Ċ)¶U0~O[}") ٓ'jkMCX<-/pG? l 9 4F~uuh++cH녙Q&t֢xqt+_Q$T^؇`uOdQp] !H舰ŶSJTJygxh!8Gb*<T h}"N4bx#$ |͑aPlI :W`LU MKbTs(Sp~U1p.7 N٨DޛhAXa @+Ά-' 6O]TU<1qw$=ҼL3fi+Mp6œ6{LE;0~pNlZ$Nжbi)y^M\D dּPe#6AX4̆[;Ek7l-bGV0r)*r:Gw6UI>j#qRH{U곎!BR"3x"3ޗm0>=&B@J k̪ts0p~ TahB!s[ 1yκ VJ3!z TPLI:‹ qs/CO-!L21y؂F 䤣[''VDzdϏӆp.EkʤI$|e\T'H>;Y :+UC7cu@ʸ.x~J+I"FH8Nk"upMozG䰦r{;Dz UwRpRr`{ls>˲$@).x-ta"N ^~&@᧧/-QNkswl^ЎFVY'C?xBo܉Q M?~UjaSӯs5 {Y2aF܈:JsҴ@Wi['OvWB6}{I5kr(4u-07HX %$هAd?[h\<n _ʩXV3/2sEu9>^O5QkF&%Y0c[kO&cfhi13_3}wajiA$tۀz'$0,NRHJ(%Bܼv5|̱Xx,L@H^G#q;_uJg*W f#;0//ZU~n6+$zv}.0.= &p ῼ|f&s܇b9.A=`D`*yRp.2謅?0thZ3˷e5,i޾0Qe;,b т)Q@.և@(ښz.1E> J|W[+U""A *w]ySAH>>ȟ˩ѠF,#/즊w k~YHleuHx}+ p8'[UܥV#60(ΔrXS6YBm% MӃY67x-nh'*,R* ;|6 %UCrc2*yEǞ+xk*Z^0NAo*ZY5uC?0 0 2P GX2z6P3Դ1S` |&|ӀiEA)k0NjD܉ @}~wU,rqt¤S>^0$rI)Vrqúy7En Uwi!u%b^IOǐǑcIѾdCN];"TB)8$V Fk?2HO>Ќ c&ȗ%Z:h >p%H$zdfn(="^ӉY+D<*;{+Zy lB0ȁ! ޝOd"RgaH IҶigu*xx\j&>c5〸͔?Mln,㳅z8jpZ{c, S9<, ЬS·ҔgP37BxW_\Mb :-! ]1DEԦ<`讏FvL y|e2&}ڛR{I~|1N5߮Nh(f 1HlV8@E)+eeR hZ [VPgRfU iE(4"cl"EB`2| Æ@#*qS& @7[|< j-Ht*/I6q8Z`b[Y'PH W'4D딴5FcPjפd"ũRXrgI7πr7ϔ0F "p2hADypP \'T &sv9.+.LpiߤvHbȩETfe閹DY +ΰH۹ #K4xB2(D?}iS|fVWxeJΕp+gزxCAexTHqggл^#iovWGk 2F٨)1?t Üpt?د" IV~Wg7bt* ̯CRr D~*GP%Fo1(H%YZH^X Vr( dG;4$t*ebm\El&{JA j.#<2j}ҕJ:BZK?76DD&B_a/#QM`N`Po$_ qV9K1=9)~7>GoTX Tc*!a?XXC O4"!jiաE;3XM aHԞ] Ľ͵E湔LD& "^})a*+Vt@jg9aC} %X*+A& >UR)c|M+-#@\+ӔWl1ԑ5SΡ:ȓ/dd2@#FU2ɺ"47]83dlXf24g(%[ }5"5'u K R*#xۙX#G!tbHwvѰtBTt>F] p^2ep@Xw9anX)@F@ h>J&mAع!u=}TQW3AM@C\"Fd+OQBq&ռW:5sz%) yR# |Rƾr%fr_ yE-p&_7D4w@"ݰ0UYb!(epQ~"V vQ߷q\y6GYR_ UݐoP؁cZ& 4Rf{`Ph;N H(T7^ΕZ n[x._3OD EF"D(33tuᒯut`RhaZ(DJ$l0A H2"^H"y1e@-oojΛ]~!Hl]S33VYX Cg~ AGI6ם3BZcĉ#Lv-CP,V@+ԘáQLs $Eϖa,A#R fWdR60C i dfT:H' g"P4 I9U^@%2E.hE:h| հ!O::fŎ hs> 2E}vnrQVl֎FeJK(dlu0@U^_~Br.*hE{XIx9>gc}~>nN̥Zdda+3D6wp;aOE~*Mͪ\GG]>lyNaDJI%B,G,K͸3t24lG@{kd?$.CD07d:[>} )_蒾3˒] [ӝ7 #;>POf c&aulh=w!Xœ@w/z]Yaw[tf$E\.-vW!^J26Uinh%+W;n"1]C?`,i(-+Gօ1L;3QͿs'9@ѭN>]aӡ&6 G 2`QIBNR wc 4R>ʚMv.u'3ʉ :o"Zg?%h~Hg٬$%&]'gFOa̓q4nx<>"JrϢuG^}A5cBZXb'nQi03anL'ue[1Q/u0G ab-_j!7Ƿ2Gngu"#GRc++I2;W]n)D&3=!ض7yș> ߊ:W/-Q6qW,WEn VL_N|YkكZzTn,P<8x9AII-b(Qu5q|2?\**! S%YiQCU| &gyV\ a[uЩ5W ݖ@==t9(Z* @8 Y $Ɔ@``0@0@V,@"(@$C|H c @b)c   1+bA'A`@:y٘`n~ X`cnXI`pfݰv@MYdp U6/2 GA D/qbjmL=L]L;/R@q@5C1db هfgvؼ ,90/~}Oo淊#;#ڜsga]{0ـ 4/x KP^rtՠcH@Rb%ԁ=#H@yBπl`.T %E.}ب@*Diɘ$1wyvݳV807FH.Ɵ8J@`'`\LTApBs)r! ( i`bootstrap-tour-0.10.2/src/docs/assets/fonts/glyphicons-halflings-regular.svg000066400000000000000000001732651246560743700273100ustar00rootroot00000000000000 bootstrap-tour-0.10.2/src/docs/assets/fonts/glyphicons-halflings-regular.ttf000066400000000000000000000715101246560743700272740ustar00rootroot00000000000000pFFTMh+ GDEF OS/2il8`cmap/V.cvt (gaspglyf[Xhead8=b,6hhea xbd$hmtxpbloca@epmaxp.g( nameԖgH|postcQwjywebfK)Qs@= Z 2UKWN@ x  , (, pX@ + / _ "&' ' )29CEIY`iy")58AEIYiy * / _ "&' ' 04@EGP`bp $07@CHP`pfߴh     utmgf`_XWUOIC=76 5 *+  / / _ _ ""&&' ' '' " ),026499@C?EECGIDPYG``QbiRpyZdnvy} "$)0578@ACEHIPY`ipy%%''((h ./<2<2/<2<23!%3#(@ (ddLL!'#'7!5!'737!LȷȷȷLL !!!!!!Lpp,p,pd7!32>53#"'.'#7347#7367632#4.#"!!! 09C3JL3akw$B dqd%Kup<3LJ9D?{dJtB+0W5ju.xd/5dZgj7X0,Z>d.6L!!L|,A!2654&#".#"xx.,,nBUq,zxawי kEPrdL !%!!PXdPLgX,dp 764/&" '%'Mc $^fMy\ ' anf`p1 %!!5!!,,  ddd&&L &7>54&&7>5@JOWOFS  @JOW$OAXr67)Q7q  Orn)`*^ "'#"  6& ,mwm,NȎdXD>.54>0{xuX6Cy>>yC8ZwwyEH-Sv@9yUUy9@vS-IG  !3!7|ߒ ?p'G  !3!'7#'#77|ߒVJMNI ?p+ӎo%!55"&=462#P%??%d3||3d L #'+/3!#3%!!#3#3%#3#3%#3#!!#3%#3#3%#3PddXdd|dddd|ddddXDdddd|ddddLLdddpdddddddddp,dddddddLL/?#!"&5463!2#!"&5463!2#!"&5463!2#!"&5463!2pXppXppppp LL/?O_o+"&=46;2+"&=46;2+"&=46;2+"&=46;2+"&=46;2+"&=46;2+"&=46;2+"&=46;2+"&=46;2,[[L/?O_+"&=46;2#!"&=463!254&+";26%#!"&=463!2+"&=46;2#!"&=463!2,D|D|D["*%''2"4jjFF % ' 7  rj' "'#"  6& %3##5#5353,mwddddm,NȎddd "'#"  6& !5,mxFm+Mȍ+4&+";2675".547 654&ddd[՛[ҧg|b|p>طv՛[[v(>7xxd %#3#3#3#3P GQ%32?6?67'76?654/&/7&''&/&#"'72"&54&("/&./80PP,<-0&("/&2,;.P P-<-1~~~ Q,=,1&("-&3*:/QQ/:/.&0!)&1,;.Q v~XY~~YXd'+/37!2#!"&=463!5463!25!!#!"&5;#3#3#3#   ;),);d;)D);dddddddddL 2  2 d);;)ddd)<<)DDD #!!!#YpXd!#!"&5463!!X  ]  ~ p,   $  63!3D_VbdDVd #!333! #(2p,P,L !!3!3#3L,zp, dd2".4>  63 33ޠ__ޠ__TȖ_ޠ__ޠ\T,,   $  6###D_VȖDV,, !3#!"&5!3!73  a2,2D%      $  654D_VD򬫭# &632!&#"2>nv՛[[՛[XbQz[՛[[!7&#"#4>32732653#"'p[vƝp[vƝ Pv՛[zppPv՛[z d #'!!!#53!5!#53!5!#53!5!#53)!dLd|DddX ddX ddX ddX PddddddddddddLL3#3.>>dd({tZ ;26%+"&546;2+"&546;2cޣc 2  2    X   ,tޣcct  ,rr 4  4  X! ''7'77,,GGGG p ȍGGGGp!%7'654,,EojCV p 956nb %7654/%%!%7'654S{w,EojCV@%957n  !%-;?CGKO!535#!3%!33!5#5!)!%35#!3###!##5#535#5!3%!#53!3#3#%!5ddd dLd,|,,|dddddXdd,dd dd ddXdd,dd,dddd ddddd,ddddddd  ##;#3#3#3!#!53#73#%#5ddddddd,dddddd [[[[[[ 463!64'&"2 E ڴSS  TT  463! ' 364'&"2 E  2DdTT  D 2TTd !!!7dd|dd '.#!"!%#5!#3!7#!"&?>3!2^ > ^(P;dXdw& &  =Z  |_D  5"!5&'./#!5".?!#"(]q *m)>$\R+5.tB*. 0 BB6,-WB Ɍd (1!2#!5>54.'32654&32654&+dx!" E4+vO ); $,LlY}^7]7( 3AvFTMY3(; 2{MRaaTZo!5>76&'.'5m!:" 0G Ms (G 9#'% 4<99C/Q8$9%3#4.+!57#"#33'3#7~2.!"dpd"!/1K}}KK}}' 2dd2R ',১ !%3#4.+!57#"#3!55!'72/!"dpd"!.22 ১' v2dd2 ',K}}KK}}L/?54&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!26X ,LddddddddL/?54&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!26DLDLddddddddL/?5463!2#!"&5463!2#!"&5463!2#!"&5463!2#!"&Xp LddddddddL/?5463!2#!"&5463!2#!"&5463!2#!"&5463!2#!"&LLLLddddddddL/?O_o546;2+"&%5463!2#!"&546;2+"&%5463!2#!"&546;2+"&%5463!2#!"&546;2+"&%5463!2#!"&dd, dd, dd, dd, ddddddddddddddddL#*:J#354&+";2654&#!"3!265#53554&#!"3!2654&#!"3!26dd,dd ɦz,,XLddddKdK}ddddL#*:J54&+";26%3#54&#!"3!26535#554&#!"3!2654&#!"3!26ddXdd ȧ,,XddddKdK}dddd#!"&5463!2 ,,,,,,v,,,,p,,L#!"&5463!2!7'"&462Xd*J%NpNNp J>2pNNpN2.'&54>264&"X{yII99 "c]s+?yyk֖~rBB "koK{|ׁE֖jk2".4>"ޠ__ޠ__X_ޠ__ޠ]Vu%.54>.'&6?*IOWM?%N~OrÀDmssE.  \7[[GvwsuEYd;^w^yJ(I43nQRlh!&7/#!"&5463!"3!26=7'Tq\qiԥn);;));0rkqUqz,;) );;)}T2qkL.#!"&5463!#"3!265' ">LԥU);;));WhHCVC9 gg_5,P X;) );;)D>3CmC&4 L##!"&5463!2!"3!26=''Lԥ,54.#"32264>:3235DQ-"#1D1i 'D )2X23L(p  =dd   $353#!5#DQdddDddddd,1##5.'#53>75367#53.'#53#5YȌ*EkI6vkו4fIKnoKf!}sD;pc! !XXc!! XXX,,;@J!!!JXXXh !!?C(,XXXL %>7X_#FX-$DuMխg; ! !pڎ&ځp&ڎ&ځ&"# !!''gp':َ'ڂ'Wpٍ'#2".4>6&+";26#3՛[[՛[[::#6#[՛[[՛.d&-37;#<&/.#"&/&#"#3!3!53%7#)"6?!)!o" =' !'= #odd+ "pXp '0  .& d,d )W9`0/p257.>7>7.#>7>'&"76 8./ieh,Jhqx{\ScFak[)!#==Y0'C7y522>7.'"&5477.'FOsvvsOFFOsvvsOFEwRY,H 7:91.f|C-[TFk1ii%LX( (WT`G//G`TW( (( (WT`G//G`TW( p(3\;hI%E:JY||UIW `=^8j|Ci`$.8A #7./7>3277>7&'77.547?.'Ɣ%Rri' FOsvH=<%%ZeI&-/"0/a+'C. .%k.f|Қk1i/:Pegy8(( (WT`G/( 4kbf&2&?@06@nUIWj|C/WR #!26'.%5#! #/%~8~ddG  ! Ddd-d,d) '%/#&=47&=467462 kd^^dkX|X1) [@ NN @[ )1ES>XX>x  !5!35 57'!! 5#'73X,1I,z Xzŵ{L!2#!#"&546d);;)d);;L;));,;)X);dL-!!!!".=!32>'4=,,'MeeM',U'5%;) ,,p*R~jqP33Pqj~R*q \ #(,.h%7 `CaF%' BCa:dv!!# #!!}+++,Xp,pX232++"&=!"&=#"&5463!7!"&'&763!7>^6**20 -d&*? 2222*L !53463!2!!P;),);DPdd);;)L 3463!2!!;),);,P, pX);;)dD. 3# #3.**,X,/ 5! !5,X,/)* !>3!2!2#!"&=46#37#3$%);;));;Idddd'-$d;)d);;)d);dddddL '3%4632#"&%%##"+"&'=454>3546?.L]&/ S8 2"Rl Q 22 !'777'7'7'7'-N鳳N--N괴N-N,-N鳳N-,Nd*.#";;276=4&#!6=4&!#'#?3320`d={.%='='2ֈdd2D(%pKd9X+d,Qv,Q}dwXL".!#"&/&54;6;2#!#3'!5##320`d={.%='=2ֈdd2(%Kd9+d,Qv,QX+}wddU=A%632!2+#!"&5467!>;2654&#!*.'&54?'#3lj  m U.UkmTk:d%7   Vi pyLN'  % H YS(  SXeV8<#!"&'#"&46!'&54?632*#!32!7%#3m!jTnlU.U m  [   $%jP ' (SNLy q  d)YXaL6:4&'%54&"'&3!26!77><546!5L(NLy%p ' S22(SVjTnkUT  nBSV    65!%>54&#!"?265&5<.'&'!1XS) % p &yMN,(22SPVn  UTlnTXڂ  VS2 $54>!! [_u,nzݠ_&*2 $54> 5!5!5Uzݠ__._zzݠ_2 $54>333[yݠ__ݵ_zzݠ_,2 $54># #[yݠ__,,_zzݠ_p,2 $54>&277>7.'.'"'&65.'6.'&76746'&67>7&72267.'6'?6.'.'>72>[yݠ__ݒ+>=>1" T>9.*-fw"#. F = .2) ( (%  )#? 7 .R  ,$   _zzݠ_^  ' "q!w F  /JG  r$>   #/ & % I+ *  ' ) $# h1'  $ `#'7;!2#!"&=46#3!2#!"&=46!!!2#!"&=46!!d);;));;);;));; );;));;,;)d);;)d);dd;)d);;)d);dd;)d);;)d);dddL !5!L2dd  7'7!7''7'!77!7'7Iȁp/ȎȁpȎXpȎَȁppȎȁсȎ:pȎ 8BL  $  654%2#"&467&54632#"'"&546762#"&54$2#"&4D_V    73H3).  ".  D򬫊 . !,!T! . $33$ 1.   .P6X3%'&'.546326327>54&#"'&#"6ZGCW#ńbg#WCGZ @C>`9J:vr3H@]aR6}FGlZ.ŁŃ.ZlGF} >FXG`RObEVA>Zo\9w27'7>54/&#"32764/&''7'&'i_.#7BB]_@BBԍB]_@BB i{_.7Bi`.5#j+]BBB@_]BBBBB i{_-87B]^74>2#!"&!!264&"753#.654&@" MNW(kVMcO/9X7\CNO,?iBHK;I,@GdfH#"&'>7>'#53&'.>7632#4.#"3#>3632b2)O'*2'V7   0 $ݦ /-aʙDP$%T) ):#b "L,B   7Gd17;V^(Xw4K,9  %(d2;6 " !### ###,**,||"3 33!#5###3!##535#3!53Xddddd,cdcdd,, dddpdddd"3 33!##535#53!53!#5##735#Xcdcddd,dddedd,,ddddpdp ddL !####53##5##3,*ddddd,| d ddL !####5##3#53#,*Jdddedd,| dd d  !####53!5!!5!!5!,*d,dpd ,|  !###!5!!5!!5!#53,* dpd,d,| LL!2#!"&546!"3!2654&,ԥ5 );;));;Lԥ,;) );;));LL")"&5463!2!"3!2654&%ԣ,A );;));;GM,ԥ;) );;));d LL"463!2#!"&%4&#!"3!26!,ԥ;) );;));d ,ԥA);;) );;LL"#!"&5463!24&#!"3!26!Lԥ,;) );;));Ԣ,);;) );;L!2#!5!2654&#!5!!5p);;) p,Lԥ;));,%276'&!676/#"3!    L . v  XJ L%!"&5463!5./"3!2?5!!5 );;)]],/5d,;));ԥ,$'''!#!"&546;7'#"3!26=az;) );;)vJd,V{);;));zNԥb   $  6$2"&4D_VrrrDVrrrL!! !2!46#36 dd p    d2L!! !2!46#3,'C>K dd, p  d2L ''!2!46#3TFK ddTFk  d2L ''!!2!46#3aaŕԕ ddOabԕ  d2L 7!7!2!46#3ԕEab ddԔaa  d2 ! %xw`w8dL+!#"&546;!3+3LDdddp,>!#"&546;!3'#3 '7BdxddX%{xap,x=2${x`#!#"&546;!3'#3''7'77dgddӪp,g!#"&546;!3!#53## # dpdd,,,p,,,!#"&546;!3/#533 33Znddd,p,n|,L 54&#!"3!265!!Lpd&f !5 5)533#53! !;#735,ppddd,p,ddddD**d/%4&;26+"&5'7373$% v2dd22d22d2RuE5!sdpAdd,dd,dL3%46?5!2!4635!2!5"&5!#!5".L2pK Kp"2KK"jx88 &v& 88 88 &v& 88 LL !%.'!!%354&#!"3!26!!%%!)%!!'!7dd'i;));;),);p,Xp,'WddddbbD);;) );;#bbdd!3?6&/&&'&'7>/.>fgї{4w|~ev- +fg=!/vg|~v1L"@5.#"?>=6 6#!"&=46754>2d|~\ud?, >pmm&RpR&A1)!((! !""!)33/2  dL7!'57##5##5##5#!5}dddddddȖdpddddL 32!4632!464&+"Xd);;d);;;)d);L;));;)D););;)pL'+#!"&5463!2!!3#!#535!#353#1#|D||||,,ddd |||DXdd,dd d,,L'+#!"&5463!2!!#5#3533#!#353#1#|D||||ddddddddd |||D  d,,L##!"&5463!2!!!5#353!5#35|D||||,d, |||DX d,d d,dL#!"&5463!2!! 3-|D|||| ,d, |||DL'#!"&5463!2!!!3264&+!#";|D||||dDd)69&&96) |||DX pTVVTL%)#!"&5463!2!!3#!#5353#335#|D||||,,dddd |||DXdd,dd dpdL#'#!"&5463!2!!5#!3#3#5335#|D||||Dd,,ddqdddd |||Dd pddL#'+!2#!"&546!!#5!##53%#53#%3#!#53||D||,cdcddddddL| |||Ddddd ddd   $  6!!!'57!D_V,dd,DVGddd  $  $  6#5#3##!#53D_Vdd,dddDVGdddddpdA!32654&#".#";!3 33 xx.,,nBUqOd,zxawי kEPr,p,,A >54&#".#";## #X^yx.,,nBUqO,,mdyawי kEPrp,,dLm%!33 33!!'ԪK^K,,Mԛ--y7)%32654'>54&'.#"&#"327!.6Ji 2;{Y^t Ji9/iJ8,K^-2iJ f=ZYqtiJ5XJi-d%!2!5#!463!546;235##!"&= ,); ;),;));;));;)pdd);d);;)ddD);;)L#'+/37;?CGKOSW54&+5#!5##"3!2653#73#73#73#73#3#73#73#73#73#3#73#73#73#73#Ld ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd "/' 7'!'&4762*$/, #**#|$*;O%>'.'&#"327>767>'&'&#"67632#"&'&>767>32EC8fOESkZ(GD0#vF?8!@)'(#Z .C"|Ey&$4I7Z 0$&\4=k6_v[w<C]W$!7GDN9@1*+,#b/W""tCu$'$4B?#>@$$\475be[dL!)1%4&+.+"#"3!26#53"&4624&"2;)37S*)R:. );;));ddȐ>X>>XX);E5+);;;));;dȐȐX>>X>L#32#!"&546;5463!2!54&+"d);;)|);;)dvR,Rv , ;));;)X);RvvRȖJf'/32"&/.546;7>7'&6;2"'267&R::v?zS^Sz?l1 8F8 ( .))GM~ %M+1==1L 3 4&#!"E~o DH.7>7>'>7>76''&'.7  &:4? FFB:8( OV $9DkC@&'GOS3 *gJ. ;4( .MV .nhB8- %>=B'Pd!I,  =CnCSm,U!ٕfm7'"/&47&676 {+oX!N` ~\F/n+We6\eA(_<::(dFHFddjdddddd5d!u,dh"ddF:.adP9'ddddddyJo****VpppppppppppppppBJbNn&fz^Pj<r0z & F | 8 ^ . x  v . 2.f>8N\0D\ bP>x&$f(P BL dDrXxN  4 l !$!R!!!"0"^""##@#j###$$6$`$$%%<%f%%&2&&''D'x'((:(l(()6)|))*.*d**+++,2,|,,---@. j (|  L 8 x6 6   $ $4 $X | 0www.glyphicons.comCopyright 2013 by Jan Kovarik. All rights reserved.GLYPHICONS HalflingsRegular1.001;UKWN;GLYPHICONSHalflings-RegularGLYPHICONS Halflings RegularVersion 1.001;PS 001.001;hotconv 1.0.70;makeotf.lib2.5.58329GLYPHICONSHalflings-RegularJan KovarikJan Kovarikwww.glyphicons.comwww.glyphicons.comwww.glyphicons.comWebfont 1.0Mon Jul 1 05:26:00 20132       !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~glyph1glyph2uni00A0uni2000uni2001uni2002uni2003uni2004uni2005uni2006uni2007uni2008uni2009uni200Auni202Funi205FEurouni2601uni2709uni270FuniE000uniE001uniE002uniE003uniE005uniE006uniE007uniE008uniE009uniE010uniE011uniE012uniE013uniE014uniE015uniE016uniE017uniE018uniE019uniE020uniE021uniE022uniE023uniE024uniE025uniE026uniE027uniE028uniE029uniE030uniE031uniE032uniE034uniE035uniE036uniE037uniE038uniE039uniE040uniE041uniE042uniE043uniE045uniE047uniE048uniE049uniE050uniE051uniE052uniE053uniE054uniE055uniE056uniE057uniE058uniE059uniE060uniE062uniE063uniE064uniE065uniE066uniE067uniE068uniE069uniE070uniE071uniE072uniE073uniE074uniE075uniE076uniE077uniE078uniE079uniE080uniE081uniE082uniE083uniE084uniE085uniE086uniE087uniE088uniE089uniE090uniE091uniE092uniE093uniE094uniE095uniE096uniE097uniE101uniE102uniE103uniE105uniE106uniE107uniE108uniE110uniE111uniE112uniE113uniE114uniE115uniE116uniE117uniE118uniE119uniE120uniE121uniE122uniE124uniE125uniE126uniE127uniE128uniE129uniE130uniE131uniE132uniE133uniE134uniE135uniE137uniE138uniE140uniE141uniE143uniE144uniE145uniE148uniE149uniE150uniE151uniE152uniE153uniE154uniE155uniE156uniE157uniE158uniE159uniE160uniE161uniE162uniE163uniE164uniE165uniE166uniE167uniE168uniE169uniE170uniE171uniE172uniE173uniE174uniE175uniE176uniE177uniE178uniE179uniE180uniE181uniE182uniE183uniE184uniE185uniE186uniE187uniE188uniE189uniE190uniE191uniE192uniE193uniE194uniE195uniE197uniE198uniE199uniE200u1F4BCu1F4C5u1F4CCu1F4CEu1F4F7u1F512u1F514u1F516u1F525u1F527QK(bootstrap-tour-0.10.2/src/docs/assets/fonts/glyphicons-halflings-regular.woff000066400000000000000000000401001246560743700274270ustar00rootroot00000000000000wOFF@@sHFFTMXh+ GDEFt OS/2F`ilcmap~./Vcvt \(gasp`glyfh3[Xhead8,468=hhea8`$ xhmtx8ploca9@maxp;@ .name;`|Ԗpost<RycQwwebf@8K)Q=xc`d``b `b`[@1  xc`fidt! B3.a0b ?k/ 2SxŒHJA x͓?LSQϣ-PBt{ 00K*N\hA4 j`X1YMtѸNNhn]\L|ɯn;}+9J&Dp5#h0qxM ,:bld[g$"qIIȠeX 2!E˒FVSva-hIuQP.{v$!VWryDƸʜ,h1MV֬4:E9]%sy^Ǜ7"Mk6e[lj3e4f|3_a+撹`MLqs֜1'M15^OzQur>{_ӽ(R/]$Iӫ4M@[A3{pnC(qOќq9H'אYBLI7a{ 33=์ zL0)2|LJ=G d2M:_YkyivVv 7iW칟fmuߥGfu쮮Cu~DOiwE42K` pھ? B*xOH|kt&Xgԃ*7{5ch Qwo H(xڵ| `Tչ=wY2m&Lf23@HaQpD@qm ` HQ`_^ԶjUVk+d.;L{9;wη˰L%Ð[2cD&aGy|9#r,\2qXGEqCqb%_*¤712Vd1;PR+9MZM/҄\\ckFEZH ï-{P\a&X _?I!LĢGDXQ1H WubK,UwS+3k\dǹoL@o"{;? aZRd3X_aDd=;jt2s#'Lt<2e )m7Y)W5sϤaV&U$d^\GAUE<|cN3x6b() G#,aq[IXUUX'h D'eģPo3BY+5pCG]}gsbԚm\3jUpϏ4u5stܻ֬f@ZqvT⊹ڽچǴu䷏w:],kK;OJ@7 7g.P6{M_?c>~_n#9|>6 `ID=^6%Yhhg{C`˖-u8}mfpdRτL5C~Q_`,uIgخ wۺifV˗v :KR8#Yfy\W$A Zb?n#qlVfD\U$\UBeX[ 7:W?fVsdKUVaaU#FTHs  ᑊaL6NAy`ٍ S7jչBnff5wFohzכ(x񇀯\{1eeÜ%$x28>юkޠ323m!u'|%t #Wʿ)$}ɑ7ɑhb+*$ P;ϺA2bT>_UV]GtYI4 ` >A<dO>V5f#_x 7ɜXV;d槚*O}@[?}E?~ ؕm#-2eY(\LV1+`r.P$UdD-R]b YDqE~F>{lȮ%nCYЎ8 n ,sE >1ҶSTVJXSa]pk7Ca ~0($؃&1yE{|[C]܁k'ʶM6{V[ p(*l#BjR-Bz]2cF܃>P=cb(/V z^vcCwuxhKHۘۖ1,БFra>0aVi(9VC =s!]k ѡ$Tڙb?\wΥ: xrYP˸.B@DNV`<졒Tc&dgUSI-2 Zdͦ~ .`rqud.Nvu7G*{\Um_7Y&l>:-`}aQ%MwuwEpffdʹyX/A_r7/)G0uIgq$ 7Л2( {Ko )s_r/aW,0Zk]_R~ANuENuUNuގ^x+yIF @M-}/˻}&8z^IQ!pyWzf83Z>Q,|  wJ|nB}ܾ΂ӧaGQ*@zu?|bj&uA/Wo*zH DuK^Kt^cRt{tx0piY}{2J< tnuw@MԟPQI!D\ zj.w9fW!(S &-'e,.qBwzɈ.Ɨ/]!QqS%'‡q0\DMcykƏa}`Ú7,}w<οo_FcLu/=,}YCBc4_y=7v*dxP3$۴"l(h 4)SLjL^Ĕ?wo#z"&k4^YVҺ;sT-oy';<*o-1mEٱ9 K ^ݣXG$ ~ ?>6Y^4ȅZm7RJVhwV #CjP{f^-e~%LDWtslݭAʭXϕy}`ls-NQG 3ngqZ֜~2ԿZبe5.#!L>/ZC=/1t)γf}'\1|Da}ؘ+K10]݅#qmTA~SSp]yJ٨s7B_RH/%G\ Y+iɟ4`A\ aRg`(LcD5Fa1,t JeRFN}N/Wzi`S?gW`Ӭ2?$yI.@w| %1$h$&e)tFziT=&/PBgy >}$0(,+ʉ# D=3oPvd#.%i~Sd__88/O@-LE%# ƎH$Sg+ +??KXAI%,ukǵ{i*~jOp] #lsX"~.Yr2 fn֦Momc_d:6mfz,MH޽ga&pa#.&@ 9VX $j02 Zy׫DKCF)^`o y+\3~~39/CBL_ mw7{fڤZ6hn"!]1T{kӮGPckwo _ ߝpt)'q{nM8ޗB)D޵h j6bzzcWr9Q"gƲP< >Q:eoCg8*WkM+w:qjel{WM&|$Ç=h8jе3.xq6W*̜?zs*1Z^k]W{^85~AyCo`~C_K;ef(F@ig0N ENCIX ȉjf qj!SW_ (so6>T]>UM /n.tZ a stkںz؜_iYpQV[0l(3ĖnM}˱?Yr:S=dz1o^:DzlC1~T @^N9#/} Ǖee1WAB H$:R>b(j 4&='6OCۙ*r{(txldifgCU|zFJvF4s-?C+Cf77SVc !XHB2HW~K1~ lKdG_,˜_Lnlﵧ=aG}*ΤVy4ơdy?wSd O~H۬j-I1b폀;JClh:Eu[-$t Tg=%I0OB\0/i6,@o )f- |;u6(Տ>Uxo )GlڀfI z Tz47;iNjzSx޵`漋sd_U$(䴚yUO41T\R4+0=?#>FJ%S2)m(c}P ~\A炂^5IɓJo8SN.Wf%WzHp{\Х_Ll$+RUzM yGwe&3!%3ʃf~"J@?~8Q8h 1{n|pn*=]`YOͩ K d%eꩢH}X(z+Yb5;,ˬY$2k鲙K76Lux7^;v-I̼yLfcg i]6Y{ڛ;55dT^BXN,ygt.^760}|$dE:G\D0zR7dRilņ\~+l]o7_$6fU5H`v= Գ|~ȑ41ۥo}l394Iʭ={ yqYII wA3FEWpIJ '9Ad@:tơ.fgg[Y(\ֈN?9qd0G*Hp~^EuP1G.]B'xX u5=%ݰfv.lb`.enP|lcJYTwBDu2fP$b$:Ȓ.!A͐At`x'ZߗVlR=ǹ7D+6 `~7/ d ¢Ur?g[:ue{C.`7T,V` <{^S6 4i1"m2%39ξgqL$lfY,_!+Jc .˫ q` ,JoE})臢LX/l~ :@hr*/MBrH*|N+ wsHg %R!,{]X\CG+飩ϳT;`:x.ޏiCzzśl>zF7`Y6j{ARk 2GBߊ^ VuQoKRUp/Q7͙z1[KoG<\/̥ +e5PR%$ƭ߇ĬQH&2U5-+8oyvS~# GPX`rh& te,g(!ZA Hןlx #?66v+Rظ".bop;#qF#oQ\?W|78 M6^?O=/$FYvx"5\mwfͮKqߗ/:ǡlzVE'5caӼj xz1XJ!P0r,?\Ms Y/Mǰ:e= ٍ31k60Z5%4@~3-$ aq[*{m2rՃو^U9mi$lzn.J^^!n {;S\_ N^Ekk^|,W{Sdދ?J@b_m 4হEcЯq(q6l!jZ5,KopoO %b((* g2Q +),{L.m|f+Ol^n_a2yHd Ybg[]'˓#)&% nŋ?.1t >qeYzYXOVOCEջh>ݠga‰99IsSځȂѻ#uBJoSo_Y059´a8ޚVJw>:\gJ,ϝs:\4O#^"':|~阕;b'#pfٚ^&ps.P i90u:{&ܹBz|BcW.Dܥ}|4 ߅#GQc,DI;t, 'wl=޹=6?eAB/a94Ǵz!pL+% ;\I\( C߮W|ȥĮ"{COy:Eq ;;ܭsHށڋ(s1uKOUwh[ qd8VJʄm}{֮& `sίfT-U`|ږAfӖCms:[=:p_Fn>@S;}{s~" ǭ[YrBjΒ vd6qqj2;W[NfKݔ֧+n=yư)5wb]qη&_:Gi;R34沾EpFA0XE>!z‡Jp!@o*tTkїgӍ;U5=ZD1kO!icKI6+.| |{Eqa7h""nhK];cJ޸R`ۡ6 WhJꔉ2]{՚qDRvǡַ~^tw<MBebf)Ј Y­vPKPk%-C(Y;>&jLֿD:#!ETd)c[@OM@TE.$٧ShSIhqz?* ]4S/>'So…0~9 U2˙_nm XGe2\OBȄӳN$(2n(J;gL5FwD/0ˬύHe'8ezCyW JlRB^˥ ᲰJ{sӝTGB]\b2u}cOfC`# w2t)ncꎋQ .^|{ ϨViszĀ:9ua]* Vbt;͡{ = 7ҿ^g_B4gԸw ޾.=FUpa9@9kCAg꿎2k%xwx_0@ݦ G1jRCȜ?6?իMOVf> "~R} ;_q)mrQ5(NOԆİraCpXjCD7sfk̍2^x> 9 Ͼըiro/ @]@]w'F0A(}f–A)+t9(dvLRz:RPG(Ru|:xK&砇B+! W6劖ٝ3.&y~2mQI:X;\;u3KB˟^M)YDqǕSާ^%].)Vezo[YlgSy,Q[WeESkz4=M2̪ (DWP j{=ǁ?@?̛HIw`נA`%]8_=8DePHzX#!M:D=ILXl֮hۼ;f U' CSHԷxBAi٢YcO7Kvτ>2z"gvtf92_d{otVv} LaTe:Qm"s(j3\JViNC趢=1qg?Wa ;;I: r>YUN-'/~k@vh(&g3dH!`M2$6uBsFR7m~|S;k`koR{{PF;L-hc ``'AճIP0yFDI棴"~ gWz|DČ0F uM3cq3hulPedUA؊纍Q:q YvA"^\`\,pj& Zk;ӫFˣ]? %Y@4yra[^!"wzrE56GVTH,t{|{u*?ϊ rX 6d:i? R[Œ3UӇG̖ȺnSTC}s}}rycNB uڴR=BzʠyIP2y%Ph x?Ixz+9+\Y-NomRVmM2yUi 7˰4褫-H }Ŕ|%=>p9=6|hm5ip8.[C,C56wh,TIn-y%&w$Wu$@Ð!rTrw~=%:Wnc,hO4㬼hI+=8ӊ>k BM>.֚`;qJ[=eC(6˳V tH[Hq6B,"gJΛ"fEz 5MݟRƇ]2g&]R7jCdƲVT|w{^eG0 !L}9( ܱKZ!}6v6+kL\7:}n_nhgt:qM2xc`d```dpdҘ11+<oVer9@xc`d`` o2] 0xc L= q100܄@> 9,3|@,Q ò@U+ 4 Ќ9P=>͂/=0}LHjLH+b6T/Ll _E (e@bF;l ͌ƂW>H|%an= B0aC(>X"ϬPqV8>1,N0yL(nI$qT6K?tP?D/ t xc``Ђ09/RN^I/0bacc:Ƭ%eV8_llYl=l؞۰b?Àc'g . 8I\k>pqWp/~#SsWψo? \!OPP{\ISHt"rBQQ; kbjb=b_Ug`А%C'I.I' {X|IsIH~##!"S$!I\1yy?u b & 9 K(|STQ RlSܧM@)Niee,){ߨȨ$LSʡj:GZuu = V94>iihnեuBIA{N&bMkcyi@.xڭN@O F$pƦ ʸh] BJl>7.\> aD,ff=̝[/hKa u^qxRE'peO"=*BB{S#+Ƣ>x8N>UU+,. Cv{SھYZ؄z 0$VH5P9\w |!_j\k\/PB<8@/u6sq͈8%LK֒1O/3/?o+0FN=|dk*I;ڠ2@U껃 khѵIO3*N&rdr/5>d˯aݎgTP4eVYa" zzZ2.:{,z:?~m{xmՒUE^IHwwҍ'CNI ,[pww!x k]]g3U_Mk\kV_ߚܚc"X%XXLae9o J*jZ:zlFl&lfllVl6 J*jؖ؞ؙؑLc]3̮þ¡ñɜtf0S9Yl03Ǚgs28 X\¥\\\\õ\­ý<<<£<<<<ó<˼«, -=>#>>3> +;~'~~7~8}32b-[t+vܩ-[ Ơ37}DG}DG}/{y؉؉؋؋^aW+ {^acccccccccS)픾Sz|+W|Oe=^eW۩vj;Nmi|Wck5{^^^^^^^^^^^^^^^^^^oЋ;::d3;:9z9z]9:ߔqʱ{~7~7~7=GqtGqtGqtGqtGqtGqtGqtGqtG۳to?q$崡 7J1r0` -|QK(bootstrap-tour-0.10.2/src/docs/assets/img/000077500000000000000000000000001246560743700204115ustar00rootroot00000000000000bootstrap-tour-0.10.2/src/docs/assets/img/apple-touch-icon-144-precomposed.png000066400000000000000000000067351246560743700271250ustar00rootroot00000000000000PNG  IHDRF IDATxNaNaY7cVx hT܆HH| 1]uaJs: ⷒ89y ug n8H8EC^OnP ˜jj<9io L Fe/:P-C6^D!:9զIS5-+^a!ƒJ1}3}'KPM@wdFPz2&8s|+MVj,/$p, B;OχP>['Pٔ@(iAE]ׅ0gXاO5H pc(f;r!mq#_@=+jt \Ȋn& ;nヺx(ye%V"2^t(<*sE+~ [ 4ukQ̫\WJ #![4Qe]D]ز WZ IF0-QNFo=I q& GB}0A]D] GEv 5k@"y~TuƷXܣxXP=آ.CS0RoV8G #;uʺ?B5{,=k c]WnL85I[$J"s7$2"DA4*$B `@4;d(h RIƔ`,]KPw}Ubɪ޻$sƺg]PB V% ..Ye+?i9XX&)GnЧL3_$ OR,HɖA]t]x,%%azԢólaKmb]Pw,օuɑI α..dnbĿ˅E8_?5w<{yv>3Z]XY )l]@`b%Ɩ .( PX K>N]IuAYj5/#iU maP8*0 %k@8W>H.( 0!B{9QA${ uP&[ (8qN;.( 0>B}yqFuAa 3'׺0 ]k@md.(8BH= Ϻ0KgEuqХ3 .uO_[]PB{.y{gIj;qų6Z^dmkœoQV.CAM'"a/;f/W?5suqй*Z5@wFqHN7Y{WWD ,^EdHgg_xRҩ /\%< BH]UwF/m1iO_Iu !!흑@B€,@ZPhi"R0e^R9@]3H.HQug$%T< HD Q LR ī?uYXr_uY3Hsg4&ٸz,CaIh/6iNNӼե.ug$)Ψoi| -L-ڝQ 3i~<d ug$$_kҜ{Kv׀3H~g4|sL}~w) ⮛P`wFyMȒxu꘥*uAa (TYgYᏧSe_2Ƥ$OD `gT-F3g 0 3JYҞ-v %;׀B3x0Ou'XdҞ]Ki$@I 3BҞ PXwFRdK.Phtg@AF (@"uAa HJ #+H]\wg_CA ,GYsSK$' HϺsDL yaVBa Ăh) 0؝@> ;3s>,CAh_`7”euqg$'b4vFH%;mrBY|쌖,\/*O"UD+ dKHz֮,V\ Ewg$!@]Ԭ[+=G{buAzD8°buAa{0;8gcSD (6;K6Ȁ@Q>=8\.,YwFйꂴB 0;'A>wx p0;8~.( BnYY5uq.(Lg(0 %Ϻ.PaAb="ڝQO :AsYhAZSwFyDyæIAy Ѻ4;1c .( BeqPDIdY?ß4 %3Ma4ߦv]ۀ(.»Ψ0)uab] %BluAb]rb$cb]b]nQԺQf..YMC,ɕXX;HM>bw IJ,uu[`Y uu?iY-(uuɑRM-b]b]rbau]b]0L!*O_1 8oz!SwuuΤi‚4f*c]dd _ %m]b]|δ^ ." p) X. Pt@',Ac<֥ 3^2+c]ekfJA9 ,'!@PĔƺ"O)S@ҜY\u U2iX&(fs9T2_ƺxK9ϼˬcF%S]AOIENDB`bootstrap-tour-0.10.2/src/docs/assets/img/favicon.png000066400000000000000000000015671246560743700225550ustar00rootroot00000000000000PNG  IHDR szz>IDATxKQd:niΨZfeTZjZ`Qd"T EKA ГY! Pxr/:ysƔgw%4+5P9(evR>+%6~TАZ׈q;Cz8[<9k1Lj<:Z0/dhob1R JZy;A-Nېz \v1$vVWx{ MPLwdy]S /rI=+Wign^Xnb=$'Ȏ:V>>Sߧ \Fܽ5 SߦAFY̐pr  G!Kz*몺AI9QmQ0Jnccأa1L3یmsЧ_ŌtlFчAX(,CH_?~>5 E"A1.\bb*H"!; V>y- LI|v|Wnݵ;0/G^-&G C{AP0G <J$C}-A!'ZvUu}F>S̉1R 5N&.#Cl-"v+ ,|v*vW/ ?= WrEA &?60AaU)~l;[ƚz$ !%D` U ' C^V nnjTL =FGoǯ2x (,ȯFc đB"dhlG1B!%@lX2添̃en2q;{1ƅGƼv D`ehv6?7<i0&د[M?pAuCW`]byܛݙGDM?Vޔ3={5g-wc(;ܙO;c=Z`rҚ6爆adL;`u4쑶MM%[ g4VX%n4-<=Lk GT} 3n˝VѥcXo2'n+I1YLKzG? * N`ŐRV _./ۤK޸eVKK+23Cگȿ!0BAeVPh}қ |XE1L[ /IÄf7ZD6-mPX y"X"a ]X+`4b`V0$ ,X1*5I:aL Ƌpe ex.X! #_0Eɫ6/J^ .-DYh@|*gQʰoj!chx^CqOȃ; / :q富ҠSwra#tV(]շqy0V V~ {_dPWnUdPYIA'Wa/Cd;KNj Uy =3nh!zJSaLM-*W3sAϬd=I"\&KiJuPz`<Zwu-+gK`'ӹz5)+W%pF3D ʀbh X?|THiZ&~z}}M/>5moGD)(?]u1()0قپ<ԺCB;|`B+` S^yt߯¸~AnA ZuF?'BPcp_V錜y0\Մ=XI֝(3 g BF& R2i@`3V!#D܌JJjgnpFy*d dLC~A`3ʋV!/8Xx} : n y7M)ܹ;_H\H0 h-| 16}[پ~["ſ(LQ_CvCWW_f^f^r nѫ׫xh \q*)4+IA'zC ЭrX!Bk Ь#*KFZIVIVџS7nUd+Pc{TuTuǫx:'H(<.yPYټ$}ac6/j9Ǝ9': c*' VY$y$= ; 9 ?z:zP-Pl>`z\GD؇D V(X-Cmڜ % ?ꘆnQ4~V2o%3dV2 M&EGNJ_7V/bUXeayS>Īe_q3fUq3HEZfUmFXUd|B[gXU)#*o`;^c$4ݾn?c}T;Ъ0% а%yt S x]atnr)XWe0 مQ'@W3o7b-OWsӲU~"q42'%tiʔ;/M~N0:7p p^9]:\ȕ4/ jWІbi zi28Xe&rJ L!jZ ʵUӖI `*с#@!\~|N*`Uv"5V!7636ɺd+lŒ09 zBc-TˈI.X*'k{rԶ}7=ݓKV bMhE*m*|e6VI`Ձ)6ƨ6xz\-q SF5SXAoVM'$Yy5DW*(X$YVd1(jdGQQ$+X 8]&<ɪ:Vsl*s:]d%A+HsbϦb8zVN׽餚z}SbYIV xSfmmhuT+q` VA' hzn<뵮 kFh+-jFoUҡJwZ'Y#ZޓIHMvV}kLlo($kt?Y[MJ>y4~ںO'Ŋ*K&Ye8&_{uN/C/Cܪ2ĭ2^JkT[` VIV ٭xȻuugjěR9MirZ#'.h-?'_'s6d_Gݾz[X2j9,y`1=3X? k4hGaY[qf7&[d0}|Q5/|1ĔRʑ>|Hr_9𕣗f>e6]2d,;~ S_}ګϗOy;*;!4pGϋUy%%tR"tWN=!9 o:L2 Ī8H._sIo@ccq>no #Vң xs|(@tTbUrTA!T#m` V`bW9*9^:'1#4~$GBiH(w$TacUac>l9l:lر<Ǝcw0:z3>Mͧ V?.Ə88:<^{x>;<ei`xI[iVx[<mG7j%d}e+$kN+djR_U^cղ/*AVx/wCd|߁iUdŭ^4 㡦 ܪ0ouQס'F7Fƚn۱`W;w O [?+z֒ S~v=dŭŐݿ땣ٮٮ$\&|[jj7BWJ :|R t#t>)BVo!-ɺ#*KFZIVIVџS7nUd+Pc{TuTuǫx:'H(<.yPYټ$}ac6/j9Ǝ9': c*' VY$y$= ; 9 ?z:zP-Pl>`z\GD؇D V(X-Cmڜ % ?ꘆnQ4~V2o%3dV2 M&EGNJ_7V/bUXeayS>Īe_q3fUq3HEZfUmFXUd|B[gXU)#*o`;^c$4ݾn?c}T;Ъ0% а%yt S x]atnr)XWe0 مQ'@W3o7b-OWsӲU~"q42'%tiʔ;/M~N0:7p p^9]:\ȕ4/ jWІbi zi28Xe&rJ L!jZ ʵUӖI `*с#@!\~|N*`Uv"5V!7636ɺd+lŒ09 zBc-TˈI.X*'k{rԶ}7=ݓKV bMhE*m*|e6VI`Ձ)6ƨ6xz\-q SF5SXAoVM'$Yy5DW*(X$YVd1(jdGQQ$+X 8]&<ɪ:Vsl*s:]d%A+HsbϦb8zVN׽餚z}SbYIV xSfmmhuT+q` VA' hzn<뵮 kFh+-jFoUҡJwZ'Y#ZޓIHMvV}kLlo($ktDDDIENDB`bootstrap-tour-0.10.2/src/docs/assets/js/000077500000000000000000000000001246560743700202515ustar00rootroot00000000000000bootstrap-tour-0.10.2/src/docs/assets/vendor/000077500000000000000000000000001246560743700211325ustar00rootroot00000000000000bootstrap-tour-0.10.2/src/docs/assets/vendor/jquery.smoothscroll.js000066400000000000000000000030011246560743700255300ustar00rootroot00000000000000/*! 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));bootstrap-tour-0.10.2/src/docs/assets/vendor/pygments-manni.css000066400000000000000000000056751246560743700246270ustar00rootroot00000000000000.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; } bootstrap-tour-0.10.2/src/docs/index.html000066400000000000000000000072261246560743700203370ustar00rootroot00000000000000--- layout: default title: Bootstrap Tour slug: home ---

Add the dependencies

If you are using Bootstrap, include bootstrap-tour.min.css and bootstrap-tour.min.js:

{% highlight html %} ... {% endhighlight %}

Otherwise, just include bootstrap-tour-standalone.min.css and bootstrap-tour-standalone.min.js:

{% highlight html %} ... {% endhighlight %}

Setup your tour:

{% 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 %}

Do you want to do more? Read the full documentation.

Code licensed under the Apache License v2.0.
Documentation licensed under CC BY 3.0.

bootstrap-tour-0.10.2/src/less/000077500000000000000000000000001246560743700163515ustar00rootroot00000000000000bootstrap-tour-0.10.2/src/less/bootstrap-tour-standalone.less000066400000000000000000000007671246560743700244050ustar00rootroot00000000000000/*! * 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 @bootstrap-path: "../../bower_components/bootstrap/less/"; @import "@{bootstrap-path}variables.less"; @import "@{bootstrap-path}mixins.less"; @import "@{bootstrap-path}buttons.less"; @import "@{bootstrap-path}button-groups.less"; @import "@{bootstrap-path}popovers.less"; @import "bootstrap-tour.less"; bootstrap-tour-0.10.2/src/less/bootstrap-tour.less000066400000000000000000000015161246560743700222500ustar00rootroot00000000000000.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; } } } bootstrap-tour-0.10.2/test/000077500000000000000000000000001246560743700155735ustar00rootroot00000000000000bootstrap-tour-0.10.2/test/bootstrap-tour.js000066400000000000000000000664711246560743700211530ustar00rootroot00000000000000/* ======================================================================== * 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: '', 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: '

', 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('
').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, ".popover.tour-" + this._options.name + " *[data-role='next']", (function(_this) { 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 = $('
', { "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 = $('
', { "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);