├── .babelrc ├── .gitignore ├── .npmignore ├── README.md ├── bower.json ├── dist ├── foundation.joyride.css ├── foundation.joyride.js ├── foundation.joyride.min.css ├── foundation.joyride.min.js ├── solo.joyride.css ├── solo.joyride.js ├── solo.joyride.min.css └── solo.joyride.min.js ├── gulp ├── config.js ├── css.js ├── javascript.js ├── publish.js └── scss.js ├── gulpfile.js ├── js └── joyride.js ├── package.json ├── scss ├── foundation_dependencies.scss └── joyride.scss └── test ├── javascript ├── index.html ├── joyride.js └── lib │ ├── chai-jquery.js │ ├── chai.js │ ├── mocha.css │ └── mocha.js └── visual ├── index.html ├── standalone.html └── umd.html /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "transform-es2015-arrow-functions", 4 | "transform-es2015-block-scoped-functions", 5 | "transform-es2015-block-scoping", 6 | "transform-es2015-classes", 7 | "transform-es2015-destructuring", 8 | "transform-es2015-template-literals", 9 | "transform-es2015-parameters", 10 | "transform-es2015-shorthand-properties", 11 | "transform-es2015-spread", 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .git 2 | .sass-cache 3 | node_modules 4 | npm-debug.log 5 | _build 6 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .sass-cache 2 | _build 3 | bower_components 4 | gulp 5 | bower.json 6 | composer.json 7 | CONTRIBUTING.md 8 | gulpfile.js 9 | test 10 | .editorconfig 11 | .versions 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Joyride 2 | Joyride is an easy to configure site tour wizard for [Foundation for Sites](https://github.com/zurb/foundation-sites). 3 | 4 | ## Demo 5 | You can try out Joyride on the [Demo Page](http://zurb.github.io/joyride/). 6 | 7 | ## Installation 8 | To install Joyride you can either use NPM ([NPM repository](https://www.npmjs.com/package/foundation-joyride)) or download the files directly. 9 | 10 | * `npm start` - Calls the build process and opens the demo in your browser. 11 | * `npm test` - Runs the JavaScript tests. 12 | * `npm run test:javascript` - Runs tests for JavaScript with Mocha using PhantomJS. 13 | * `npm run test:visual` - Runs visual tests/live demos. 14 | 15 | 16 | ## Usage 17 | All versions of joyride depend on jQuery and [what-input](https://github.com/ten1seven/what-input). While jQuery is mandatory, what-input is used for styling purposes and not necessary for joyride to work. 18 | 19 | Regardless of the way you use Joyride, you need to initialize it like all Foundation plugins by calling: 20 | 21 | ```js 22 | $(document).foundation(); 23 | ``` 24 | 25 | The following HTML is an example on how to use Joyride. You can also have a look at the visual test cases in the `test/visual/` folder. 26 | 27 | ```html 28 |
    29 |
  1. 30 |

    This is the default one without settings

    31 |
  2. 32 |
  3. 33 |

    This one isn't closable

    34 |
  4. 35 |
  5. 36 |

    If no target is specified, you create a modal.

    37 |
  6. 38 |
  7. 39 |

    Your ride ends here!

    40 |

    41 | 42 |

    43 |
  8. 44 |
45 | ``` 46 | 47 | ### Foundation plugin 48 | Originally, Joyride is a plugin for Foundation for Sites and leaverages existing plugins and functionalities of the framework. 49 | To use Joyride with Foundation, just include the files into your page right after the Foundation files. Then follow the example above to create the ride. 50 | 51 | ### Standalone plugin 52 | To make Joyride available for a broader amount of users, it is also available as a standalone plugin. All relevant Foundation functionalities are bundled with the Joyride files, so Joyride can still benefit from them. 53 | To use Joyride with Foundation, just include the files into your page right and follow the example above to create the ride. 54 | 55 | ### Using script loader 56 | Joyride can be used by including its files via HTML-tags and also the most popular script loaders, such as RequireJS. This is done by leveraging UMD. 57 | 58 | ## Testing 59 | 60 | * `npm run test:javascript` to run JavaScript tests with Mocha using PhantomJS. 61 | * `npm run test:visual` to run visual regression tests. 62 | 63 | ## Contributing 64 | 65 | Check out our [contributing guide](http://foundation.zurb.com/develop/contribute.html) to learn how you can contribute to this plugin. You can also browse the [Help Wanted](https://github.com/zurb/joyride/labels/help%20wanted) tag in our issue tracker to find things to do. 66 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "foundation-joyride", 3 | "version": "3.0.0", 4 | "main": [ 5 | "dist/foundation.joyride.css", 6 | "dist/foundation.joyride.js" 7 | ], 8 | "ignore": [ 9 | "gulp", 10 | "test", 11 | "CONTRIBUTING.md", 12 | "gulpfile.js", 13 | "package.js", 14 | "package.json", 15 | ".npm", 16 | ".gitignore", 17 | ".npmignore", 18 | ".versions", 19 | "_build", 20 | ".sass-cache" 21 | ], 22 | "dependencies": { 23 | "jquery": "~2.2.0", 24 | "what-input": "~2.0.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /dist/foundation.joyride.css: -------------------------------------------------------------------------------- 1 | [data-joyride] { 2 | display: none; } 3 | 4 | .tooltip.joyride, 5 | .reveal.joyride { 6 | font-size: 100%; 7 | min-width: 20rem; 8 | padding: 0.5em; } 9 | .tooltip.joyride .close, 10 | .reveal.joyride .close { 11 | float: right; } 12 | .tooltip.joyride .joyride-buttons, 13 | .reveal.joyride .joyride-buttons { 14 | text-align: center; } 15 | .tooltip.joyride .joyride-buttons button, 16 | .reveal.joyride .joyride-buttons button { 17 | margin: 0 0.5em; } 18 | 19 | [data-whatinput='mouse'] .joyride { 20 | outline: 0; } 21 | -------------------------------------------------------------------------------- /dist/foundation.joyride.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /******************************************* 3 | * * 4 | * This Ride was created by Marius Olbertz * 5 | * Please thank Marius on GitHub /owlbertz * 6 | * or the web http://www.mariusolbertz.de/ * 7 | * * 8 | ******************************************/ 9 | 10 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 11 | 12 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 13 | 14 | !function (root, factory) { 15 | if (typeof define === 'function' && define.amd) { 16 | // AMD 17 | define(['jquery', 'foundation'], factory); 18 | } else if (typeof exports === 'object') { 19 | // Node, CommonJS-like 20 | module.exports = factory(require('jquery')); 21 | } else { 22 | // Browser globals (root is window) 23 | root.returnExports = factory(root.jQuery); 24 | } 25 | }(this, function ($) { 26 | /** 27 | * Joyride module. 28 | * @module foundation.joyride 29 | * @requires foundation.util.keyboard 30 | * @requires foundation.Tooltip 31 | * @requires foundation.Reveal 32 | */ 33 | var Joyride = function () { 34 | /** 35 | * Creates a new instance of Joyride. 36 | * @class 37 | * @param {jQuery} element - jQuery object (list) to be used as the structure. 38 | * @param {Object} options - object to extend the default configuration. 39 | */ 40 | 41 | function Joyride(element, options) { 42 | _classCallCheck(this, Joyride); 43 | 44 | this.$element = element; 45 | this.options = $.extend({}, Joyride.defaults, this.$element.data(), options); 46 | this._init(); 47 | 48 | Foundation.registerPlugin(this, 'Joyride'); 49 | Foundation.Keyboard.register('Joyride', { 50 | 'ltr': { 51 | 'ARROW_RIGHT': 'next', 52 | 'ARROW_LEFT': 'previous', 53 | 'ESCAPE': 'close' 54 | }, 55 | 'rtl': { 56 | 'ARROW_RIGHT': 'previous', 57 | 'ARROW_LEFT': 'next' 58 | } 59 | }); 60 | } 61 | 62 | /** 63 | * Initializes the joyride by rendering required markup 64 | * @private 65 | */ 66 | 67 | 68 | _createClass(Joyride, [{ 69 | key: '_init', 70 | value: function _init() { 71 | this.id = this.$element.attr('id') || Foundation.GetYoDigits(6, 'joyride'); 72 | this.current = 0; 73 | this.$items = $([]); // initialize empty collection 74 | this.structure = this._parseList(); 75 | this._render(this.structure); 76 | this._events(); 77 | 78 | if (this.options.autostart) { 79 | this.start(); 80 | } 81 | } 82 | 83 | /** 84 | * Parses the list of the instance, stored in $element. 85 | * @private 86 | * @return {Array} structure 87 | */ 88 | 89 | }, { 90 | key: '_parseList', 91 | value: function _parseList() { 92 | var structure = []; 93 | this.$element.find('li').each(function (i) { 94 | var item = $.extend({}, { 95 | text: $(this).html(), 96 | $target: $($(this).data('target')), 97 | isModal: !!!$($(this).data('target')).length, 98 | closable: Joyride.defaults.closable 99 | }, $(this).data()); 100 | structure.push(item); 101 | }); 102 | return structure; 103 | } 104 | 105 | /** 106 | * Creates the markup for the items 107 | * @private 108 | * @param {Array} structure the joyride's structure from _parseList 109 | * @return {Object} markup jQuery representation of the generated markup 110 | */ 111 | 112 | }, { 113 | key: '_render', 114 | value: function _render(structure) { 115 | for (var s in structure) { 116 | var options = $.extend({}, this.options, structure[s]), 117 | // if specific item has config, this should overwrite global settings 118 | $item; 119 | 120 | if (options.$target.length) { 121 | // target element exists, create tooltip 122 | var tooltip = new Foundation.Tooltip(structure[s].$target, { 123 | positionClass: options.position, 124 | disableHover: true, 125 | clickOpen: false, 126 | tooltipClass: 'tooltip joyride', 127 | triggerClass: '', 128 | hOffset: this.options.hOffset, 129 | vOffset: this.options.vOffset, 130 | showOn: 'all' // to avoid conflicts with standalone version when MQs are not set up properly. Should be somewhat rewritten 131 | }); 132 | this.structure[s].item = tooltip; 133 | $item = tooltip.template; 134 | } else { 135 | // not target, create modal with Reveal 136 | var modal = new Foundation.Reveal($('
').appendTo($('body'))); 137 | this.structure[s].item = modal; 138 | $item = modal.$element; 139 | } 140 | $item.attr({ 141 | 'data-index': s, 142 | 'data-joyride-for': structure[s].target 143 | }).html(structure[s].text); 144 | if (options.keyboardAccess) { 145 | $item.attr('tabindex', '-1'); 146 | } 147 | 148 | this.$items = this.$items.add($item); 149 | 150 | // add buttons 151 | if (structure[s].nextText || options.showNext && s < structure.length - 1 || structure[s].prevText || options.showPrev && s > 0) { 152 | var $buttons = $('
'); 153 | if (structure[s].prevText || options.showPrev && s > 0) { 154 | $buttons.append($(this.options.prevButton).text(options.prevText)); 155 | } 156 | if (structure[s].nextText || options.showNext && s < structure.length - 1) { 157 | $buttons.append($(this.options.nextButton).text(options.nextText)); 158 | } 159 | $item.append($buttons); 160 | } 161 | 162 | // add close button 163 | if (options.closable) { 164 | var $close = $(this.options.closeButton); 165 | $close.find('.show-for-sr').text(this.options.closeText); 166 | $item.prepend($close); 167 | } 168 | } 169 | } 170 | 171 | /** 172 | * Shows the item with the given index 173 | * @private 174 | * @param {Number} index of the item to be displayed 175 | */ 176 | 177 | }, { 178 | key: '_showItem', 179 | value: function _showItem(index) { 180 | if (this.structure[index].isModal) { 181 | this.structure[index].item.open(); 182 | } else { 183 | this.structure[index].item.show(); 184 | } 185 | // scroll target into view if target exists 186 | if (this.structure[index].$target.length) { 187 | $('html, body').stop().animate({ 188 | 'scrollTop': Math.max(0, this.$items.eq(index).offset().top - this.options.scrollOffset) 189 | }, this.options.scrollSpeed); 190 | } 191 | if (this.options.keyboardAccess) { 192 | this.$items.eq(index).focus(); 193 | } 194 | this.current = index; 195 | } 196 | 197 | /** 198 | * Hides the item with the given index 199 | * @private 200 | * @param {Number} index of the item to be hidden 201 | */ 202 | 203 | }, { 204 | key: '_hideItem', 205 | value: function _hideItem(index) { 206 | if (this.structure[index].isModal) { 207 | this.structure[index].item.close(); 208 | } else { 209 | this.structure[index].item.hide(); 210 | } 211 | } 212 | 213 | /** 214 | * Hides all items 215 | * @private 216 | */ 217 | 218 | }, { 219 | key: '_hideAll', 220 | value: function _hideAll() { 221 | for (var s in this.structure) { 222 | this._hideItem(s); 223 | } 224 | } 225 | 226 | /** 227 | * Shows the next item in the ride 228 | * @private 229 | */ 230 | 231 | }, { 232 | key: 'showNext', 233 | value: function showNext() { 234 | this._hideItem(this.current); 235 | this._showItem(this.current + 1); 236 | } 237 | 238 | /** 239 | * Shows the previous item in the ride 240 | * @private 241 | */ 242 | 243 | }, { 244 | key: 'showPrev', 245 | value: function showPrev() { 246 | this._hideItem(this.current); 247 | this._showItem(this.current - 1); 248 | } 249 | 250 | /** 251 | * Starts the ride 252 | * @private 253 | * @return {Number} index - the index where to start, 0 by default 254 | */ 255 | 256 | }, { 257 | key: 'start', 258 | value: function start(index) { 259 | var index = index || 0; 260 | this._hideAll(); 261 | this._showItem(index); 262 | } 263 | 264 | /** 265 | * Adds event handlers for the modal. 266 | * @private 267 | */ 268 | 269 | }, { 270 | key: '_events', 271 | value: function _events() { 272 | var _this = this; 273 | $('[data-joyride-start="#' + _this.id + '"]').click(function () { 274 | _this.start(); 275 | }); 276 | 277 | this.$items.on('click.zf.joyride', '[data-joyride-next]', function (e) { 278 | _this.showNext(); 279 | }).on('click.zf.joyride', '[data-joyride-prev]', function (e) { 280 | _this.showPrev(); 281 | }).on('click.zf.joyride', '[data-joyride-close]', function (e) { 282 | e.preventDefault(); 283 | if (_this.structure[_this.current].closable) { 284 | _this._hideItem(_this.current); 285 | } 286 | }).on('keydown.zf.joyride', function (e) { 287 | var $element = $(this); 288 | Foundation.Keyboard.handleKey(e, 'Joyride', { 289 | next: function () { 290 | if ($element.data('index') < _this.structure.length - 1) { 291 | _this.showNext(); 292 | } 293 | }, 294 | previous: function () { 295 | if ($element.data('index') > 0) { 296 | _this.showPrev(); 297 | } 298 | }, 299 | close: function () { 300 | if (_this.structure[_this.current].closable) { 301 | _this._hideItem(_this.current); 302 | } 303 | }, 304 | handled: function () { 305 | e.preventDefault(); 306 | } 307 | }); 308 | }); 309 | } 310 | 311 | /** 312 | * Destroys an instance of a Joyride. 313 | * @fires Joyride#destroyed 314 | */ 315 | 316 | }, { 317 | key: 'destroy', 318 | value: function destroy() { 319 | this.$element.hide(); 320 | 321 | for (var s in this.structure) { 322 | this.structure[s].item.destroy(); 323 | } 324 | 325 | /** 326 | * Fires when the plugin has been destroyed. 327 | * @event Joyride#destroyed 328 | */ 329 | this.$element.trigger('destroyed.zf.joyride'); 330 | 331 | Foundation.unregisterPlugin(this); 332 | } 333 | }]); 334 | 335 | return Joyride; 336 | }(); 337 | 338 | Joyride.defaults = { 339 | /** 340 | * Autostart the joyride on page load. 341 | * @option 342 | * @example false 343 | */ 344 | autostart: false, 345 | /** 346 | * Speed with which the page scrolls to the next stop. 347 | * @option 348 | * @example 1000 349 | */ 350 | scrollSpeed: 1000, 351 | /** 352 | * Enable navigation via keyboard. 353 | * @option 354 | * @example true 355 | */ 356 | keyboardAccess: true, 357 | /** 358 | * If the joyride elements should be closable. 359 | * @option 360 | * @example true 361 | */ 362 | closable: true, 363 | /** 364 | * Text for the next button. 365 | * @option 366 | * @example 'Next' 367 | */ 368 | nextText: 'Next', 369 | /** 370 | * Text for the previous button. 371 | * @option 372 | * @example 'Previous' 373 | */ 374 | prevText: 'Previous', 375 | /** 376 | * Text for the close button (for accessibility purposes). 377 | * @option 378 | * @example 'Close' 379 | */ 380 | closeText: 'Close', 381 | /** 382 | * Whether to show next button. 383 | * @option 384 | * @example true 385 | */ 386 | showNext: true, 387 | /** 388 | * Whether to show previous button. 389 | * @option 390 | * @example true 391 | */ 392 | showPrev: true, 393 | /** 394 | * Vertical offset for tooltips (see tooltip plugin configuration). 395 | * @option 396 | * @example true 397 | */ 398 | vOffset: 10, 399 | /** 400 | * Horizontal offset for tooltips (see tooltip plugin configuration). 401 | * @option 402 | * @example true 403 | */ 404 | hOffset: 12, 405 | /** 406 | * Offset while scrolling the window. 407 | * @option 408 | * @example 50 409 | */ 410 | scrollOffset: 50, 411 | /** 412 | * Position of the tooltips (see tooltip plugin configuration). 413 | * @option 414 | * @example true 415 | */ 416 | position: 'top center', 417 | /** 418 | * Templates for the close button. 419 | * @option 420 | * @example '' 421 | */ 422 | closeButton: '', 423 | /** 424 | * Templates for the next button. 425 | * @option 426 | * @example '' 427 | */ 428 | nextButton: '', 429 | /** 430 | * Templates for the pevious button. 431 | * @option 432 | * @example '' 433 | */ 434 | prevButton: '' 435 | }; 436 | 437 | // Window exports 438 | Foundation.plugin(Joyride, 'Joyride'); 439 | 440 | return Joyride; 441 | }); 442 | -------------------------------------------------------------------------------- /dist/foundation.joyride.min.css: -------------------------------------------------------------------------------- 1 | [data-joyride]{display:none}.reveal.joyride,.tooltip.joyride{font-size:100%;min-width:20rem;padding:.5em}.reveal.joyride .close,.tooltip.joyride .close{float:right}.reveal.joyride .joyride-buttons,.tooltip.joyride .joyride-buttons{text-align:center}.reveal.joyride .joyride-buttons button,.tooltip.joyride .joyride-buttons button{margin:0 .5em}[data-whatinput=mouse] .joyride{outline:0} -------------------------------------------------------------------------------- /dist/foundation.joyride.min.js: -------------------------------------------------------------------------------- 1 | "use strict";function _classCallCheck(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var _createClass=function(){function t(t,e){for(var s=0;s').appendTo(t("body")));this.structure[s].item=r,i=r.$element}if(i.attr({"data-index":s,"data-joyride-for":e[s].target}).html(e[s].text),o.keyboardAccess&&i.attr("tabindex","-1"),this.$items=this.$items.add(i),e[s].nextText||o.showNext&&s0){var a=t('
');(e[s].prevText||o.showPrev&&s>0)&&a.append(t(this.options.prevButton).text(o.prevText)),(e[s].nextText||o.showNext&&s0&&e.showPrev()},close:function(){e.structure[e.current].closable&&e._hideItem(e.current)},handled:function(){s.preventDefault()}})})}},{key:"destroy",value:function(){this.$element.hide();for(var t in this.structure)this.structure[t].item.destroy();this.$element.trigger("destroyed.zf.joyride"),Foundation.unregisterPlugin(this)}}]),e}();return e.defaults={autostart:!1,scrollSpeed:1e3,keyboardAccess:!0,closable:!0,nextText:"Next",prevText:"Previous",closeText:"Close",showNext:!0,showPrev:!0,vOffset:10,hOffset:12,scrollOffset:50,position:"top center",closeButton:'',nextButton:'',prevButton:''},Foundation.plugin(e,"Joyride"),e}); -------------------------------------------------------------------------------- /dist/solo.joyride.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Import dependency SASS files that are needed. 3 | * 4 | * Based on: 5 | * Foundation for Sites by ZURB 6 | * foundation.zurb.com 7 | * Licensed under MIT Open Source 8 | */ 9 | .hide { 10 | display: none !important; } 11 | 12 | .invisible { 13 | visibility: hidden; } 14 | 15 | @media screen and (max-width: 39.9375em) { 16 | .hide-for-small-only { 17 | display: none !important; } } 18 | 19 | @media screen and (max-width: 0em), screen and (min-width: 40em) { 20 | .show-for-small-only { 21 | display: none !important; } } 22 | 23 | @media screen and (min-width: 40em) { 24 | .hide-for-medium { 25 | display: none !important; } } 26 | 27 | @media screen and (max-width: 39.9375em) { 28 | .show-for-medium { 29 | display: none !important; } } 30 | 31 | @media screen and (min-width: 40em) and (max-width: 63.9375em) { 32 | .hide-for-medium-only { 33 | display: none !important; } } 34 | 35 | @media screen and (max-width: 39.9375em), screen and (min-width: 64em) { 36 | .show-for-medium-only { 37 | display: none !important; } } 38 | 39 | @media screen and (min-width: 64em) { 40 | .hide-for-large { 41 | display: none !important; } } 42 | 43 | @media screen and (max-width: 63.9375em) { 44 | .show-for-large { 45 | display: none !important; } } 46 | 47 | @media screen and (min-width: 64em) and (max-width: 74.9375em) { 48 | .hide-for-large-only { 49 | display: none !important; } } 50 | 51 | @media screen and (max-width: 63.9375em), screen and (min-width: 75em) { 52 | .show-for-large-only { 53 | display: none !important; } } 54 | 55 | .show-for-sr, 56 | .show-on-focus { 57 | position: absolute !important; 58 | width: 1px; 59 | height: 1px; 60 | overflow: hidden; 61 | clip: rect(0, 0, 0, 0); } 62 | 63 | .show-on-focus:active, .show-on-focus:focus { 64 | position: static !important; 65 | height: auto; 66 | width: auto; 67 | overflow: visible; 68 | clip: auto; } 69 | 70 | .show-for-landscape, 71 | .hide-for-portrait { 72 | display: block !important; } 73 | @media screen and (orientation: landscape) { 74 | .show-for-landscape, 75 | .hide-for-portrait { 76 | display: block !important; } } 77 | @media screen and (orientation: portrait) { 78 | .show-for-landscape, 79 | .hide-for-portrait { 80 | display: none !important; } } 81 | 82 | .hide-for-landscape, 83 | .show-for-portrait { 84 | display: none !important; } 85 | @media screen and (orientation: landscape) { 86 | .hide-for-landscape, 87 | .show-for-portrait { 88 | display: none !important; } } 89 | @media screen and (orientation: portrait) { 90 | .hide-for-landscape, 91 | .show-for-portrait { 92 | display: block !important; } } 93 | 94 | .has-tip { 95 | border-bottom: dotted 1px #8a8a8a; 96 | font-weight: bold; 97 | position: relative; 98 | display: inline-block; 99 | cursor: help; } 100 | 101 | .tooltip { 102 | background-color: #0a0a0a; 103 | color: #fefefe; 104 | font-size: 80%; 105 | padding: 0.75rem; 106 | position: absolute; 107 | z-index: 10; 108 | top: calc(100% + 0.6495rem); 109 | max-width: 10rem !important; 110 | border-radius: 0; } 111 | .tooltip::before { 112 | content: ''; 113 | display: block; 114 | width: 0; 115 | height: 0; 116 | border: inset 0.75rem; 117 | border-color: transparent transparent #0a0a0a; 118 | border-bottom-style: solid; 119 | border-top-width: 0; 120 | bottom: 100%; 121 | position: absolute; 122 | left: 50%; 123 | -webkit-transform: translateX(-50%); 124 | transform: translateX(-50%); } 125 | .tooltip.top::before { 126 | content: ''; 127 | display: block; 128 | width: 0; 129 | height: 0; 130 | border: inset 0.75rem; 131 | border-color: #0a0a0a transparent transparent; 132 | border-top-style: solid; 133 | border-bottom-width: 0; 134 | top: 100%; 135 | bottom: auto; } 136 | .tooltip.left::before { 137 | content: ''; 138 | display: block; 139 | width: 0; 140 | height: 0; 141 | border: inset 0.75rem; 142 | border-color: transparent transparent transparent #0a0a0a; 143 | border-left-style: solid; 144 | border-right-width: 0; 145 | bottom: auto; 146 | left: 100%; 147 | top: 50%; 148 | -webkit-transform: translateY(-50%); 149 | transform: translateY(-50%); } 150 | .tooltip.right::before { 151 | content: ''; 152 | display: block; 153 | width: 0; 154 | height: 0; 155 | border: inset 0.75rem; 156 | border-color: transparent #0a0a0a transparent transparent; 157 | border-right-style: solid; 158 | border-left-width: 0; 159 | bottom: auto; 160 | left: auto; 161 | right: 100%; 162 | top: 50%; 163 | -webkit-transform: translateY(-50%); 164 | transform: translateY(-50%); } 165 | 166 | body.is-reveal-open { 167 | overflow: hidden; } 168 | 169 | .reveal-overlay { 170 | display: none; 171 | position: fixed; 172 | top: 0; 173 | bottom: 0; 174 | left: 0; 175 | right: 0; 176 | z-index: 1005; 177 | background-color: rgba(10, 10, 10, 0.45); 178 | overflow-y: scroll; } 179 | 180 | .reveal { 181 | display: none; 182 | z-index: 1006; 183 | padding: 1rem; 184 | border: 1px solid #cacaca; 185 | background-color: #fefefe; 186 | border-radius: 0; 187 | position: relative; 188 | top: 100px; 189 | margin-left: auto; 190 | margin-right: auto; 191 | overflow-y: auto; } 192 | [data-whatinput='mouse'] .reveal { 193 | outline: 0; } 194 | @media screen and (min-width: 40em) { 195 | .reveal { 196 | min-height: 0; } } 197 | .reveal .column, 198 | .reveal .columns { 199 | min-width: 0; } 200 | .reveal > :last-child { 201 | margin-bottom: 0; } 202 | @media screen and (min-width: 40em) { 203 | .reveal { 204 | width: 600px; 205 | max-width: 75rem; } } 206 | @media screen and (min-width: 40em) { 207 | .reveal .reveal { 208 | left: auto; 209 | right: auto; 210 | margin: 0 auto; } } 211 | .reveal.collapse { 212 | padding: 0; } 213 | @media screen and (min-width: 40em) { 214 | .reveal.tiny { 215 | width: 30%; 216 | max-width: 75rem; } } 217 | @media screen and (min-width: 40em) { 218 | .reveal.small { 219 | width: 50%; 220 | max-width: 75rem; } } 221 | @media screen and (min-width: 40em) { 222 | .reveal.large { 223 | width: 90%; 224 | max-width: 75rem; } } 225 | .reveal.full { 226 | top: 0; 227 | left: 0; 228 | width: 100%; 229 | height: 100%; 230 | height: 100vh; 231 | min-height: 100vh; 232 | max-width: none; 233 | margin-left: 0; 234 | border: 0; 235 | border-radius: 0; } 236 | @media screen and (max-width: 39.9375em) { 237 | .reveal { 238 | top: 0; 239 | left: 0; 240 | width: 100%; 241 | height: 100%; 242 | height: 100vh; 243 | min-height: 100vh; 244 | max-width: none; 245 | margin-left: 0; 246 | border: 0; 247 | border-radius: 0; } } 248 | .reveal.without-overlay { 249 | position: fixed; } 250 | 251 | [data-joyride] { 252 | display: none; } 253 | 254 | .tooltip.joyride, 255 | .reveal.joyride { 256 | font-size: 100%; 257 | min-width: 20rem; 258 | padding: 0.5em; } 259 | .tooltip.joyride .close, 260 | .reveal.joyride .close { 261 | float: right; } 262 | .tooltip.joyride .joyride-buttons, 263 | .reveal.joyride .joyride-buttons { 264 | text-align: center; } 265 | .tooltip.joyride .joyride-buttons button, 266 | .reveal.joyride .joyride-buttons button { 267 | margin: 0 0.5em; } 268 | 269 | [data-whatinput='mouse'] .joyride { 270 | outline: 0; } 271 | -------------------------------------------------------------------------------- /dist/solo.joyride.min.css: -------------------------------------------------------------------------------- 1 | [data-whatinput=mouse] .joyride,[data-whatinput=mouse] .reveal{outline:0}.hide{display:none!important}.invisible{visibility:hidden}@media screen and (max-width:0em),screen and (min-width:40em){.show-for-small-only{display:none!important}}@media screen and (min-width:40em){.hide-for-medium{display:none!important}.reveal{min-height:0}}@media screen and (max-width:39.9375em){.hide-for-small-only,.show-for-medium{display:none!important}}@media screen and (min-width:40em) and (max-width:63.9375em){.hide-for-medium-only{display:none!important}}@media screen and (max-width:39.9375em),screen and (min-width:64em){.show-for-medium-only{display:none!important}}@media screen and (min-width:64em){.hide-for-large{display:none!important}}@media screen and (max-width:63.9375em){.show-for-large{display:none!important}}@media screen and (min-width:64em) and (max-width:74.9375em){.hide-for-large-only{display:none!important}}@media screen and (max-width:63.9375em),screen and (min-width:75em){.show-for-large-only{display:none!important}}.show-for-sr,.show-on-focus{position:absolute!important;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0)}.show-on-focus:active,.show-on-focus:focus{position:static!important;height:auto;width:auto;overflow:visible;clip:auto}.hide-for-portrait,.show-for-landscape{display:block!important}@media screen and (orientation:landscape){.hide-for-portrait,.show-for-landscape{display:block!important}.hide-for-landscape,.show-for-portrait{display:none!important}}.hide-for-landscape,.show-for-portrait{display:none!important}@media screen and (orientation:portrait){.hide-for-portrait,.show-for-landscape{display:none!important}.hide-for-landscape,.show-for-portrait{display:block!important}}.has-tip{border-bottom:dotted 1px #8a8a8a;font-weight:700;position:relative;display:inline-block;cursor:help}.tooltip.top::before,.tooltip::before{content:'';display:block;width:0;height:0}.tooltip{background-color:#0a0a0a;color:#fefefe;font-size:80%;padding:.75rem;position:absolute;z-index:10;top:calc(100% + .6495rem);max-width:10rem!important;border-radius:0}.tooltip::before{border:.75rem inset;border-color:transparent transparent #0a0a0a;border-bottom-style:solid;border-top-width:0;bottom:100%;position:absolute;left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.tooltip.top::before{border:.75rem inset;border-color:#0a0a0a transparent transparent;border-top-style:solid;border-bottom-width:0;top:100%;bottom:auto}.tooltip.left::before,.tooltip.right::before{content:'';display:block;width:0;height:0;bottom:auto;top:50%}.tooltip.left::before{border:.75rem inset;border-color:transparent transparent transparent #0a0a0a;border-left-style:solid;border-right-width:0;left:100%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.tooltip.right::before{border:.75rem inset;border-color:transparent #0a0a0a transparent transparent;border-right-style:solid;border-left-width:0;left:auto;right:100%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.reveal,[data-joyride]{display:none}body.is-reveal-open{overflow:hidden}.reveal-overlay{display:none;position:fixed;top:0;bottom:0;left:0;right:0;z-index:1005;background-color:rgba(10,10,10,.45);overflow-y:scroll}.reveal{z-index:1006;padding:1rem;border:1px solid #cacaca;background-color:#fefefe;border-radius:0;position:relative;top:100px;margin-left:auto;margin-right:auto;overflow-y:auto}.reveal .column,.reveal .columns{min-width:0}.reveal>:last-child{margin-bottom:0}.reveal.collapse{padding:0}@media screen and (min-width:40em){.reveal{width:600px;max-width:75rem}.reveal .reveal{left:auto;right:auto;margin:0 auto}.reveal.tiny{width:30%;max-width:75rem}.reveal.small{width:50%;max-width:75rem}.reveal.large{width:90%;max-width:75rem}}.reveal.full{top:0;left:0;width:100%;height:100%;height:100vh;min-height:100vh;max-width:none;margin-left:0;border:0;border-radius:0}@media screen and (max-width:39.9375em){.reveal{top:0;left:0;width:100%;height:100%;height:100vh;min-height:100vh;max-width:none;margin-left:0;border:0;border-radius:0}}.reveal.without-overlay{position:fixed}.reveal.joyride,.tooltip.joyride{font-size:100%;min-width:20rem;padding:.5em}.reveal.joyride .close,.tooltip.joyride .close{float:right}.reveal.joyride .joyride-buttons,.tooltip.joyride .joyride-buttons{text-align:center}.reveal.joyride .joyride-buttons button,.tooltip.joyride .joyride-buttons button{margin:0 .5em} -------------------------------------------------------------------------------- /dist/solo.joyride.min.js: -------------------------------------------------------------------------------- 1 | function _classCallCheck(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function _classCallCheck(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function _classCallCheck(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}!function(t){"use strict";function e(t){if(void 0===Function.prototype.name){var e=/function\s([^(]{1,})\(/,i=e.exec(t.toString());return i&&i.length>1?i[1].trim():""}return void 0===t.prototype?t.constructor.name:t.prototype.constructor.name}function i(t){return!!/true/.test(t)||!/false/.test(t)&&(isNaN(1*t)?t:parseFloat(t))}function n(t){return t.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}var o="6.2.1",s={version:o,_plugins:{},_uuids:[],rtl:function(){return"rtl"===t("html").attr("dir")},plugin:function(t,i){var o=i||e(t),s=n(o);this._plugins[s]=this[o]=t},registerPlugin:function(t,i){var o=i?n(i):e(t.constructor).toLowerCase();t.uuid=this.GetYoDigits(6,o),t.$element.attr("data-"+o)||t.$element.attr("data-"+o,t.uuid),t.$element.data("zfPlugin")||t.$element.data("zfPlugin",t),t.$element.trigger("init.zf."+o),this._uuids.push(t.uuid)},unregisterPlugin:function(t){var i=n(e(t.$element.data("zfPlugin").constructor));this._uuids.splice(this._uuids.indexOf(t.uuid),1),t.$element.removeAttr("data-"+i).removeData("zfPlugin").trigger("destroyed.zf."+i);for(var o in t)t[o]=null},reInit:function(e){var i=e instanceof t;try{if(i)e.each(function(){t(this).data("zfPlugin")._init()});else{var o=typeof e,s=this,a={object:function(e){e.forEach(function(e){e=n(e),t("[data-"+e+"]").foundation("_init")})},string:function(){e=n(e),t("[data-"+e+"]").foundation("_init")},undefined:function(){this.object(Object.keys(s._plugins))}};a[o](e)}}catch(r){console.error(r)}finally{return e}},GetYoDigits:function(t,e){return t=t||6,Math.round(Math.pow(36,t+1)-Math.random()*Math.pow(36,t)).toString(36).slice(1)+(e?"-"+e:"")},reflow:function(e,n){"undefined"==typeof n?n=Object.keys(this._plugins):"string"==typeof n&&(n=[n]);var o=this;t.each(n,function(n,s){var a=o._plugins[s],r=t(e).find("[data-"+s+"]").addBack("[data-"+s+"]");r.each(function(){var e=t(this),n={};if(e.data("zfPlugin"))return void console.warn("Tried to initialize "+s+" on an element that already has a Foundation plugin.");if(e.attr("data-options")){e.attr("data-options").split(";").forEach(function(t,e){var o=t.split(":").map(function(t){return t.trim()});o[0]&&(n[o[0]]=i(o[1]))})}try{e.data("zfPlugin",new a(t(this),n))}catch(o){console.error(o)}finally{return}})})},getFnName:e,transitionend:function(t){var e,i={transition:"transitionend",WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"otransitionend"},n=document.createElement("div");for(var o in i)"undefined"!=typeof n.style[o]&&(e=i[o]);return e?e:(e=setTimeout(function(){t.triggerHandler("transitionend",[t])},1),"transitionend")}};s.util={throttle:function(t,e){var i=null;return function(){var n=this,o=arguments;null===i&&(i=setTimeout(function(){t.apply(n,o),i=null},e))}}};var a=function(i){var n=typeof i,o=t("meta.foundation-mq"),a=t(".no-js");if(o.length||t('').appendTo(document.head),a.length&&a.removeClass("no-js"),"undefined"===n)s.MediaQuery._init(),s.reflow(this);else{if("string"!==n)throw new TypeError("We're sorry, "+n+" is not a valid parameter. You must use a string representing the method you wish to invoke.");var r=Array.prototype.slice.call(arguments,1),l=this.data("zfPlugin");if(void 0===l||void 0===l[i])throw new ReferenceError("We're sorry, '"+i+"' is not an available method for "+(l?e(l):"this element")+".");1===this.length?l[i].apply(l,r):this.each(function(e,n){l[i].apply(t(n).data("zfPlugin"),r)})}return this};window.Foundation=s,t.fn.foundation=a,function(){Date.now&&window.Date.now||(window.Date.now=Date.now=function(){return(new Date).getTime()});for(var t=["webkit","moz"],e=0;e=h.offset.top,r=u.offset.left>=h.offset.left,l=u.offset.left+u.width<=h.width}else a=u.offset.top+u.height<=u.windowDims.height+u.windowDims.offset.top,s=u.offset.top>=u.windowDims.offset.top,r=u.offset.left>=u.windowDims.offset.left,l=u.offset.left+u.width<=u.windowDims.width;var d=[a,s,r,l];return n?r===l==!0:o?s===a==!0:d.indexOf(!1)===-1}function i(t,e){if(t=t.length?t[0]:t,t===window||t===document)throw new Error("I'm sorry, Dave. I'm afraid I can't do that.");var i=t.getBoundingClientRect(),n=t.parentNode.getBoundingClientRect(),o=document.body.getBoundingClientRect(),s=window.pageYOffset,a=window.pageXOffset;return{width:i.width,height:i.height,offset:{top:i.top+s,left:i.left+a},parentDims:{width:n.width,height:n.height,offset:{top:n.top+s,left:n.left+a}},windowDims:{width:o.width,height:o.height,offset:{top:s,left:a}}}}function n(t,e,n,o,s,a){var r=i(t),l=e?i(e):null;switch(n){case"top":return{left:Foundation.rtl()?l.offset.left-r.width+l.width:l.offset.left,top:l.offset.top-(r.height+o)};case"left":return{left:l.offset.left-(r.width+s),top:l.offset.top};case"right":return{left:l.offset.left+l.width+s,top:l.offset.top};case"center top":return{left:l.offset.left+l.width/2-r.width/2,top:l.offset.top-(r.height+o)};case"center bottom":return{left:a?s:l.offset.left+l.width/2-r.width/2,top:l.offset.top+l.height+o};case"center left":return{left:l.offset.left-(r.width+s),top:l.offset.top+l.height/2-r.height/2};case"center right":return{left:l.offset.left+l.width+s+1,top:l.offset.top+l.height/2-r.height/2};case"center":return{left:r.windowDims.offset.left+r.windowDims.width/2-r.width/2,top:r.windowDims.offset.top+r.windowDims.height/2-r.height/2};case"reveal":return{left:(r.windowDims.width-r.width)/2,top:r.windowDims.offset.top+o};case"reveal full":return{left:r.windowDims.offset.left,top:r.windowDims.offset.top};case"left bottom":return{left:l.offset.left-(r.width+s),top:l.offset.top+l.height};case"right bottom":return{left:l.offset.left+l.width+s-r.width,top:l.offset.top+l.height};default:return{left:Foundation.rtl()?l.offset.left-r.width+l.width:l.offset.left,top:l.offset.top+l.height+o}}}Foundation.Box={ImNotTouchingYou:e,GetDimensions:i,GetOffsets:n}}(jQuery),!function(t){function e(t){var e={};for(var i in t)e[t[i]]=t[i];return e}var i={9:"TAB",13:"ENTER",27:"ESCAPE",32:"SPACE",37:"ARROW_LEFT",38:"ARROW_UP",39:"ARROW_RIGHT",40:"ARROW_DOWN"},n={},o={keys:e(i),parseKey:function(t){var e=i[t.which||t.keyCode]||String.fromCharCode(t.which).toUpperCase();return t.shiftKey&&(e="SHIFT_"+e),t.ctrlKey&&(e="CTRL_"+e),t.altKey&&(e="ALT_"+e),e},handleKey:function(e,i,o){var s,a,r,l=n[i],u=this.parseKey(e);return l?(s="undefined"==typeof l.ltr?l:Foundation.rtl()?t.extend({},l.ltr,l.rtl):t.extend({},l.rtl,l.ltr),a=s[u],r=o[a],void(r&&"function"==typeof r?(r.apply(),(o.handled||"function"==typeof o.handled)&&o.handled.apply()):(o.unhandled||"function"==typeof o.unhandled)&&o.unhandled.apply())):console.warn("Component not defined!")},findFocusable:function(e){return e.find("a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]").filter(function(){return!(!t(this).is(":visible")||t(this).attr("tabindex")<0)})},register:function(t,e){n[t]=e}};Foundation.Keyboard=o}(jQuery),!function(t){function e(t){var e={};return"string"!=typeof t?e:(t=t.trim().slice(1,-1))?e=t.split("&").reduce(function(t,e){var i=e.replace(/\+/g," ").split("="),n=i[0],o=i[1];return n=decodeURIComponent(n),o=void 0===o?null:decodeURIComponent(o),t.hasOwnProperty(n)?Array.isArray(t[n])?t[n].push(o):t[n]=[t[n],o]:t[n]=o,t},{}):e}var i={queries:[],current:"",_init:function(){var i,n=this,o=t(".foundation-mq").css("font-family");i=e(o);for(var s in i)n.queries.push({name:s,value:"only screen and (min-width: "+i[s]+")"});this.current=this._getCurrentSize(),this._watcher()},atLeast:function(t){var e=this.get(t);return!!e&&window.matchMedia(e).matches},get:function(t){for(var e in this.queries){var i=this.queries[e];if(t===i.name)return i.value}return null},_getCurrentSize:function(){for(var t,e=0;e1&&void 0!==arguments[1]?arguments[1]:"zf";e.attr("role","menubar");var n=e.find("li").attr({role:"menuitem"}),o="is-"+i+"-submenu",s=o+"-item",a="is-"+i+"-submenu-parent";e.find("a:first").attr("tabindex",0),n.each(function(){var e=t(this),i=e.children("ul");i.length&&(e.addClass(a).attr({"aria-haspopup":!0,"aria-expanded":!1,"aria-label":e.children("a:first").text()}),i.addClass("submenu "+o).attr({"data-submenu":"","aria-hidden":!0,role:"menu"})),e.parent("[data-submenu]").length&&e.addClass("is-submenu-item "+s)})},Burn:function(t,e){var i=(t.find("li").removeAttr("tabindex"),"is-"+e+"-submenu"),n=i+"-item",o="is-"+e+"-submenu-parent";t.find("*").removeClass(i+" "+n+" "+o+" is-submenu-item submenu is-active").removeAttr("data-submenu").css("display","")}};Foundation.Nest=e}(jQuery),!function(t){function e(t,e,i){var n,o,s=this,a=e.duration,r=Object.keys(t.data())[0]||"timer",l=-1;this.isPaused=!1,this.restart=function(){l=-1,clearTimeout(o),this.start()},this.start=function(){this.isPaused=!1,clearTimeout(o),l=l<=0?a:l,t.data("paused",!1),n=Date.now(),o=setTimeout(function(){e.infinite&&s.restart(),i()},l),t.trigger("timerstart.zf."+r)},this.pause=function(){this.isPaused=!0,clearTimeout(o),t.data("paused",!0);var e=Date.now();l-=e-n,t.trigger("timerpaused.zf."+r)}}function i(e,i){function n(){o--,0===o&&i()}var o=e.length;0===o&&i(),e.each(function(){this.complete?n():"undefined"!=typeof this.naturalWidth&&this.naturalWidth>0?n():t(this).one("load",function(){n()})})}Foundation.Timer=e,Foundation.onImagesLoaded=i}(jQuery),function(t){function e(){this.removeEventListener("touchmove",i),this.removeEventListener("touchend",e),u=!1}function i(i){if(t.spotSwipe.preventDefault&&i.preventDefault(),u){var n,o=i.touches[0].pageX,a=(i.touches[0].pageY,s-o);l=(new Date).getTime()-r,Math.abs(a)>=t.spotSwipe.moveThreshold&&l<=t.spotSwipe.timeThreshold&&(n=a>0?"left":"right"),n&&(i.preventDefault(),e.call(this),t(this).trigger("swipe",n).trigger("swipe"+n))}}function n(t){1==t.touches.length&&(s=t.touches[0].pageX,a=t.touches[0].pageY,u=!0,r=(new Date).getTime(),this.addEventListener("touchmove",i,!1),this.addEventListener("touchend",e,!1))}function o(){this.addEventListener&&this.addEventListener("touchstart",n,!1)}t.spotSwipe={version:"1.0.0",enabled:"ontouchstart"in document.documentElement,preventDefault:!1,moveThreshold:75,timeThreshold:200};var s,a,r,l,u=!1;t.event.special.swipe={setup:o},t.each(["left","up","down","right"],function(){t.event.special["swipe"+this]={setup:function(){t(this).on("swipe",t.noop)}}})}(jQuery),!function(t){t.fn.addTouch=function(){this.each(function(i,n){t(n).bind("touchstart touchmove touchend touchcancel",function(){e(event)})});var e=function(t){var e,i=t.changedTouches,n=i[0],o={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup"},s=o[t.type];"MouseEvent"in window&&"function"==typeof window.MouseEvent?e=window.MouseEvent(s,{bubbles:!0,cancelable:!0,screenX:n.screenX,screenY:n.screenY,clientX:n.clientX,clientY:n.clientY}):(e=document.createEvent("MouseEvent"),e.initMouseEvent(s,!0,!0,window,1,n.screenX,n.screenY,n.clientX,n.clientY,!1,!1,!1,!1,0,null)),n.target.dispatchEvent(e)}}}(jQuery),!function(t){function e(){s(),n(),o(),i()}function i(e){var i=t("[data-yeti-box]"),n=["dropdown","tooltip","reveal"];if(e&&("string"==typeof e?n.push(e):"object"==typeof e&&"string"==typeof e[0]?n.concat(e):console.error("Plugin names must be strings")),i.length){var o=n.map(function(t){return"closeme.zf."+t}).join(" ");t(window).off(o).on(o,function(e,i){var n=e.namespace.split(".")[0],o=t("[data-"+n+"]").not('[data-yeti-box="'+i+'"]');o.each(function(){var e=t(this);e.triggerHandler("close.zf.trigger",[e])})})}}function n(e){var i=void 0,n=t("[data-resize]");n.length&&t(window).off("resize.zf.trigger").on("resize.zf.trigger",function(o){i&&clearTimeout(i),i=setTimeout(function(){a||n.each(function(){t(this).triggerHandler("resizeme.zf.trigger")}),n.attr("data-events","resize")},e||10)})}function o(e){var i=void 0,n=t("[data-scroll]");n.length&&t(window).off("scroll.zf.trigger").on("scroll.zf.trigger",function(o){i&&clearTimeout(i),i=setTimeout(function(){a||n.each(function(){t(this).triggerHandler("scrollme.zf.trigger")}),n.attr("data-events","scroll")},e||10)})}function s(){if(!a)return!1;var e=document.querySelectorAll("[data-resize], [data-scroll], [data-mutate]"),i=function(e){var i=t(e[0].target);switch(i.attr("data-events")){case"resize":i.triggerHandler("resizeme.zf.trigger",[i]);break;case"scroll":i.triggerHandler("scrollme.zf.trigger",[i,window.pageYOffset]);break;default:return!1}};if(e.length)for(var n=0;n<=e.length-1;n++){var o=new a(i);o.observe(e[n],{attributes:!0,childList:!1,characterData:!1,subtree:!1,attributeFilter:["data-events"]})}}var a=function(){for(var t=["WebKit","Moz","O","Ms",""],e=0;e
").addClass(i).attr({role:"tooltip","aria-hidden":!0,"data-is-active":!1,"data-is-focus":!1,id:e});return n}},{key:"_reposition",value:function(t){this.usedPositions.push(t?t:"bottom"),!t&&this.usedPositions.indexOf("top")<0?this.template.addClass("top"):"top"===t&&this.usedPositions.indexOf("bottom")<0?this.template.removeClass(t):"left"===t&&this.usedPositions.indexOf("right")<0?this.template.removeClass(t).addClass("right"):"right"===t&&this.usedPositions.indexOf("left")<0?this.template.removeClass(t).addClass("left"):!t&&this.usedPositions.indexOf("top")>-1&&this.usedPositions.indexOf("left")<0?this.template.addClass("left"):"top"===t&&this.usedPositions.indexOf("bottom")>-1&&this.usedPositions.indexOf("left")<0?this.template.removeClass(t).addClass("left"):"left"===t&&this.usedPositions.indexOf("right")>-1&&this.usedPositions.indexOf("bottom")<0?this.template.removeClass(t):"right"===t&&this.usedPositions.indexOf("left")>-1&&this.usedPositions.indexOf("bottom")<0?this.template.removeClass(t):this.template.removeClass(t),this.classChanged=!0,this.counter--}},{key:"_setPosition",value:function(){var t=this._getPositionClass(this.template),e=Foundation.Box.GetDimensions(this.template),i=Foundation.Box.GetDimensions(this.$element),n="left"===t?"left":"right"===t?"left":"top",o="top"===n?"height":"width";"height"===o?this.options.vOffset:this.options.hOffset;if(e.width>=e.windowDims.width||!this.counter&&!Foundation.Box.ImNotTouchingYou(this.template))return this.template.offset(Foundation.Box.GetOffsets(this.template,this.$element,"center bottom",this.options.vOffset,this.options.hOffset,!0)).css({width:i.windowDims.width-2*this.options.hOffset,height:"auto"}),!1;for(this.template.offset(Foundation.Box.GetOffsets(this.template,this.$element,"center "+(t||"bottom"),this.options.vOffset,this.options.hOffset));!Foundation.Box.ImNotTouchingYou(this.template)&&this.counter;)this._reposition(t),this._setPosition()}},{key:"show",value:function(){if("all"!==this.options.showOn&&!Foundation.MediaQuery.atLeast(this.options.showOn))return!1;var t=this;this.template.css("visibility","hidden").show(),this._setPosition(),this.$element.trigger("closeme.zf.tooltip",this.template.attr("id")),this.template.attr({"data-is-active":!0,"aria-hidden":!1}),t.isActive=!0,this.template.stop().hide().css("visibility","").fadeIn(this.options.fadeInDuration,function(){}),this.$element.trigger("show.zf.tooltip")}},{key:"hide",value:function(){var t=this;this.template.stop().attr({"aria-hidden":!0,"data-is-active":!1}).fadeOut(this.options.fadeOutDuration,function(){t.isActive=!1,t.isClick=!1,t.classChanged&&(t.template.removeClass(t._getPositionClass(t.template)).addClass(t.options.positionClass),t.usedPositions=[],t.counter=4,t.classChanged=!1)}),this.$element.trigger("hide.zf.tooltip")}},{key:"_events",value:function(){var t=this,e=(this.template,!1);this.options.disableHover||this.$element.on("mouseenter.zf.tooltip",function(e){t.isActive||(t.timeout=setTimeout(function(){t.show()},t.options.hoverDelay))}).on("mouseleave.zf.tooltip",function(i){clearTimeout(t.timeout),(!e||!t.isClick&&t.options.clickOpen)&&t.hide()}),this.options.clickOpen&&this.$element.on("mousedown.zf.tooltip",function(e){e.stopImmediatePropagation(),t.isClick?t.hide():(t.isClick=!0,!t.options.disableHover&&t.$element.attr("tabindex")||t.isActive||t.show())}),this.options.disableForTouch||this.$element.on("tap.zf.tooltip touchend.zf.tooltip",function(e){t.isActive?t.hide():t.show()}),this.$element.on({"close.zf.trigger":this.hide.bind(this)}),this.$element.on("focus.zf.tooltip",function(i){return e=!0,!t.isClick&&void t.show()}).on("focusout.zf.tooltip",function(i){e=!1,t.isClick=!1,t.hide()}).on("resizeme.zf.trigger",function(){t.isActive&&t._setPosition()})}},{key:"toggle",value:function(){this.isActive?this.hide():this.show()}},{key:"destroy",value:function(){this.$element.attr("title",this.template.text()).off(".zf.trigger .zf.tootip").removeAttr("aria-describedby").removeAttr("data-yeti-box").removeAttr("data-toggle").removeAttr("data-resize"),this.template.remove(),Foundation.unregisterPlugin(this)}}]),e}();e.defaults={disableForTouch:!1,hoverDelay:200,fadeInDuration:150,fadeOutDuration:150,disableHover:!1,templateClasses:"",tooltipClass:"tooltip",triggerClass:"has-tip",showOn:"small",template:"",tipText:"",touchCloseText:"Tap to close.",clickOpen:!0,positionClass:"",vOffset:10,hOffset:12},Foundation.plugin(e,"Tooltip")}(jQuery);var _createClass=function(){function t(t,e){for(var i=0;i
").addClass("reveal-overlay").attr({tabindex:-1,"aria-hidden":!0}).appendTo("body");return i}},{key:"_updatePosition",value:function(){var e,i,n=this.$element.outerWidth(),o=t(window).width(),s=this.$element.outerHeight(),a=t(window).height();e="auto"===this.options.hOffset?parseInt((o-n)/2,10):parseInt(this.options.hOffset,10),i="auto"===this.options.vOffset?s>a?parseInt(Math.min(100,a/10),10):parseInt((a-s)/4,10):parseInt(this.options.vOffset,10),this.$element.css({top:i+"px"}),this.$overlay&&"auto"===this.options.hOffset||(this.$element.css({left:e+"px"}),this.$element.css({margin:"0px"}))}},{key:"_events",value:function(){var e=this;this.$element.on({"open.zf.trigger":this.open.bind(this),"close.zf.trigger":this.close.bind(this),"toggle.zf.trigger":this.toggle.bind(this),"resizeme.zf.trigger":function(){e._updatePosition()}}),this.$anchor.length&&this.$anchor.on("keydown.zf.reveal",function(t){13!==t.which&&32!==t.which||(t.stopPropagation(),t.preventDefault(),e.open())}),this.options.closeOnClick&&this.options.overlay&&this.$overlay.off(".zf.reveal").on("click.zf.reveal",function(i){i.target===e.$element[0]||t.contains(e.$element[0],i.target)||e.close()}),this.options.deepLink&&t(window).on("popstate.zf.reveal:"+this.id,this._handleState.bind(this))}},{key:"_handleState",value:function(t){window.location.hash!=="#"+this.id||this.isActive?this.close():this.open()}},{key:"open",value:function(){var e=this;if(this.options.deepLink){var i="#"+this.id;window.history.pushState?window.history.pushState(null,null,i):window.location.hash=i}if(this.isActive=!0,this.$element.css({visibility:"hidden"}).show().scrollTop(0),this.options.overlay&&this.$overlay.css({visibility:"hidden"}).show(),this._updatePosition(),this.$element.hide().css({visibility:""}),this.$overlay&&this.$overlay.css({visibility:""}).hide(),this.options.multipleOpened||this.$element.trigger("closeme.zf.reveal",this.id),this.options.animationIn?(this.options.overlay&&Foundation.Motion.animateIn(this.$overlay,"fade-in"),Foundation.Motion.animateIn(this.$element,this.options.animationIn,function(){e.focusableElements=Foundation.Keyboard.findFocusable(e.$element)})):(this.options.overlay&&this.$overlay.show(0),this.$element.show(this.options.showDelay)),this.$element.attr({"aria-hidden":!1,tabindex:-1}).focus(),this.$element.trigger("open.zf.reveal"),this.isiOS){var n=window.pageYOffset;t("html, body").addClass("is-reveal-open").scrollTop(n)}else t("body").addClass("is-reveal-open");t("body").addClass("is-reveal-open").attr("aria-hidden",!(!this.options.overlay&&!this.options.fullScreen)),setTimeout(function(){e._extraHandlers()},0)}},{key:"_extraHandlers",value:function(){var e=this;this.focusableElements=Foundation.Keyboard.findFocusable(this.$element),this.options.overlay||!this.options.closeOnClick||this.options.fullScreen||t("body").on("click.zf.reveal",function(i){i.target===e.$element[0]||t.contains(e.$element[0],i.target)||e.close()}),this.options.closeOnEsc&&t(window).on("keydown.zf.reveal",function(t){Foundation.Keyboard.handleKey(t,"Reveal",{close:function(){e.options.closeOnEsc&&(e.close(),e.$anchor.focus())}})}),this.$element.on("keydown.zf.reveal",function(i){var n=t(this);Foundation.Keyboard.handleKey(i,"Reveal",{tab_forward:function(){e.$element.find(":focus").is(e.focusableElements.eq(-1))&&(e.focusableElements.eq(0).focus(),i.preventDefault()),0===e.focusableElements.length&&i.preventDefault()},tab_backward:function(){(e.$element.find(":focus").is(e.focusableElements.eq(0))||e.$element.is(":focus"))&&(e.focusableElements.eq(-1).focus(),i.preventDefault()),0===e.focusableElements.length&&i.preventDefault()},open:function(){e.$element.find(":focus").is(e.$element.find("[data-close]"))?setTimeout(function(){e.$anchor.focus()},1):n.is(e.focusableElements)&&e.open()},close:function(){e.options.closeOnEsc&&(e.close(),e.$anchor.focus())}})})}},{key:"close",value:function(){function e(){i.isiOS?t("html, body").removeClass("is-reveal-open"):t("body").removeClass("is-reveal-open"),t("body").attr({"aria-hidden":!1,tabindex:""}),i.$element.attr("aria-hidden",!0),i.$element.trigger("closed.zf.reveal")}if(!this.isActive||!this.$element.is(":visible"))return!1;var i=this;this.options.animationOut?(this.options.overlay?Foundation.Motion.animateOut(this.$overlay,"fade-out",e):e(),Foundation.Motion.animateOut(this.$element,this.options.animationOut)):(this.options.overlay?this.$overlay.hide(0,e):e(),this.$element.hide(this.options.hideDelay)),this.options.closeOnEsc&&t(window).off("keydown.zf.reveal"),!this.options.overlay&&this.options.closeOnClick&&t("body").off("click.zf.reveal"),this.$element.off("keydown.zf.reveal"),this.options.resetOnClose&&this.$element.html(this.$element.html()),this.isActive=!1,i.options.deepLink&&(window.history.replaceState?window.history.replaceState("",document.title,window.location.pathname):window.location.hash="")}},{key:"toggle",value:function(){this.isActive?this.close():this.open()}},{key:"destroy",value:function(){this.options.overlay&&(this.$element.appendTo(t("body")),this.$overlay.hide().off().remove()),this.$element.hide().off(),this.$anchor.off(".zf"),t(window).off(".zf.reveal:"+this.id),Foundation.unregisterPlugin(this)}}]),i}();i.defaults={animationIn:"",animationOut:"",showDelay:0,hideDelay:0,closeOnClick:!0,closeOnEsc:!0,multipleOpened:!1,vOffset:"auto",hOffset:"auto",fullScreen:!1,btmOffsetPct:10,overlay:!0,resetOnClose:!1,deepLink:!1},Foundation.plugin(i,"Reveal")}(jQuery);var _createClass=function(){function t(t,e){for(var i=0;i').appendTo(t("body"))); 2 | this.structure[i].item=a,n=a.$element}if(n.attr({"data-index":i,"data-joyride-for":e[i].target}).html(e[i].text),o.keyboardAccess&&n.attr("tabindex","-1"),this.$items=this.$items.add(n),e[i].nextText||o.showNext&&i0){var r=t('
');(e[i].prevText||o.showPrev&&i>0)&&r.append(t(this.options.prevButton).text(o.prevText)),(e[i].nextText||o.showNext&&i0&&e.showPrev()},close:function(){e.structure[e.current].closable&&e._hideItem(e.current)},handled:function(){i.preventDefault()}})})}},{key:"destroy",value:function(){this.$element.hide();for(var t in this.structure)this.structure[t].item.destroy();this.$element.trigger("destroyed.zf.joyride"),Foundation.unregisterPlugin(this)}}]),e}();return e.defaults={autostart:!1,scrollSpeed:1e3,keyboardAccess:!0,closable:!0,nextText:"Next",prevText:"Previous",closeText:"Close",showNext:!0,showPrev:!0,vOffset:10,hOffset:12,scrollOffset:50,position:"top center",closeButton:'',nextButton:'',prevButton:''},Foundation.plugin(e,"Joyride"),e}); -------------------------------------------------------------------------------- /gulp/config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Configuration file for the gulp tasks. 3 | * 4 | * @author Marius Olbertz 5 | * @version 0.1gu 6 | */ 7 | module.exports = { 8 | name: 'joyride', 9 | srcPath: '', 10 | destPath: 'dist/', 11 | buildPath: '_build/', 12 | pluginPath: '_build/', 13 | foundationPath: 'node_modules/foundation-sites', 14 | css: { 15 | compatibility: ['last 2 versions', 'ie 10', 'Android >= 4.1'], // compatibility for auto prefixer 16 | components: [ 17 | 'tooltip', 18 | 'reveal' 19 | ] 20 | }, 21 | javascript: { 22 | dependencies: [ // define JS dependencies for this project to concat 23 | 'node_modules/foundation-sites/js/foundation.core.js', 24 | 'node_modules/foundation-sites/js/foundation.util.*.js', 25 | 'node_modules/foundation-sites/js/foundation.tooltip.js', 26 | 'node_modules/foundation-sites/js/foundation.reveal.js', 27 | 'dist/foundation.joyride.js' 28 | ] 29 | } 30 | }; -------------------------------------------------------------------------------- /gulp/css.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'), 2 | autoprefixer = require('gulp-autoprefixer'), 3 | minify_css = require('gulp-minify-css'), 4 | concat = require('gulp-concat'), 5 | rename = require('gulp-rename'), 6 | config = require('./config'); 7 | 8 | /** 9 | * Gulp task css:foundation. 10 | * Concates the CSS dependencies for the Foundation based version. Applies Autoprefixer. 11 | * Outputs to buildPath. 12 | */ 13 | gulp.task('css:foundation', ['scss:foundation'], function () { 14 | return gulp.src([config.buildPath + config.name + '.css']) 15 | .pipe(autoprefixer({ 16 | browsers: config.css.compatibility 17 | })) 18 | .pipe(rename('foundation.' + config.name + '.css')) 19 | .pipe(gulp.dest(config.buildPath + 'assets/')); 20 | }); 21 | 22 | /** 23 | * Gulp task css:standalone. 24 | * Concates the CSS dependencies for the standalone version. Applies Autoprefixer. 25 | * Outputs to buildPath. 26 | */ 27 | gulp.task('css:standalone', ['scss:standalone', 'css:foundation'], function () { 28 | return gulp.src([config.buildPath + '/*.css']) 29 | .pipe(concat('solo.' + config.name + '.css')) 30 | .pipe(autoprefixer({ 31 | browsers: config.css.compatibility 32 | })) 33 | .pipe(gulp.dest(config.buildPath + 'assets/')); 34 | }); 35 | 36 | 37 | /** 38 | * Gulp task css:min. 39 | * Minifies the result of css:*. 40 | * Outputs to destPath. 41 | */ 42 | gulp.task('css:min', ['css:foundation', 'css:standalone'], function () { 43 | return gulp.src(config.buildPath + '/assets/*.css') 44 | .pipe(minify_css()) 45 | .pipe(rename({suffix: '.min'})) 46 | .pipe(gulp.dest(config.destPath)); 47 | }); 48 | -------------------------------------------------------------------------------- /gulp/javascript.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'), 2 | rename = require('gulp-rename'), 3 | concat = require('gulp-concat'), 4 | babel = require('gulp-babel'), 5 | uglify = require('gulp-uglify'), 6 | gulpUtil = require('gulp-util'), 7 | config = require('./config'); 8 | 9 | /** 10 | * Gulp task js:foundation. 11 | * Concates the JS dependencies for the Foundation based version. Applies Babel. 12 | * Outputs to buildPath. 13 | */ 14 | gulp.task('js:foundation', function () { 15 | return gulp.src(config.srcPath + 'js/' + config.name + '.js') 16 | .pipe(babel()) 17 | .pipe(rename('foundation.' + config.name + '.js')) 18 | .pipe(gulp.dest(config.buildPath + 'assets/')); 19 | }); 20 | 21 | /** 22 | * Gulp task js:standalone. 23 | * Concates the JS dependencies for the standalone version. Applies Babel. 24 | * Outputs to buildPath. 25 | */ 26 | gulp.task('js:standalone', ['js:foundation'], function () { 27 | return gulp.src(config.javascript.dependencies) 28 | .pipe(babel()) 29 | .pipe(concat('solo.' + config.name + '.js')) 30 | .pipe(gulp.dest(config.buildPath + 'assets/')); 31 | }); 32 | 33 | /** 34 | * Gulp task js:min. 35 | * Uglifies the result of js:*. 36 | * Outputs to destPath. 37 | */ 38 | gulp.task('js:min', ['js:foundation', 'js:standalone'], function () { 39 | return gulp.src(config.buildPath + 'assets/*.js') 40 | .pipe(uglify().on('error', gulpUtil.log)) 41 | .pipe(rename({suffix: '.min'})) 42 | .pipe(gulp.dest(config.destPath)); 43 | }); 44 | -------------------------------------------------------------------------------- /gulp/publish.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'), 2 | runSequence = require('run-sequence'), 3 | rimraf = require('rimraf').sync, 4 | babel = require('gulp-babel'), 5 | exec = require('child_process').exec, 6 | config = require('./config'), 7 | tmpFolder = './_publish/'; 8 | 9 | /** 10 | * Gulp task publish. 11 | * Publishes latest version to gh-pages. 12 | */ 13 | gulp.task('publish', function (cb) { 14 | runSequence('publish:prepare', 'publish:push', 'publish:clean', cb); 15 | }); 16 | 17 | /** 18 | * Gulp task publish:prepare. 19 | * Creates temporary folder to publish by copying all relevant assets. 20 | */ 21 | gulp.task('publish:prepare', function (cb) { 22 | // Copy HTML files 23 | gulp.src(['./test/visual/*']) 24 | .pipe(gulp.dest(tmpFolder)) 25 | .on('end', function() { 26 | // Copy component files 27 | gulp.src([config.buildPath + '/assets/*']) 28 | .pipe(gulp.dest(tmpFolder + 'assets/')) 29 | .on('end', function() { 30 | // Copy dependencies 31 | gulp.src(['./node_modules/{foundation-sites,what-input,jquery}/**/*']) 32 | .pipe(gulp.dest(tmpFolder + '/')) 33 | .on('end', cb); 34 | }); 35 | }); 36 | }); 37 | 38 | /** 39 | * Gulp task publish:clean. 40 | * Cleans up temporary folder for publish. 41 | */ 42 | gulp.task('publish:clean', function (cb) { 43 | rimraf(tmpFolder); 44 | }); 45 | 46 | /** 47 | * Gulp task publish:push. 48 | * Publishes the visual tests to gh-pages. 49 | */ 50 | gulp.task('publish:push', function(cb) { 51 | exec('git subtree push --prefix ' + tmpFolder + ' origin gh-pages', function(error, stdout, stderr) { 52 | console.log(stdout); 53 | cb(); 54 | }); 55 | }); -------------------------------------------------------------------------------- /gulp/scss.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'), 2 | rename = require('gulp-rename'), 3 | sass = require('gulp-ruby-sass') 4 | mustache = require('gulp-mustache'), 5 | config = require('./config'); 6 | 7 | /** 8 | * Gulp task scss:*. 9 | * Converts SASS to CSS into the build folder. 10 | */ 11 | 12 | gulp.task('scss:foundation', function () { 13 | return sass(config.srcPath + 'scss/' + config.name + '.scss', {sourcemap: false}) 14 | .pipe(rename(config.name + '.css')) 15 | .pipe(gulp.dest(config.buildPath)); 16 | }); 17 | 18 | gulp.task('scss:standalone', ['writeScss:foundation', 'scss:foundation'], function () { 19 | return sass(config.buildPath + 'foundation.scss', {sourcemap: false, defaultEncoding: 'UTF-8'}) 20 | .pipe(gulp.dest(config.buildPath)); 21 | }); 22 | 23 | 24 | // prepare imports for SASS dynamically based on config 25 | gulp.task('writeScss:foundation', function () { 26 | return gulp.src(config.srcPath + 'scss/foundation_dependencies.scss') 27 | .pipe(mustache(config.css)) 28 | .pipe(rename('foundation.scss')) 29 | .pipe(gulp.dest(config.buildPath)); 30 | }); -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'), 2 | runSequence = require('run-sequence'), 3 | rimraf = require('rimraf').sync, 4 | requireDir = require('require-dir'), 5 | browser = require('browser-sync'), 6 | config = require('./gulp/config'); 7 | 8 | requireDir('./gulp'); 9 | 10 | 11 | 12 | /** 13 | * Gulp task default. 14 | * Calls build:all. 15 | */ 16 | gulp.task('default', ['serve', 'watch']); 17 | 18 | /** 19 | * Gulp task build:all. 20 | * Calls build:foundation and build:standalone. 21 | */ 22 | gulp.task('build:all', function(cb) { 23 | runSequence('build:foundation', 'build:standalone', cb); 24 | }); 25 | 26 | /** 27 | * Gulp task build:foundation. 28 | * Calls js:foundation and css:foundation. 29 | */ 30 | gulp.task('build:foundation', ['js:foundation', 'css:foundation']); 31 | 32 | /** 33 | * Gulp task build:standalone. 34 | * Calls js:standalone and css:standalone. 35 | */ 36 | gulp.task('build:standalone', ['js:standalone', 'css:standalone']); 37 | 38 | /** 39 | * Gulp task dist. 40 | * Copies the built files into the dist folder. 41 | */ 42 | gulp.task('dist', ['js:min', 'css:min'], function() { 43 | // uninified files 44 | gulp.src([config.buildPath + 'assets/*']) 45 | .pipe(gulp.dest(config.destPath)); 46 | }); 47 | 48 | /** 49 | * Gulp task watch. 50 | * Watch files for changes and reloads the browser. 51 | */ 52 | gulp.task('watch', function() { 53 | gulp.watch('./js/**/*', [[['js:foundation'], 'js:standalone'], browser.reload]); 54 | gulp.watch('./scss/**/*', [[['css:foundation'], 'css:standalone'], browser.reload]); 55 | gulp.watch('./test/visual/*.html', [browser.reload]); 56 | }); 57 | 58 | /** 59 | * Gulp task serve. 60 | * Starts a BrowerSync instance. 61 | */ 62 | gulp.task('serve', ['build:all'], function() { 63 | browser.init({ 64 | server: { 65 | baseDir: './test/visual', 66 | routes: { 67 | "/assets": "_build/assets", 68 | "/jquery": "node_modules/jquery", 69 | "/foundation-sites": "node_modules/foundation-sites", 70 | "/what-input": "node_modules/what-input" 71 | } 72 | } 73 | }); 74 | }); 75 | 76 | /** 77 | * Gulp task clean. 78 | * Deletes the build folder. 79 | */ 80 | gulp.task('clean', function () { 81 | rimraf(config.buildPath); 82 | }); -------------------------------------------------------------------------------- /js/joyride.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /******************************************* 3 | * * 4 | * This Ride was created by Marius Olbertz * 5 | * Please thank Marius on GitHub /owlbertz * 6 | * or the web http://www.mariusolbertz.de/ * 7 | * * 8 | ******************************************/ 9 | 10 | !(function (root, factory) { 11 | if (typeof define === 'function' && define.amd) { 12 | // AMD 13 | define(['jquery', 'foundation'], factory); 14 | } else if (typeof exports === 'object') { 15 | // Node, CommonJS-like 16 | module.exports = factory(require('jquery')); 17 | } else { 18 | // Browser globals (root is window) 19 | root.returnExports = factory(root.jQuery); 20 | } 21 | }(this, function ($) { 22 | /** 23 | * Joyride module. 24 | * @module foundation.joyride 25 | * @requires foundation.util.keyboard 26 | * @requires foundation.Tooltip 27 | * @requires foundation.Reveal 28 | */ 29 | class Joyride { 30 | /** 31 | * Creates a new instance of Joyride. 32 | * @class 33 | * @param {jQuery} element - jQuery object (list) to be used as the structure. 34 | * @param {Object} options - object to extend the default configuration. 35 | */ 36 | 37 | constructor(element, options) { 38 | this.$element = element; 39 | this.options = $.extend({}, Joyride.defaults, this.$element.data(), options); 40 | this._init(); 41 | 42 | Foundation.registerPlugin(this, 'Joyride'); 43 | Foundation.Keyboard.register('Joyride', { 44 | 'ltr': { 45 | 'ARROW_RIGHT': 'next', 46 | 'ARROW_LEFT': 'previous', 47 | 'ESCAPE': 'close' 48 | }, 49 | 'rtl': { 50 | 'ARROW_RIGHT': 'previous', 51 | 'ARROW_LEFT': 'next' 52 | } 53 | }); 54 | 55 | } 56 | 57 | 58 | 59 | /** 60 | * Initializes the joyride by rendering required markup 61 | * @private 62 | */ 63 | _init() { 64 | this.id = this.$element.attr('id') || Foundation.GetYoDigits(6, 'joyride'); 65 | this.current = 0; 66 | this.$items = $([]); // initialize empty collection 67 | this.structure = this._parseList(); 68 | this._render(this.structure); 69 | this._events(); 70 | 71 | if (this.options.autostart) { 72 | this.start(); 73 | } 74 | } 75 | 76 | /** 77 | * Parses the list of the instance, stored in $element. 78 | * @private 79 | * @return {Array} structure 80 | */ 81 | _parseList() { 82 | var structure = []; 83 | this.$element.find('li').each(function(i) { 84 | var item = $.extend({}, { 85 | text: $(this).html(), 86 | $target: $($(this).data('target')), 87 | isModal: !!!$($(this).data('target')).length, 88 | closable: Joyride.defaults.closable 89 | }, $(this).data()); 90 | structure.push(item); 91 | }); 92 | return structure; 93 | } 94 | 95 | /** 96 | * Creates the markup for the items 97 | * @private 98 | * @param {Array} structure the joyride's structure from _parseList 99 | * @return {Object} markup jQuery representation of the generated markup 100 | */ 101 | _render(structure) { 102 | for (var s in structure) { 103 | var options = $.extend({}, this.options, structure[s]),// if specific item has config, this should overwrite global settings 104 | $item; 105 | 106 | if (options.$target.length) { // target element exists, create tooltip 107 | var tooltip = new Foundation.Tooltip(structure[s].$target, { 108 | positionClass: options.position, 109 | disableHover: true, 110 | clickOpen: false, 111 | tooltipClass: 'tooltip joyride', 112 | triggerClass: '', 113 | hOffset: this.options.hOffset, 114 | vOffset: this.options.vOffset, 115 | showOn: 'all' // to avoid conflicts with standalone version when MQs are not set up properly. Should be somewhat rewritten 116 | }); 117 | this.structure[s].item = tooltip; 118 | $item = tooltip.template; 119 | 120 | } else { // not target, create modal with Reveal 121 | var modal = new Foundation.Reveal($('
').appendTo($('body'))); 122 | this.structure[s].item = modal; 123 | $item = modal.$element; 124 | } 125 | $item.attr({ 126 | 'data-index': s, 127 | 'data-joyride-for': structure[s].target 128 | }) 129 | .html(structure[s].text); 130 | if (options.keyboardAccess) { 131 | $item.attr('tabindex', '-1'); 132 | } 133 | 134 | this.$items = this.$items.add($item); 135 | 136 | // add buttons 137 | if ( 138 | (structure[s].nextText || (options.showNext && s < structure.length -1)) 139 | || (structure[s].prevText || (options.showPrev && s > 0)) 140 | ) { 141 | var $buttons = $('
'); 142 | if (structure[s].prevText || (options.showPrev && s > 0)) { 143 | $buttons.append($(this.options.prevButton).text(options.prevText)); 144 | } 145 | if (structure[s].nextText || (options.showNext && s < structure.length -1)) { 146 | $buttons.append($(this.options.nextButton).text(options.nextText)); 147 | } 148 | $item.append($buttons); 149 | } 150 | 151 | // add close button 152 | if (options.closable) { 153 | var $close = $(this.options.closeButton); 154 | $close.find('.show-for-sr').text(this.options.closeText); 155 | $item.prepend($close); 156 | } 157 | } 158 | } 159 | 160 | /** 161 | * Shows the item with the given index 162 | * @private 163 | * @param {Number} index of the item to be displayed 164 | */ 165 | _showItem(index) { 166 | if (this.structure[index].isModal) { 167 | this.structure[index].item.open(); 168 | } else { 169 | this.structure[index].item.show(); 170 | } 171 | // scroll target into view if target exists 172 | if (this.structure[index].$target.length) { 173 | $('html, body').stop().animate({ 174 | 'scrollTop': Math.max(0, this.$items.eq(index).offset().top - this.options.scrollOffset) 175 | }, this.options.scrollSpeed); 176 | } 177 | if (this.options.keyboardAccess) { 178 | this.$items.eq(index).focus(); 179 | } 180 | this.current = index; 181 | } 182 | 183 | /** 184 | * Hides the item with the given index 185 | * @private 186 | * @param {Number} index of the item to be hidden 187 | */ 188 | _hideItem(index) { 189 | if (this.structure[index].isModal) { 190 | this.structure[index].item.close(); 191 | } else { 192 | this.structure[index].item.hide(); 193 | } 194 | } 195 | 196 | /** 197 | * Hides all items 198 | * @private 199 | */ 200 | _hideAll() { 201 | for (var s in this.structure) { 202 | this._hideItem(s); 203 | } 204 | } 205 | 206 | /** 207 | * Shows the next item in the ride 208 | * @private 209 | */ 210 | showNext() { 211 | this._hideItem(this.current); 212 | this._showItem(this.current + 1); 213 | } 214 | 215 | /** 216 | * Shows the previous item in the ride 217 | * @private 218 | */ 219 | showPrev() { 220 | this._hideItem(this.current); 221 | this._showItem(this.current - 1); 222 | } 223 | 224 | /** 225 | * Starts the ride 226 | * @private 227 | * @return {Number} index - the index where to start, 0 by default 228 | */ 229 | start(index) { 230 | var index = index || 0; 231 | this._hideAll(); 232 | this._showItem(index); 233 | } 234 | 235 | /** 236 | * Adds event handlers for the modal. 237 | * @private 238 | */ 239 | _events() { 240 | var _this = this; 241 | $('[data-joyride-start="#'+_this.id+'"]').click(function() { 242 | _this.start(); 243 | }); 244 | 245 | this.$items.on('click.zf.joyride', '[data-joyride-next]', function(e) { 246 | _this.showNext(); 247 | }).on('click.zf.joyride', '[data-joyride-prev]', function(e) { 248 | _this.showPrev(); 249 | }).on('click.zf.joyride', '[data-joyride-close]', function(e) { 250 | e.preventDefault(); 251 | if (_this.structure[_this.current].closable) { 252 | _this._hideItem(_this.current); 253 | } 254 | }).on('keydown.zf.joyride', function(e) { 255 | var $element = $(this); 256 | Foundation.Keyboard.handleKey(e, 'Joyride', { 257 | next: function() { 258 | if ($element.data('index') < _this.structure.length - 1) { 259 | _this.showNext(); 260 | } 261 | }, 262 | previous: function() { 263 | if ($element.data('index') > 0) { 264 | _this.showPrev(); 265 | } 266 | }, 267 | close: function() { 268 | if (_this.structure[_this.current].closable) { 269 | _this._hideItem(_this.current); 270 | } 271 | }, 272 | handled: function() { 273 | e.preventDefault(); 274 | } 275 | }); 276 | }); 277 | } 278 | 279 | /** 280 | * Destroys an instance of a Joyride. 281 | * @fires Joyride#destroyed 282 | */ 283 | destroy() { 284 | this.$element.hide(); 285 | 286 | for (var s in this.structure) { 287 | this.structure[s].item.destroy(); 288 | } 289 | 290 | /** 291 | * Fires when the plugin has been destroyed. 292 | * @event Joyride#destroyed 293 | */ 294 | this.$element.trigger('destroyed.zf.joyride'); 295 | 296 | Foundation.unregisterPlugin(this); 297 | } 298 | } 299 | 300 | Joyride.defaults = { 301 | /** 302 | * Autostart the joyride on page load. 303 | * @option 304 | * @example false 305 | */ 306 | autostart: false, 307 | /** 308 | * Speed with which the page scrolls to the next stop. 309 | * @option 310 | * @example 1000 311 | */ 312 | scrollSpeed: 1000, 313 | /** 314 | * Enable navigation via keyboard. 315 | * @option 316 | * @example true 317 | */ 318 | keyboardAccess: true, 319 | /** 320 | * If the joyride elements should be closable. 321 | * @option 322 | * @example true 323 | */ 324 | closable: true, 325 | /** 326 | * Text for the next button. 327 | * @option 328 | * @example 'Next' 329 | */ 330 | nextText: 'Next', 331 | /** 332 | * Text for the previous button. 333 | * @option 334 | * @example 'Previous' 335 | */ 336 | prevText: 'Previous', 337 | /** 338 | * Text for the close button (for accessibility purposes). 339 | * @option 340 | * @example 'Close' 341 | */ 342 | closeText: 'Close', 343 | /** 344 | * Whether to show next button. 345 | * @option 346 | * @example true 347 | */ 348 | showNext: true, 349 | /** 350 | * Whether to show previous button. 351 | * @option 352 | * @example true 353 | */ 354 | showPrev: true, 355 | /** 356 | * Vertical offset for tooltips (see tooltip plugin configuration). 357 | * @option 358 | * @example true 359 | */ 360 | vOffset: 10, 361 | /** 362 | * Horizontal offset for tooltips (see tooltip plugin configuration). 363 | * @option 364 | * @example true 365 | */ 366 | hOffset: 12, 367 | /** 368 | * Offset while scrolling the window. 369 | * @option 370 | * @example 50 371 | */ 372 | scrollOffset: 50, 373 | /** 374 | * Position of the tooltips (see tooltip plugin configuration). 375 | * @option 376 | * @example true 377 | */ 378 | position: 'top center', 379 | /** 380 | * Templates for the close button. 381 | * @option 382 | * @example '' 383 | */ 384 | closeButton: '', 385 | /** 386 | * Templates for the next button. 387 | * @option 388 | * @example '' 389 | */ 390 | nextButton: '', 391 | /** 392 | * Templates for the pevious button. 393 | * @option 394 | * @example '' 395 | */ 396 | prevButton: '' 397 | }; 398 | 399 | // Window exports 400 | Foundation.plugin(Joyride, 'Joyride'); 401 | 402 | return Joyride; 403 | })); 404 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "foundation-joyride", 3 | "version": "3.0.0", 4 | "description": "Joyride plugin for Foundation 6.", 5 | "main": "dist/foundation.joyride.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/zurb/joyride" 9 | }, 10 | "keywords": [ 11 | "javascript", 12 | "joyride", 13 | "foundation" 14 | ], 15 | "author": "Marius Olbertz", 16 | "license": "MIT", 17 | "bugs": { 18 | "url": "https://github.com/zurb/joyride/issues" 19 | }, 20 | "homepage": "https://github.com/zurb/joyride", 21 | "scripts": { 22 | "start": "gulp", 23 | "test": "npm run test:javascript", 24 | "test:javascript": "gulp build:all && mocha-phantomjs test/javascript/index.html", 25 | "test:visual": "gulp", 26 | "dist": "gulp dist" 27 | }, 28 | "dependencies": { 29 | "jquery": "^2.2.0", 30 | "what-input": "^2.0.0" 31 | }, 32 | "devDependencies": { 33 | "babel-core": "^6.3.26", 34 | "babel-eslint": "^5.0.0", 35 | "babel-plugin-transform-es2015-arrow-functions": "^6.3.13", 36 | "babel-plugin-transform-es2015-block-scoped-functions": "^6.3.13", 37 | "babel-plugin-transform-es2015-block-scoping": "^6.4.0", 38 | "babel-plugin-transform-es2015-classes": "^6.3.15", 39 | "babel-plugin-transform-es2015-destructuring": "^6.3.15", 40 | "babel-plugin-transform-es2015-parameters": "^6.3.26", 41 | "babel-plugin-transform-es2015-shorthand-properties": "^6.5.0", 42 | "babel-plugin-transform-es2015-spread": "^6.4.0", 43 | "babel-plugin-transform-es2015-template-literals": "^6.3.13", 44 | "browser-sync": "^2.11.2", 45 | "chai-jquery": "^2.0.0", 46 | "chalk": "^1.1.1", 47 | "foundation-sites": "~6.3.1", 48 | "gulp": "^3.9.0", 49 | "gulp-autoprefixer": "^3.1.0", 50 | "gulp-babel": "^6.1.2", 51 | "gulp-compressor": "^0.1.0", 52 | "gulp-concat": "^2.6.0", 53 | "gulp-minify-css": "^1.2.1", 54 | "gulp-mocha": "^2.2.0", 55 | "gulp-mustache": "^2.2.0", 56 | "gulp-rename": "^1.2.2", 57 | "gulp-ruby-sass": "^2.0.5", 58 | "gulp-uglify": "^1.4.2", 59 | "gulp-util": "^3.0.7", 60 | "mocha": "^2.4.5", 61 | "mocha-phantomjs": "^4.0.2", 62 | "motion-ui": "^1.2.2", 63 | "opener": "^1.4.1", 64 | "require-dir": "^0.3.0", 65 | "rimraf": "^2.5.2", 66 | "run-sequence": "^1.1.5" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /scss/foundation_dependencies.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Import dependency SASS files that are needed. 3 | * 4 | * Based on: 5 | * Foundation for Sites by ZURB 6 | * foundation.zurb.com 7 | * Licensed under MIT Open Source 8 | */ 9 | 10 | 11 | // Sass utilities 12 | @import '../node_modules/foundation-sites/scss/util/util'; 13 | 14 | // Global variables and styles 15 | @import '../node_modules/foundation-sites/scss/global'; 16 | 17 | // Components 18 | @import '../node_modules/foundation-sites/scss/typography/typography'; 19 | @import '../node_modules/foundation-sites/scss/components/visibility'; 20 | 21 | 22 | {{#components}} 23 | @import '../node_modules/foundation-sites/scss/components/{{.}}'; 24 | {{/components}} 25 | 26 | 27 | // Imports 28 | @include foundation-visibility-classes; 29 | 30 | {{#components}} 31 | @include foundation-{{.}}; 32 | {{/components}} -------------------------------------------------------------------------------- /scss/joyride.scss: -------------------------------------------------------------------------------- 1 | 2 | // foundation.zurb.com 3 | // Licensed under MIT Open Source 4 | 5 | 6 | //// 7 | /// @group joyride 8 | //// 9 | 10 | /// Default padding of the joyride background. 11 | /// @type Number 12 | $joyride-padding: 0.5em; 13 | 14 | /// Default font size for joyride tiems. 15 | /// @type Number 16 | $joyride-font-size: 100%; 17 | 18 | /// Default min-width of joyride items. 19 | /// @type Number 20 | $joyride-min-width: 20rem; 21 | 22 | /// Margin between the buttons to navigate. 23 | /// @type Number 24 | $joyride-button-space: 0.5em; 25 | 26 | [data-joyride] { 27 | display: none; 28 | } 29 | 30 | .tooltip.joyride, 31 | .reveal.joyride { 32 | font-size: $joyride-font-size; 33 | min-width: $joyride-min-width; 34 | padding: $joyride-padding; 35 | 36 | 37 | .close { 38 | float: right; 39 | } 40 | 41 | .joyride-buttons { 42 | text-align: center; 43 | 44 | button { 45 | margin: 0 $joyride-button-space; 46 | } 47 | } 48 | } 49 | 50 | [data-whatinput='mouse'] .joyride { 51 | outline: 0; 52 | } -------------------------------------------------------------------------------- /test/javascript/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Mocha 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | 24 | 25 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /test/javascript/joyride.js: -------------------------------------------------------------------------------- 1 | describe('Joyride', function() { 2 | var plugin; 3 | var $html; 4 | var joyrideListHtml = '

Target 1

Target 2

' 5 | +'
    ' 6 | + '
  1. ' 7 | + '

    First

    ' 8 | + '
  2. ' 9 | + '
  3. ' 10 | + '

    Second

    ' 11 | + '
  4. ' 12 | + '
'; 13 | 14 | afterEach(function() { 15 | plugin.destroy(); 16 | $html.remove(); 17 | }); 18 | 19 | describe('constructor()', function() { 20 | it('stores the element and plugin options', function() { 21 | $html = $(joyrideListHtml).appendTo('body'); 22 | plugin = new Foundation.Joyride($html.find('[data-joyride]'), {}); 23 | 24 | plugin.$element.should.be.an('object'); 25 | plugin.options.should.be.an('object'); 26 | }); 27 | }); 28 | 29 | describe('_init()', function() { 30 | it('hides the joyride list', function() { 31 | $html = $(joyrideListHtml).appendTo('body'); 32 | plugin = new Foundation.Joyride($html.find('[data-joyride]'), {}); 33 | 34 | plugin.$element.should.have.attr('data-joyride'); 35 | plugin.$element.should.be.hidden; 36 | }); 37 | }); 38 | 39 | describe('_render()', function() { 40 | it('creates tooltips for stops with target', function() { 41 | $html = $(joyrideListHtml).appendTo('body'); 42 | plugin = new Foundation.Joyride($html.find('[data-joyride]'), {}); 43 | 44 | plugin.structure[0].item.$element.should.have.attr('data-tooltip'); 45 | }); 46 | 47 | it('creates reveal modals for stops without target', function() { 48 | $html = $(joyrideListHtml); 49 | $html.find('li').removeAttr('data-target'); 50 | $html.appendTo('body'); 51 | plugin = new Foundation.Joyride($html.find('[data-joyride]'), {}); 52 | 53 | plugin.structure[0].item.$element.should.have.attr('data-reveal'); 54 | }); 55 | }); 56 | 57 | describe('start()', function() { 58 | it('starts joyride automatically', function() { 59 | $html = $(joyrideListHtml).appendTo('body'); 60 | plugin = new Foundation.Joyride($html.find('[data-joyride]'), {}); 61 | plugin.start(); 62 | 63 | $(plugin.$items[0]).should.be.visible; 64 | }); 65 | 66 | it('starts joyride by clicking', function() { 67 | $html = $(joyrideListHtml); 68 | $html.find('[data-joyride]').attr({'data-autostart': false, 'id': 'test-joyride'}); 69 | 70 | var $button = $(''); 71 | $html.append($button); 72 | $html.appendTo('body'); 73 | plugin = new Foundation.Joyride($html.find('[data-joyride]'), {}); 74 | 75 | $button.trigger('click'); 76 | 77 | $(plugin.$items[0]).should.have.attr('aria-hidden', 'false'); 78 | }); 79 | }); 80 | 81 | describe('showNext()', function() { 82 | it('hides the current element', function() { 83 | $html = $(joyrideListHtml).appendTo('body'); 84 | plugin = new Foundation.Joyride($html.find('[data-joyride]'), {}); 85 | plugin.start(); 86 | 87 | plugin.showNext(); 88 | $(plugin.$items[0]).should.have.attr('aria-hidden', 'true'); 89 | }); 90 | 91 | it('shows the next element', function() { 92 | $html = $(joyrideListHtml).appendTo('body'); 93 | plugin = new Foundation.Joyride($html.find('[data-joyride]'), {}); 94 | plugin.start(); 95 | 96 | plugin.showNext(); 97 | $(plugin.$items[1]).should.have.attr('aria-hidden', 'false'); 98 | }); 99 | }); 100 | 101 | describe('showPrev()', function() { 102 | it('hides the current element', function() { 103 | $html = $(joyrideListHtml).appendTo('body'); 104 | plugin = new Foundation.Joyride($html.find('[data-joyride]'), {}); 105 | plugin.start(); 106 | 107 | plugin.showNext(); 108 | plugin.showPrev(); 109 | $(plugin.$items[1]).should.have.attr('aria-hidden', 'true'); 110 | }); 111 | 112 | it('shows the previous element', function() { 113 | $html = $(joyrideListHtml).appendTo('body'); 114 | plugin = new Foundation.Joyride($html.find('[data-joyride]'), {}); 115 | plugin.start(); 116 | 117 | plugin.showNext(); 118 | plugin.showPrev(); 119 | $(plugin.$items[0]).should.have.attr('aria-hidden', 'false'); 120 | }); 121 | }); 122 | }); 123 | -------------------------------------------------------------------------------- /test/javascript/lib/chai-jquery.js: -------------------------------------------------------------------------------- 1 | (function (chaiJquery) { 2 | // Module systems magic dance. 3 | if (typeof require === "function" && typeof exports === "object" && typeof module === "object") { 4 | // NodeJS 5 | module.exports = chaiJquery; 6 | } else if (typeof define === "function" && define.amd) { 7 | // AMD 8 | define(['jquery'], function ($) { 9 | return function (chai, utils) { 10 | return chaiJquery(chai, utils, $); 11 | }; 12 | }); 13 | } else { 14 | // Other environment (usually 132 | 133 | 134 | 135 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /test/visual/standalone.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Joyride 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 |
17 |
18 |
19 |
20 |

Joyride

21 |

22 | Joyride plugin for Foundation 6. 23 |

24 |
25 |
26 |
27 | 38 |
39 |
40 |
41 |

Basic Joyride

42 | 43 |

44 | Joyride makes use of the Tooltip component, so it is required to also have it included in your project. 45 | You can define your Joyride stops by creating a HTML list and adding the `data-joyride` attribute. Make sure that the data-target attribute within the li-tags matches the id of the element you want to address. 46 |

47 |
<ol data-joyride data-autostart="true" id="docs-joyride">
 48 |   <li data-target="#basic-joyride">
 49 |     <h3>First</h3>
 50 |     <p>This is the default one without settings</p>
 51 |   </li>
 52 |   <li data-target="#sass-reference" data-next-text="Weiter" data-prev-text="Zurück">
 53 |     <h3>Second</h3>
 54 |     <p>This is the default one with custom texts</p>
 55 |   </li>
 56 |   <li data-target="#js-class" data-position="bottom" data-closable="false">
 57 |     <h3>Third</h3>
 58 |     <p>This one isn't closable</p>
 59 |   </li>
 60 |   <li>
 61 |     <h3>Fourth</h3>
 62 |     <p>If no target is specified, you create a modal.</p>
 63 |   </li>
 64 |   <li data-target="#trigger-start">
 65 |     <h3>Fifth</h3>
 66 |     <p>Your ride ends here!</p>
 67 |     <button class="button success" data-joyride-close>OK, thanks!</button>
 68 |   </li>
 69 | </ol>
70 |

Trigger start

71 |

72 | You can either have the Joyride start on page load, or by defining a button, etc. To enable auto start, set the data-autostart attribute of the list to true. A custom trigger can be defined by adding the data-joyride-start attribute pointing at the Joyride instance you want to start. 73 |

74 | 75 |

76 | 77 |

78 | 79 |

Open issues

80 |

81 | The following things are still open: 82 | 83 |

    84 |
  • Some sort of cookie usage to remember if the user already had a ride
  • 85 |
  • Proper testing
  • 86 |
  • Example as Markdown
  • 87 |
  • Align Gulp tasks and implement watching
  • 88 |
89 |

90 |
91 |
92 |
93 | 100 |
101 | 102 | 103 |
    104 |
  1. 105 |

    First

    106 |

    This is the default one without settings

    107 |
  2. 108 |
  3. 109 |

    Second

    110 |

    This is the default one with custom texts

    111 |
  4. 112 |
  5. 113 |

    Third

    114 |

    This one isn't closable

    115 |
  6. 116 |
  7. 117 |

    Fourth

    118 |

    If no target is specified, you create a modal.

    119 |
  8. 120 |
  9. 121 |

    Fifth

    122 |

    Your ride ends here!

    123 |

    124 | 125 |

    126 |
  10. 127 |
128 | 129 | 130 | 131 | 132 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /test/visual/umd.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Joyride 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 |
18 |
19 |
20 |
21 |

Joyride

22 |

23 | Joyride plugin for Foundation 6. 24 |

25 |
26 |
27 |
28 | 39 |
40 |
41 |
42 |

Basic Joyride

43 | 44 |

45 | Joyride makes use of the Tooltip component, so it is required to also have it included in your project. 46 | You can define your Joyride stops by creating a HTML list and adding the `data-joyride` attribute. Make sure that the data-target attribute within the li-tags matches the id of the element you want to address. 47 |

48 |
<ol data-joyride data-autostart="true" id="docs-joyride">
 49 |   <li data-target="#basic-joyride">
 50 |     <h3>First</h3>
 51 |     <p>This is the default one without settings</p>
 52 |   </li>
 53 |   <li data-target="#sass-reference" data-next-text="Weiter" data-prev-text="Zurück">
 54 |     <h3>Second</h3>
 55 |     <p>This is the default one with custom texts</p>
 56 |   </li>
 57 |   <li data-target="#js-class" data-position="bottom" data-closable="false">
 58 |     <h3>Third</h3>
 59 |     <p>This one isn't closable</p>
 60 |   </li>
 61 |   <li>
 62 |     <h3>Fourth</h3>
 63 |     <p>If no target is specified, you create a modal.</p>
 64 |   </li>
 65 |   <li data-target="#trigger-start">
 66 |     <h3>Fifth</h3>
 67 |     <p>Your ride ends here!</p>
 68 |     <button class="button success" data-joyride-close>OK, thanks!</button>
 69 |   </li>
 70 | </ol>
71 |

Trigger start

72 |

73 | You can either have the Joyride start on page load, or by defining a button, etc. To enable auto start, set the data-autostart attribute of the list to true. A custom trigger can be defined by adding the data-joyride-start attribute pointing at the Joyride instance you want to start. 74 |

75 | 76 |

77 | 78 |

79 | 80 |

Open issues

81 |

82 | The following things are still open: 83 | 84 |

    85 |
  • Some sort of cookie usage to remember if the user already had a ride
  • 86 |
  • Proper testing
  • 87 |
  • Example as Markdown
  • 88 |
  • Align Gulp tasks and implement watching
  • 89 |
90 |

91 |
92 |
93 |
94 | 101 |
102 | 103 | 104 |
    105 |
  1. 106 |

    First

    107 |

    This is the default one without settings

    108 |
  2. 109 |
  3. 110 |

    Second

    111 |

    This is the default one with custom texts

    112 |
  4. 113 |
  5. 114 |

    Third

    115 |

    This one isn't closable

    116 |
  6. 117 |
  7. 118 |

    Fourth

    119 |

    If no target is specified, you create a modal.

    120 |
  8. 121 |
  9. 122 |

    Fifth

    123 |

    Your ride ends here!

    124 |

    125 | 126 |

    127 |
  10. 128 |
129 | 130 | 131 | 132 | 158 | 159 | 160 | --------------------------------------------------------------------------------