├── .gitignore ├── .travis.yml ├── Gruntfile.js ├── README.md ├── bower.json ├── css ├── libs │ └── animate.css └── site.css ├── demo.html ├── dist ├── wow.js └── wow.min.js ├── package.json ├── spec ├── coffeescripts │ ├── helpers │ │ └── SpecHelper.coffee │ └── wow-spec.coffee └── javascripts │ ├── fixtures │ ├── custom.html │ └── simple.html │ ├── helpers │ └── SpecHelper.js │ ├── libs │ ├── jasmine-jquery.js │ └── jquery.js │ └── wow-spec.js └── src └── wow.coffee /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .grunt/ 3 | node_modules/ 4 | _SpecRunner.html -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 0.10 4 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | /*global module:false*/ 2 | module.exports = function(grunt) { 3 | mainTasks = ['coffee', 'growl:coffee', 'jasmine', 'growl:jasmine', 'uglify'] 4 | 5 | // Project configuration. 6 | grunt.initConfig({ 7 | pkg: grunt.file.readJSON('package.json'), 8 | uglify: { 9 | dist: { 10 | files: { 11 | 'dist/wow.min.js': 'dist/wow.js' 12 | } 13 | }, 14 | options: { 15 | banner : '/*! <%= pkg.title %> - v<%= pkg.version %> - ' + 16 | '<%= grunt.template.today("yyyy-mm-dd") %>\n' + 17 | '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' + 18 | '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' + 19 | '*/', 20 | report: 'gzip' 21 | } 22 | }, 23 | coffee : { 24 | plugin : { 25 | files: [{ 26 | expand: true, 27 | cwd: 'src/', 28 | src: '*.coffee', 29 | dest: 'dist/', 30 | ext: '.js' 31 | }] 32 | }, 33 | specs : { 34 | files: [{ 35 | expand: true, 36 | cwd: 'spec/coffeescripts/', 37 | src: '*.coffee', 38 | dest: 'spec/javascripts/', 39 | ext: '.js' 40 | }] 41 | }, 42 | helpers : { 43 | files: [{ 44 | expand: true, 45 | cwd: 'spec/coffeescripts/helpers/', 46 | src: '*.coffee', 47 | dest: 'spec/javascripts/helpers/', 48 | ext: '.js' 49 | }] 50 | } 51 | }, 52 | jasmine : { 53 | src : ['spec/javascripts/libs/*.js', 'dist/wow.js'], 54 | options : { 55 | specs : 'spec/javascripts/**/*.js', 56 | helpers : 'spec/javascripts/helpers/**/*.js' 57 | } 58 | }, 59 | watch : { 60 | files: [ 61 | 'src/*', 62 | 'spec/coffeescripts/**/*.coffee' 63 | ], 64 | tasks: mainTasks 65 | }, 66 | growl : { 67 | coffee : { 68 | title : 'CoffeeScript', 69 | message : 'Compiled successfully' 70 | }, 71 | jasmine : { 72 | title : 'Jasmine', 73 | message : 'Tests passed successfully' 74 | } 75 | } 76 | }); 77 | 78 | // Lib tasks. 79 | grunt.loadNpmTasks('grunt-growl'); 80 | grunt.loadNpmTasks('grunt-contrib-jasmine'); 81 | grunt.loadNpmTasks('grunt-contrib-coffee'); 82 | grunt.loadNpmTasks('grunt-contrib-watch'); 83 | grunt.loadNpmTasks('grunt-contrib-uglify'); 84 | 85 | grunt.registerTask('default', mainTasks); 86 | 87 | // Travis CI task. 88 | grunt.registerTask('travis', ['coffee', 'jasmine']); 89 | }; 90 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WOW.js [![Build Status](https://secure.travis-ci.org/matthieua/WOW.svg?branch=master)](http://travis-ci.org/matthieua/WOW) 2 | 3 | Reveal CSS animation as you scroll down a page. 4 | By default, you can use it to trigger [animate.css](https://github.com/daneden/animate.css) animations. 5 | But you can easily change the settings to your favorite animation library. 6 | 7 | Advantages: 8 | - Smaller than other JavaScript parallax plugins, like Scrollorama (they do fantastic things, but can be too heavy for simple needs) 9 | - Super simple to install, and works with animate.css, so if you already use it, that will be very fast to setup 10 | - Fast execution and lightweight code: the browser will like it ;-) 11 | - You can change the settings - [see below](#advanced-usage) 12 | 13 | Follow [@mattdelac_](//twitter.com/mattdelac_) for updates as WOW evolves. 14 | 15 | ### [LIVE DEMO ➫](http://delac.io/WOW/) 16 | 17 | 18 | ## Version 19 | 20 | 1.1.3 21 | 22 | ## License 23 | 24 | ### Commercial license 25 | 26 | If you want to use WOW.js to develop commercial sites, themes, projects, and applications, the Commercial license is the appropriate license. With this option, your source code is kept proprietary. Purchase a WOW.js Commercial License at [uplabs.com/posts/wow-js-commercial](http://www.uplabs.com/posts/wow-js-commercial?utm_source=wow&utm_medium=pricing&utm_campaign=wow) 27 | 28 | ### Open source license 29 | If you are creating an open source application under a license compatible with the GNU GPL license v3, you may use this project under the terms of the GPLv3. 30 | 31 | 32 | 33 | ## Documentation 34 | 35 | It just take seconds to install and use WOW.js! 36 | [Read the documentation ➫](http://delac.io/WOW/docs.html) 37 | 38 | ### Dependencies 39 | - [animate.css](https://github.com/daneden/animate.css) 40 | 41 | ### Installation 42 | 43 | - Bower 44 | 45 | ```bash 46 | bower install wowjs 47 | ``` 48 | 49 | - NPM 50 | 51 | ```bash 52 | npm install wowjs 53 | ``` 54 | 55 | ### Basic usage 56 | In order to hide all elements when they are supposed to be hidden. (Anti Flickering) 57 | - CSS 58 | .wow { 59 | visibility: hidden; 60 | } 61 | 62 | - HTML 63 | 64 | ```html 65 |
66 |
67 | ``` 68 | 69 | - JavaScript 70 | 71 | ```javascript 72 | new WOW().init(); 73 | ``` 74 | 75 | ### Advanced usage 76 | 77 | - HTML 78 | 79 | ```html 80 |
81 |
82 | ``` 83 | 84 | - JavaScript 85 | 86 | ```javascript 87 | var wow = new WOW( 88 | { 89 | boxClass: 'wow', // animated element css class (default is wow) 90 | animateClass: 'animated', // animation css class (default is animated) 91 | offset: 0, // distance to the element when triggering the animation (default is 0) 92 | mobile: true, // trigger animations on mobile devices (default is true) 93 | live: true, // act on asynchronously loaded content (default is true) 94 | callback: function(box) { 95 | // the callback is fired every time an animation is started 96 | // the argument that is passed in is the DOM node being animated 97 | }, 98 | scrollContainer: null // optional scroll container selector, otherwise use window 99 | } 100 | ); 101 | wow.init(); 102 | ``` 103 | 104 | ### Asynchronous content support 105 | 106 | In IE 10+, Chrome 18+ and Firefox 14+, animations will be automatically 107 | triggered for any DOM nodes you add after calling `wow.init()`. If you do not 108 | like that, you can disable this by setting `live` to `false`. 109 | 110 | If you want to support older browsers (e.g. IE9+), as a fallback, you can call 111 | the `wow.sync()` method after you have added new DOM elements to animate (but 112 | `live` should still be set to `true`). Calling `wow.sync()` has no side 113 | effects. 114 | 115 | 116 | ## Contribute 117 | 118 | You're more than welcome to contribute to this project. Please note: your code may be used as part of a commercial product if merged. Be clear about what license applies to your patch. The MIT license or public domain unlicense are permissive, and allow integration of your patch into this project as part of a commercial product. 119 | 120 | The library is written in CoffeeScript, please update `wow.coffee` file. 121 | 122 | We use grunt to compile and minify the library: 123 | 124 | Install needed libraries 125 | 126 | ``` 127 | npm install 128 | ``` 129 | 130 | Get the compilation running in the background 131 | 132 | ``` 133 | grunt watch 134 | ``` 135 | 136 | Enjoy! 137 | 138 | ## Bug tracker 139 | 140 | If you find a bug, please report it [here on Github](https://github.com/matthieua/WOW/issues)! 141 | 142 | ## Developer 143 | 144 | Developed by Matt Delac, [delac.io](https://www.delac.io/) 145 | 146 | + [@mattdelac](//twitter.com/mattdelac_) 147 | + [Github Profile](//github.com/matthieua) 148 | 149 | ## Contributors 150 | 151 | Thanks to everyone who has contributed to the project so far: 152 | 153 | - Attila Oláh - [@attilaolah](//twitter.com/attilaolah) - [Github Profile](//github.com/attilaolah) 154 | - [and many others](//github.com/matthieua/WOW/graphs/contributors) 155 | 156 | Initiated and designed by [Vincent Le Moign](//www.webalys.com/), [@webalys](//twitter.com/webalys) 157 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wow", 3 | "homepage": "https://github.com/matthieua/WOW", 4 | "authors": [ 5 | "Matt Delac " 6 | ], 7 | "description": "Reveal CSS animation as you scroll down a page.", 8 | "main": "dist/wow.js", 9 | "keywords": [ 10 | "scroll", 11 | "animation", 12 | "reveal" 13 | ], 14 | "license": "GPLv3", 15 | "ignore": [ 16 | "**/.*", 17 | "node_modules", 18 | "bower_components", 19 | "test", 20 | "tests" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /css/libs/animate.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | 3 | 4 | /*! 5 | Animate.css - http://daneden.me/animate 6 | Licensed under the MIT license 7 | 8 | Copyright (c) 2013 Daniel Eden 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | 17 | .animated { 18 | -webkit-animation-duration: 1s; 19 | animation-duration: 1s; 20 | -webkit-animation-fill-mode: both; 21 | animation-fill-mode: both; 22 | } 23 | 24 | .animated.hinge { 25 | -webkit-animation-duration: 2s; 26 | animation-duration: 2s; 27 | } 28 | 29 | @-webkit-keyframes bounce { 30 | 0%, 20%, 50%, 80%, 100% { 31 | -webkit-transform: translateY(0); 32 | transform: translateY(0); 33 | } 34 | 35 | 40% { 36 | -webkit-transform: translateY(-30px); 37 | transform: translateY(-30px); 38 | } 39 | 40 | 60% { 41 | -webkit-transform: translateY(-15px); 42 | transform: translateY(-15px); 43 | } 44 | } 45 | 46 | @keyframes bounce { 47 | 0%, 20%, 50%, 80%, 100% { 48 | -webkit-transform: translateY(0); 49 | -ms-transform: translateY(0); 50 | transform: translateY(0); 51 | } 52 | 53 | 40% { 54 | -webkit-transform: translateY(-30px); 55 | -ms-transform: translateY(-30px); 56 | transform: translateY(-30px); 57 | } 58 | 59 | 60% { 60 | -webkit-transform: translateY(-15px); 61 | -ms-transform: translateY(-15px); 62 | transform: translateY(-15px); 63 | } 64 | } 65 | 66 | .bounce { 67 | -webkit-animation-name: bounce; 68 | animation-name: bounce; 69 | } 70 | 71 | @-webkit-keyframes flash { 72 | 0%, 50%, 100% { 73 | opacity: 1; 74 | } 75 | 76 | 25%, 75% { 77 | opacity: 0; 78 | } 79 | } 80 | 81 | @keyframes flash { 82 | 0%, 50%, 100% { 83 | opacity: 1; 84 | } 85 | 86 | 25%, 75% { 87 | opacity: 0; 88 | } 89 | } 90 | 91 | .flash { 92 | -webkit-animation-name: flash; 93 | animation-name: flash; 94 | } 95 | 96 | /* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ 97 | 98 | @-webkit-keyframes pulse { 99 | 0% { 100 | -webkit-transform: scale(1); 101 | transform: scale(1); 102 | } 103 | 104 | 50% { 105 | -webkit-transform: scale(1.1); 106 | transform: scale(1.1); 107 | } 108 | 109 | 100% { 110 | -webkit-transform: scale(1); 111 | transform: scale(1); 112 | } 113 | } 114 | 115 | @keyframes pulse { 116 | 0% { 117 | -webkit-transform: scale(1); 118 | -ms-transform: scale(1); 119 | transform: scale(1); 120 | } 121 | 122 | 50% { 123 | -webkit-transform: scale(1.1); 124 | -ms-transform: scale(1.1); 125 | transform: scale(1.1); 126 | } 127 | 128 | 100% { 129 | -webkit-transform: scale(1); 130 | -ms-transform: scale(1); 131 | transform: scale(1); 132 | } 133 | } 134 | 135 | .pulse { 136 | -webkit-animation-name: pulse; 137 | animation-name: pulse; 138 | } 139 | 140 | @-webkit-keyframes shake { 141 | 0%, 100% { 142 | -webkit-transform: translateX(0); 143 | transform: translateX(0); 144 | } 145 | 146 | 10%, 30%, 50%, 70%, 90% { 147 | -webkit-transform: translateX(-10px); 148 | transform: translateX(-10px); 149 | } 150 | 151 | 20%, 40%, 60%, 80% { 152 | -webkit-transform: translateX(10px); 153 | transform: translateX(10px); 154 | } 155 | } 156 | 157 | @keyframes shake { 158 | 0%, 100% { 159 | -webkit-transform: translateX(0); 160 | -ms-transform: translateX(0); 161 | transform: translateX(0); 162 | } 163 | 164 | 10%, 30%, 50%, 70%, 90% { 165 | -webkit-transform: translateX(-10px); 166 | -ms-transform: translateX(-10px); 167 | transform: translateX(-10px); 168 | } 169 | 170 | 20%, 40%, 60%, 80% { 171 | -webkit-transform: translateX(10px); 172 | -ms-transform: translateX(10px); 173 | transform: translateX(10px); 174 | } 175 | } 176 | 177 | .shake { 178 | -webkit-animation-name: shake; 179 | animation-name: shake; 180 | } 181 | 182 | @-webkit-keyframes swing { 183 | 20% { 184 | -webkit-transform: rotate(15deg); 185 | transform: rotate(15deg); 186 | } 187 | 188 | 40% { 189 | -webkit-transform: rotate(-10deg); 190 | transform: rotate(-10deg); 191 | } 192 | 193 | 60% { 194 | -webkit-transform: rotate(5deg); 195 | transform: rotate(5deg); 196 | } 197 | 198 | 80% { 199 | -webkit-transform: rotate(-5deg); 200 | transform: rotate(-5deg); 201 | } 202 | 203 | 100% { 204 | -webkit-transform: rotate(0deg); 205 | transform: rotate(0deg); 206 | } 207 | } 208 | 209 | @keyframes swing { 210 | 20% { 211 | -webkit-transform: rotate(15deg); 212 | -ms-transform: rotate(15deg); 213 | transform: rotate(15deg); 214 | } 215 | 216 | 40% { 217 | -webkit-transform: rotate(-10deg); 218 | -ms-transform: rotate(-10deg); 219 | transform: rotate(-10deg); 220 | } 221 | 222 | 60% { 223 | -webkit-transform: rotate(5deg); 224 | -ms-transform: rotate(5deg); 225 | transform: rotate(5deg); 226 | } 227 | 228 | 80% { 229 | -webkit-transform: rotate(-5deg); 230 | -ms-transform: rotate(-5deg); 231 | transform: rotate(-5deg); 232 | } 233 | 234 | 100% { 235 | -webkit-transform: rotate(0deg); 236 | -ms-transform: rotate(0deg); 237 | transform: rotate(0deg); 238 | } 239 | } 240 | 241 | .swing { 242 | -webkit-transform-origin: top center; 243 | -ms-transform-origin: top center; 244 | transform-origin: top center; 245 | -webkit-animation-name: swing; 246 | animation-name: swing; 247 | } 248 | 249 | @-webkit-keyframes tada { 250 | 0% { 251 | -webkit-transform: scale(1); 252 | transform: scale(1); 253 | } 254 | 255 | 10%, 20% { 256 | -webkit-transform: scale(0.9) rotate(-3deg); 257 | transform: scale(0.9) rotate(-3deg); 258 | } 259 | 260 | 30%, 50%, 70%, 90% { 261 | -webkit-transform: scale(1.1) rotate(3deg); 262 | transform: scale(1.1) rotate(3deg); 263 | } 264 | 265 | 40%, 60%, 80% { 266 | -webkit-transform: scale(1.1) rotate(-3deg); 267 | transform: scale(1.1) rotate(-3deg); 268 | } 269 | 270 | 100% { 271 | -webkit-transform: scale(1) rotate(0); 272 | transform: scale(1) rotate(0); 273 | } 274 | } 275 | 276 | @keyframes tada { 277 | 0% { 278 | -webkit-transform: scale(1); 279 | -ms-transform: scale(1); 280 | transform: scale(1); 281 | } 282 | 283 | 10%, 20% { 284 | -webkit-transform: scale(0.9) rotate(-3deg); 285 | -ms-transform: scale(0.9) rotate(-3deg); 286 | transform: scale(0.9) rotate(-3deg); 287 | } 288 | 289 | 30%, 50%, 70%, 90% { 290 | -webkit-transform: scale(1.1) rotate(3deg); 291 | -ms-transform: scale(1.1) rotate(3deg); 292 | transform: scale(1.1) rotate(3deg); 293 | } 294 | 295 | 40%, 60%, 80% { 296 | -webkit-transform: scale(1.1) rotate(-3deg); 297 | -ms-transform: scale(1.1) rotate(-3deg); 298 | transform: scale(1.1) rotate(-3deg); 299 | } 300 | 301 | 100% { 302 | -webkit-transform: scale(1) rotate(0); 303 | -ms-transform: scale(1) rotate(0); 304 | transform: scale(1) rotate(0); 305 | } 306 | } 307 | 308 | .tada { 309 | -webkit-animation-name: tada; 310 | animation-name: tada; 311 | } 312 | 313 | /* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ 314 | 315 | @-webkit-keyframes wobble { 316 | 0% { 317 | -webkit-transform: translateX(0%); 318 | transform: translateX(0%); 319 | } 320 | 321 | 15% { 322 | -webkit-transform: translateX(-25%) rotate(-5deg); 323 | transform: translateX(-25%) rotate(-5deg); 324 | } 325 | 326 | 30% { 327 | -webkit-transform: translateX(20%) rotate(3deg); 328 | transform: translateX(20%) rotate(3deg); 329 | } 330 | 331 | 45% { 332 | -webkit-transform: translateX(-15%) rotate(-3deg); 333 | transform: translateX(-15%) rotate(-3deg); 334 | } 335 | 336 | 60% { 337 | -webkit-transform: translateX(10%) rotate(2deg); 338 | transform: translateX(10%) rotate(2deg); 339 | } 340 | 341 | 75% { 342 | -webkit-transform: translateX(-5%) rotate(-1deg); 343 | transform: translateX(-5%) rotate(-1deg); 344 | } 345 | 346 | 100% { 347 | -webkit-transform: translateX(0%); 348 | transform: translateX(0%); 349 | } 350 | } 351 | 352 | @keyframes wobble { 353 | 0% { 354 | -webkit-transform: translateX(0%); 355 | -ms-transform: translateX(0%); 356 | transform: translateX(0%); 357 | } 358 | 359 | 15% { 360 | -webkit-transform: translateX(-25%) rotate(-5deg); 361 | -ms-transform: translateX(-25%) rotate(-5deg); 362 | transform: translateX(-25%) rotate(-5deg); 363 | } 364 | 365 | 30% { 366 | -webkit-transform: translateX(20%) rotate(3deg); 367 | -ms-transform: translateX(20%) rotate(3deg); 368 | transform: translateX(20%) rotate(3deg); 369 | } 370 | 371 | 45% { 372 | -webkit-transform: translateX(-15%) rotate(-3deg); 373 | -ms-transform: translateX(-15%) rotate(-3deg); 374 | transform: translateX(-15%) rotate(-3deg); 375 | } 376 | 377 | 60% { 378 | -webkit-transform: translateX(10%) rotate(2deg); 379 | -ms-transform: translateX(10%) rotate(2deg); 380 | transform: translateX(10%) rotate(2deg); 381 | } 382 | 383 | 75% { 384 | -webkit-transform: translateX(-5%) rotate(-1deg); 385 | -ms-transform: translateX(-5%) rotate(-1deg); 386 | transform: translateX(-5%) rotate(-1deg); 387 | } 388 | 389 | 100% { 390 | -webkit-transform: translateX(0%); 391 | -ms-transform: translateX(0%); 392 | transform: translateX(0%); 393 | } 394 | } 395 | 396 | .wobble { 397 | -webkit-animation-name: wobble; 398 | animation-name: wobble; 399 | } 400 | 401 | @-webkit-keyframes bounceIn { 402 | 0% { 403 | opacity: 0; 404 | -webkit-transform: scale(.3); 405 | transform: scale(.3); 406 | } 407 | 408 | 50% { 409 | opacity: 1; 410 | -webkit-transform: scale(1.05); 411 | transform: scale(1.05); 412 | } 413 | 414 | 70% { 415 | -webkit-transform: scale(.9); 416 | transform: scale(.9); 417 | } 418 | 419 | 100% { 420 | -webkit-transform: scale(1); 421 | transform: scale(1); 422 | } 423 | } 424 | 425 | @keyframes bounceIn { 426 | 0% { 427 | opacity: 0; 428 | -webkit-transform: scale(.3); 429 | -ms-transform: scale(.3); 430 | transform: scale(.3); 431 | } 432 | 433 | 50% { 434 | opacity: 1; 435 | -webkit-transform: scale(1.05); 436 | -ms-transform: scale(1.05); 437 | transform: scale(1.05); 438 | } 439 | 440 | 70% { 441 | -webkit-transform: scale(.9); 442 | -ms-transform: scale(.9); 443 | transform: scale(.9); 444 | } 445 | 446 | 100% { 447 | -webkit-transform: scale(1); 448 | -ms-transform: scale(1); 449 | transform: scale(1); 450 | } 451 | } 452 | 453 | .bounceIn { 454 | -webkit-animation-name: bounceIn; 455 | animation-name: bounceIn; 456 | } 457 | 458 | @-webkit-keyframes bounceInDown { 459 | 0% { 460 | opacity: 0; 461 | -webkit-transform: translateY(-2000px); 462 | transform: translateY(-2000px); 463 | } 464 | 465 | 60% { 466 | opacity: 1; 467 | -webkit-transform: translateY(30px); 468 | transform: translateY(30px); 469 | } 470 | 471 | 80% { 472 | -webkit-transform: translateY(-10px); 473 | transform: translateY(-10px); 474 | } 475 | 476 | 100% { 477 | -webkit-transform: translateY(0); 478 | transform: translateY(0); 479 | } 480 | } 481 | 482 | @keyframes bounceInDown { 483 | 0% { 484 | opacity: 0; 485 | -webkit-transform: translateY(-2000px); 486 | -ms-transform: translateY(-2000px); 487 | transform: translateY(-2000px); 488 | } 489 | 490 | 60% { 491 | opacity: 1; 492 | -webkit-transform: translateY(30px); 493 | -ms-transform: translateY(30px); 494 | transform: translateY(30px); 495 | } 496 | 497 | 80% { 498 | -webkit-transform: translateY(-10px); 499 | -ms-transform: translateY(-10px); 500 | transform: translateY(-10px); 501 | } 502 | 503 | 100% { 504 | -webkit-transform: translateY(0); 505 | -ms-transform: translateY(0); 506 | transform: translateY(0); 507 | } 508 | } 509 | 510 | .bounceInDown { 511 | -webkit-animation-name: bounceInDown; 512 | animation-name: bounceInDown; 513 | } 514 | 515 | @-webkit-keyframes bounceInLeft { 516 | 0% { 517 | opacity: 0; 518 | -webkit-transform: translateX(-2000px); 519 | transform: translateX(-2000px); 520 | } 521 | 522 | 60% { 523 | opacity: 1; 524 | -webkit-transform: translateX(30px); 525 | transform: translateX(30px); 526 | } 527 | 528 | 80% { 529 | -webkit-transform: translateX(-10px); 530 | transform: translateX(-10px); 531 | } 532 | 533 | 100% { 534 | -webkit-transform: translateX(0); 535 | transform: translateX(0); 536 | } 537 | } 538 | 539 | @keyframes bounceInLeft { 540 | 0% { 541 | opacity: 0; 542 | -webkit-transform: translateX(-2000px); 543 | -ms-transform: translateX(-2000px); 544 | transform: translateX(-2000px); 545 | } 546 | 547 | 60% { 548 | opacity: 1; 549 | -webkit-transform: translateX(30px); 550 | -ms-transform: translateX(30px); 551 | transform: translateX(30px); 552 | } 553 | 554 | 80% { 555 | -webkit-transform: translateX(-10px); 556 | -ms-transform: translateX(-10px); 557 | transform: translateX(-10px); 558 | } 559 | 560 | 100% { 561 | -webkit-transform: translateX(0); 562 | -ms-transform: translateX(0); 563 | transform: translateX(0); 564 | } 565 | } 566 | 567 | .bounceInLeft { 568 | -webkit-animation-name: bounceInLeft; 569 | animation-name: bounceInLeft; 570 | } 571 | 572 | @-webkit-keyframes bounceInRight { 573 | 0% { 574 | opacity: 0; 575 | -webkit-transform: translateX(2000px); 576 | transform: translateX(2000px); 577 | } 578 | 579 | 60% { 580 | opacity: 1; 581 | -webkit-transform: translateX(-30px); 582 | transform: translateX(-30px); 583 | } 584 | 585 | 80% { 586 | -webkit-transform: translateX(10px); 587 | transform: translateX(10px); 588 | } 589 | 590 | 100% { 591 | -webkit-transform: translateX(0); 592 | transform: translateX(0); 593 | } 594 | } 595 | 596 | @keyframes bounceInRight { 597 | 0% { 598 | opacity: 0; 599 | -webkit-transform: translateX(2000px); 600 | -ms-transform: translateX(2000px); 601 | transform: translateX(2000px); 602 | } 603 | 604 | 60% { 605 | opacity: 1; 606 | -webkit-transform: translateX(-30px); 607 | -ms-transform: translateX(-30px); 608 | transform: translateX(-30px); 609 | } 610 | 611 | 80% { 612 | -webkit-transform: translateX(10px); 613 | -ms-transform: translateX(10px); 614 | transform: translateX(10px); 615 | } 616 | 617 | 100% { 618 | -webkit-transform: translateX(0); 619 | -ms-transform: translateX(0); 620 | transform: translateX(0); 621 | } 622 | } 623 | 624 | .bounceInRight { 625 | -webkit-animation-name: bounceInRight; 626 | animation-name: bounceInRight; 627 | } 628 | 629 | @-webkit-keyframes bounceInUp { 630 | 0% { 631 | opacity: 0; 632 | -webkit-transform: translateY(2000px); 633 | transform: translateY(2000px); 634 | } 635 | 636 | 60% { 637 | opacity: 1; 638 | -webkit-transform: translateY(-30px); 639 | transform: translateY(-30px); 640 | } 641 | 642 | 80% { 643 | -webkit-transform: translateY(10px); 644 | transform: translateY(10px); 645 | } 646 | 647 | 100% { 648 | -webkit-transform: translateY(0); 649 | transform: translateY(0); 650 | } 651 | } 652 | 653 | @keyframes bounceInUp { 654 | 0% { 655 | opacity: 0; 656 | -webkit-transform: translateY(2000px); 657 | -ms-transform: translateY(2000px); 658 | transform: translateY(2000px); 659 | } 660 | 661 | 60% { 662 | opacity: 1; 663 | -webkit-transform: translateY(-30px); 664 | -ms-transform: translateY(-30px); 665 | transform: translateY(-30px); 666 | } 667 | 668 | 80% { 669 | -webkit-transform: translateY(10px); 670 | -ms-transform: translateY(10px); 671 | transform: translateY(10px); 672 | } 673 | 674 | 100% { 675 | -webkit-transform: translateY(0); 676 | -ms-transform: translateY(0); 677 | transform: translateY(0); 678 | } 679 | } 680 | 681 | .bounceInUp { 682 | -webkit-animation-name: bounceInUp; 683 | animation-name: bounceInUp; 684 | } 685 | 686 | @-webkit-keyframes bounceOut { 687 | 0% { 688 | -webkit-transform: scale(1); 689 | transform: scale(1); 690 | } 691 | 692 | 25% { 693 | -webkit-transform: scale(.95); 694 | transform: scale(.95); 695 | } 696 | 697 | 50% { 698 | opacity: 1; 699 | -webkit-transform: scale(1.1); 700 | transform: scale(1.1); 701 | } 702 | 703 | 100% { 704 | opacity: 0; 705 | -webkit-transform: scale(.3); 706 | transform: scale(.3); 707 | } 708 | } 709 | 710 | @keyframes bounceOut { 711 | 0% { 712 | -webkit-transform: scale(1); 713 | -ms-transform: scale(1); 714 | transform: scale(1); 715 | } 716 | 717 | 25% { 718 | -webkit-transform: scale(.95); 719 | -ms-transform: scale(.95); 720 | transform: scale(.95); 721 | } 722 | 723 | 50% { 724 | opacity: 1; 725 | -webkit-transform: scale(1.1); 726 | -ms-transform: scale(1.1); 727 | transform: scale(1.1); 728 | } 729 | 730 | 100% { 731 | opacity: 0; 732 | -webkit-transform: scale(.3); 733 | -ms-transform: scale(.3); 734 | transform: scale(.3); 735 | } 736 | } 737 | 738 | .bounceOut { 739 | -webkit-animation-name: bounceOut; 740 | animation-name: bounceOut; 741 | } 742 | 743 | @-webkit-keyframes bounceOutDown { 744 | 0% { 745 | -webkit-transform: translateY(0); 746 | transform: translateY(0); 747 | } 748 | 749 | 20% { 750 | opacity: 1; 751 | -webkit-transform: translateY(-20px); 752 | transform: translateY(-20px); 753 | } 754 | 755 | 100% { 756 | opacity: 0; 757 | -webkit-transform: translateY(2000px); 758 | transform: translateY(2000px); 759 | } 760 | } 761 | 762 | @keyframes bounceOutDown { 763 | 0% { 764 | -webkit-transform: translateY(0); 765 | -ms-transform: translateY(0); 766 | transform: translateY(0); 767 | } 768 | 769 | 20% { 770 | opacity: 1; 771 | -webkit-transform: translateY(-20px); 772 | -ms-transform: translateY(-20px); 773 | transform: translateY(-20px); 774 | } 775 | 776 | 100% { 777 | opacity: 0; 778 | -webkit-transform: translateY(2000px); 779 | -ms-transform: translateY(2000px); 780 | transform: translateY(2000px); 781 | } 782 | } 783 | 784 | .bounceOutDown { 785 | -webkit-animation-name: bounceOutDown; 786 | animation-name: bounceOutDown; 787 | } 788 | 789 | @-webkit-keyframes bounceOutLeft { 790 | 0% { 791 | -webkit-transform: translateX(0); 792 | transform: translateX(0); 793 | } 794 | 795 | 20% { 796 | opacity: 1; 797 | -webkit-transform: translateX(20px); 798 | transform: translateX(20px); 799 | } 800 | 801 | 100% { 802 | opacity: 0; 803 | -webkit-transform: translateX(-2000px); 804 | transform: translateX(-2000px); 805 | } 806 | } 807 | 808 | @keyframes bounceOutLeft { 809 | 0% { 810 | -webkit-transform: translateX(0); 811 | -ms-transform: translateX(0); 812 | transform: translateX(0); 813 | } 814 | 815 | 20% { 816 | opacity: 1; 817 | -webkit-transform: translateX(20px); 818 | -ms-transform: translateX(20px); 819 | transform: translateX(20px); 820 | } 821 | 822 | 100% { 823 | opacity: 0; 824 | -webkit-transform: translateX(-2000px); 825 | -ms-transform: translateX(-2000px); 826 | transform: translateX(-2000px); 827 | } 828 | } 829 | 830 | .bounceOutLeft { 831 | -webkit-animation-name: bounceOutLeft; 832 | animation-name: bounceOutLeft; 833 | } 834 | 835 | @-webkit-keyframes bounceOutRight { 836 | 0% { 837 | -webkit-transform: translateX(0); 838 | transform: translateX(0); 839 | } 840 | 841 | 20% { 842 | opacity: 1; 843 | -webkit-transform: translateX(-20px); 844 | transform: translateX(-20px); 845 | } 846 | 847 | 100% { 848 | opacity: 0; 849 | -webkit-transform: translateX(2000px); 850 | transform: translateX(2000px); 851 | } 852 | } 853 | 854 | @keyframes bounceOutRight { 855 | 0% { 856 | -webkit-transform: translateX(0); 857 | -ms-transform: translateX(0); 858 | transform: translateX(0); 859 | } 860 | 861 | 20% { 862 | opacity: 1; 863 | -webkit-transform: translateX(-20px); 864 | -ms-transform: translateX(-20px); 865 | transform: translateX(-20px); 866 | } 867 | 868 | 100% { 869 | opacity: 0; 870 | -webkit-transform: translateX(2000px); 871 | -ms-transform: translateX(2000px); 872 | transform: translateX(2000px); 873 | } 874 | } 875 | 876 | .bounceOutRight { 877 | -webkit-animation-name: bounceOutRight; 878 | animation-name: bounceOutRight; 879 | } 880 | 881 | @-webkit-keyframes bounceOutUp { 882 | 0% { 883 | -webkit-transform: translateY(0); 884 | transform: translateY(0); 885 | } 886 | 887 | 20% { 888 | opacity: 1; 889 | -webkit-transform: translateY(20px); 890 | transform: translateY(20px); 891 | } 892 | 893 | 100% { 894 | opacity: 0; 895 | -webkit-transform: translateY(-2000px); 896 | transform: translateY(-2000px); 897 | } 898 | } 899 | 900 | @keyframes bounceOutUp { 901 | 0% { 902 | -webkit-transform: translateY(0); 903 | -ms-transform: translateY(0); 904 | transform: translateY(0); 905 | } 906 | 907 | 20% { 908 | opacity: 1; 909 | -webkit-transform: translateY(20px); 910 | -ms-transform: translateY(20px); 911 | transform: translateY(20px); 912 | } 913 | 914 | 100% { 915 | opacity: 0; 916 | -webkit-transform: translateY(-2000px); 917 | -ms-transform: translateY(-2000px); 918 | transform: translateY(-2000px); 919 | } 920 | } 921 | 922 | .bounceOutUp { 923 | -webkit-animation-name: bounceOutUp; 924 | animation-name: bounceOutUp; 925 | } 926 | 927 | @-webkit-keyframes fadeIn { 928 | 0% { 929 | opacity: 0; 930 | } 931 | 932 | 100% { 933 | opacity: 1; 934 | } 935 | } 936 | 937 | @keyframes fadeIn { 938 | 0% { 939 | opacity: 0; 940 | } 941 | 942 | 100% { 943 | opacity: 1; 944 | } 945 | } 946 | 947 | .fadeIn { 948 | -webkit-animation-name: fadeIn; 949 | animation-name: fadeIn; 950 | } 951 | 952 | @-webkit-keyframes fadeInDown { 953 | 0% { 954 | opacity: 0; 955 | -webkit-transform: translateY(-20px); 956 | transform: translateY(-20px); 957 | } 958 | 959 | 100% { 960 | opacity: 1; 961 | -webkit-transform: translateY(0); 962 | transform: translateY(0); 963 | } 964 | } 965 | 966 | @keyframes fadeInDown { 967 | 0% { 968 | opacity: 0; 969 | -webkit-transform: translateY(-20px); 970 | -ms-transform: translateY(-20px); 971 | transform: translateY(-20px); 972 | } 973 | 974 | 100% { 975 | opacity: 1; 976 | -webkit-transform: translateY(0); 977 | -ms-transform: translateY(0); 978 | transform: translateY(0); 979 | } 980 | } 981 | 982 | .fadeInDown { 983 | -webkit-animation-name: fadeInDown; 984 | animation-name: fadeInDown; 985 | } 986 | 987 | @-webkit-keyframes fadeInDownBig { 988 | 0% { 989 | opacity: 0; 990 | -webkit-transform: translateY(-2000px); 991 | transform: translateY(-2000px); 992 | } 993 | 994 | 100% { 995 | opacity: 1; 996 | -webkit-transform: translateY(0); 997 | transform: translateY(0); 998 | } 999 | } 1000 | 1001 | @keyframes fadeInDownBig { 1002 | 0% { 1003 | opacity: 0; 1004 | -webkit-transform: translateY(-2000px); 1005 | -ms-transform: translateY(-2000px); 1006 | transform: translateY(-2000px); 1007 | } 1008 | 1009 | 100% { 1010 | opacity: 1; 1011 | -webkit-transform: translateY(0); 1012 | -ms-transform: translateY(0); 1013 | transform: translateY(0); 1014 | } 1015 | } 1016 | 1017 | .fadeInDownBig { 1018 | -webkit-animation-name: fadeInDownBig; 1019 | animation-name: fadeInDownBig; 1020 | } 1021 | 1022 | @-webkit-keyframes fadeInLeft { 1023 | 0% { 1024 | opacity: 0; 1025 | -webkit-transform: translateX(-20px); 1026 | transform: translateX(-20px); 1027 | } 1028 | 1029 | 100% { 1030 | opacity: 1; 1031 | -webkit-transform: translateX(0); 1032 | transform: translateX(0); 1033 | } 1034 | } 1035 | 1036 | @keyframes fadeInLeft { 1037 | 0% { 1038 | opacity: 0; 1039 | -webkit-transform: translateX(-20px); 1040 | -ms-transform: translateX(-20px); 1041 | transform: translateX(-20px); 1042 | } 1043 | 1044 | 100% { 1045 | opacity: 1; 1046 | -webkit-transform: translateX(0); 1047 | -ms-transform: translateX(0); 1048 | transform: translateX(0); 1049 | } 1050 | } 1051 | 1052 | .fadeInLeft { 1053 | -webkit-animation-name: fadeInLeft; 1054 | animation-name: fadeInLeft; 1055 | } 1056 | 1057 | @-webkit-keyframes fadeInLeftBig { 1058 | 0% { 1059 | opacity: 0; 1060 | -webkit-transform: translateX(-2000px); 1061 | transform: translateX(-2000px); 1062 | } 1063 | 1064 | 100% { 1065 | opacity: 1; 1066 | -webkit-transform: translateX(0); 1067 | transform: translateX(0); 1068 | } 1069 | } 1070 | 1071 | @keyframes fadeInLeftBig { 1072 | 0% { 1073 | opacity: 0; 1074 | -webkit-transform: translateX(-2000px); 1075 | -ms-transform: translateX(-2000px); 1076 | transform: translateX(-2000px); 1077 | } 1078 | 1079 | 100% { 1080 | opacity: 1; 1081 | -webkit-transform: translateX(0); 1082 | -ms-transform: translateX(0); 1083 | transform: translateX(0); 1084 | } 1085 | } 1086 | 1087 | .fadeInLeftBig { 1088 | -webkit-animation-name: fadeInLeftBig; 1089 | animation-name: fadeInLeftBig; 1090 | } 1091 | 1092 | @-webkit-keyframes fadeInRight { 1093 | 0% { 1094 | opacity: 0; 1095 | -webkit-transform: translateX(20px); 1096 | transform: translateX(20px); 1097 | } 1098 | 1099 | 100% { 1100 | opacity: 1; 1101 | -webkit-transform: translateX(0); 1102 | transform: translateX(0); 1103 | } 1104 | } 1105 | 1106 | @keyframes fadeInRight { 1107 | 0% { 1108 | opacity: 0; 1109 | -webkit-transform: translateX(20px); 1110 | -ms-transform: translateX(20px); 1111 | transform: translateX(20px); 1112 | } 1113 | 1114 | 100% { 1115 | opacity: 1; 1116 | -webkit-transform: translateX(0); 1117 | -ms-transform: translateX(0); 1118 | transform: translateX(0); 1119 | } 1120 | } 1121 | 1122 | .fadeInRight { 1123 | -webkit-animation-name: fadeInRight; 1124 | animation-name: fadeInRight; 1125 | } 1126 | 1127 | @-webkit-keyframes fadeInRightBig { 1128 | 0% { 1129 | opacity: 0; 1130 | -webkit-transform: translateX(2000px); 1131 | transform: translateX(2000px); 1132 | } 1133 | 1134 | 100% { 1135 | opacity: 1; 1136 | -webkit-transform: translateX(0); 1137 | transform: translateX(0); 1138 | } 1139 | } 1140 | 1141 | @keyframes fadeInRightBig { 1142 | 0% { 1143 | opacity: 0; 1144 | -webkit-transform: translateX(2000px); 1145 | -ms-transform: translateX(2000px); 1146 | transform: translateX(2000px); 1147 | } 1148 | 1149 | 100% { 1150 | opacity: 1; 1151 | -webkit-transform: translateX(0); 1152 | -ms-transform: translateX(0); 1153 | transform: translateX(0); 1154 | } 1155 | } 1156 | 1157 | .fadeInRightBig { 1158 | -webkit-animation-name: fadeInRightBig; 1159 | animation-name: fadeInRightBig; 1160 | } 1161 | 1162 | @-webkit-keyframes fadeInUp { 1163 | 0% { 1164 | opacity: 0; 1165 | -webkit-transform: translateY(20px); 1166 | transform: translateY(20px); 1167 | } 1168 | 1169 | 100% { 1170 | opacity: 1; 1171 | -webkit-transform: translateY(0); 1172 | transform: translateY(0); 1173 | } 1174 | } 1175 | 1176 | @keyframes fadeInUp { 1177 | 0% { 1178 | opacity: 0; 1179 | -webkit-transform: translateY(20px); 1180 | -ms-transform: translateY(20px); 1181 | transform: translateY(20px); 1182 | } 1183 | 1184 | 100% { 1185 | opacity: 1; 1186 | -webkit-transform: translateY(0); 1187 | -ms-transform: translateY(0); 1188 | transform: translateY(0); 1189 | } 1190 | } 1191 | 1192 | .fadeInUp { 1193 | -webkit-animation-name: fadeInUp; 1194 | animation-name: fadeInUp; 1195 | } 1196 | 1197 | @-webkit-keyframes fadeInUpBig { 1198 | 0% { 1199 | opacity: 0; 1200 | -webkit-transform: translateY(2000px); 1201 | transform: translateY(2000px); 1202 | } 1203 | 1204 | 100% { 1205 | opacity: 1; 1206 | -webkit-transform: translateY(0); 1207 | transform: translateY(0); 1208 | } 1209 | } 1210 | 1211 | @keyframes fadeInUpBig { 1212 | 0% { 1213 | opacity: 0; 1214 | -webkit-transform: translateY(2000px); 1215 | -ms-transform: translateY(2000px); 1216 | transform: translateY(2000px); 1217 | } 1218 | 1219 | 100% { 1220 | opacity: 1; 1221 | -webkit-transform: translateY(0); 1222 | -ms-transform: translateY(0); 1223 | transform: translateY(0); 1224 | } 1225 | } 1226 | 1227 | .fadeInUpBig { 1228 | -webkit-animation-name: fadeInUpBig; 1229 | animation-name: fadeInUpBig; 1230 | } 1231 | 1232 | @-webkit-keyframes fadeOut { 1233 | 0% { 1234 | opacity: 1; 1235 | } 1236 | 1237 | 100% { 1238 | opacity: 0; 1239 | } 1240 | } 1241 | 1242 | @keyframes fadeOut { 1243 | 0% { 1244 | opacity: 1; 1245 | } 1246 | 1247 | 100% { 1248 | opacity: 0; 1249 | } 1250 | } 1251 | 1252 | .fadeOut { 1253 | -webkit-animation-name: fadeOut; 1254 | animation-name: fadeOut; 1255 | } 1256 | 1257 | @-webkit-keyframes fadeOutDown { 1258 | 0% { 1259 | opacity: 1; 1260 | -webkit-transform: translateY(0); 1261 | transform: translateY(0); 1262 | } 1263 | 1264 | 100% { 1265 | opacity: 0; 1266 | -webkit-transform: translateY(20px); 1267 | transform: translateY(20px); 1268 | } 1269 | } 1270 | 1271 | @keyframes fadeOutDown { 1272 | 0% { 1273 | opacity: 1; 1274 | -webkit-transform: translateY(0); 1275 | -ms-transform: translateY(0); 1276 | transform: translateY(0); 1277 | } 1278 | 1279 | 100% { 1280 | opacity: 0; 1281 | -webkit-transform: translateY(20px); 1282 | -ms-transform: translateY(20px); 1283 | transform: translateY(20px); 1284 | } 1285 | } 1286 | 1287 | .fadeOutDown { 1288 | -webkit-animation-name: fadeOutDown; 1289 | animation-name: fadeOutDown; 1290 | } 1291 | 1292 | @-webkit-keyframes fadeOutDownBig { 1293 | 0% { 1294 | opacity: 1; 1295 | -webkit-transform: translateY(0); 1296 | transform: translateY(0); 1297 | } 1298 | 1299 | 100% { 1300 | opacity: 0; 1301 | -webkit-transform: translateY(2000px); 1302 | transform: translateY(2000px); 1303 | } 1304 | } 1305 | 1306 | @keyframes fadeOutDownBig { 1307 | 0% { 1308 | opacity: 1; 1309 | -webkit-transform: translateY(0); 1310 | -ms-transform: translateY(0); 1311 | transform: translateY(0); 1312 | } 1313 | 1314 | 100% { 1315 | opacity: 0; 1316 | -webkit-transform: translateY(2000px); 1317 | -ms-transform: translateY(2000px); 1318 | transform: translateY(2000px); 1319 | } 1320 | } 1321 | 1322 | .fadeOutDownBig { 1323 | -webkit-animation-name: fadeOutDownBig; 1324 | animation-name: fadeOutDownBig; 1325 | } 1326 | 1327 | @-webkit-keyframes fadeOutLeft { 1328 | 0% { 1329 | opacity: 1; 1330 | -webkit-transform: translateX(0); 1331 | transform: translateX(0); 1332 | } 1333 | 1334 | 100% { 1335 | opacity: 0; 1336 | -webkit-transform: translateX(-20px); 1337 | transform: translateX(-20px); 1338 | } 1339 | } 1340 | 1341 | @keyframes fadeOutLeft { 1342 | 0% { 1343 | opacity: 1; 1344 | -webkit-transform: translateX(0); 1345 | -ms-transform: translateX(0); 1346 | transform: translateX(0); 1347 | } 1348 | 1349 | 100% { 1350 | opacity: 0; 1351 | -webkit-transform: translateX(-20px); 1352 | -ms-transform: translateX(-20px); 1353 | transform: translateX(-20px); 1354 | } 1355 | } 1356 | 1357 | .fadeOutLeft { 1358 | -webkit-animation-name: fadeOutLeft; 1359 | animation-name: fadeOutLeft; 1360 | } 1361 | 1362 | @-webkit-keyframes fadeOutLeftBig { 1363 | 0% { 1364 | opacity: 1; 1365 | -webkit-transform: translateX(0); 1366 | transform: translateX(0); 1367 | } 1368 | 1369 | 100% { 1370 | opacity: 0; 1371 | -webkit-transform: translateX(-2000px); 1372 | transform: translateX(-2000px); 1373 | } 1374 | } 1375 | 1376 | @keyframes fadeOutLeftBig { 1377 | 0% { 1378 | opacity: 1; 1379 | -webkit-transform: translateX(0); 1380 | -ms-transform: translateX(0); 1381 | transform: translateX(0); 1382 | } 1383 | 1384 | 100% { 1385 | opacity: 0; 1386 | -webkit-transform: translateX(-2000px); 1387 | -ms-transform: translateX(-2000px); 1388 | transform: translateX(-2000px); 1389 | } 1390 | } 1391 | 1392 | .fadeOutLeftBig { 1393 | -webkit-animation-name: fadeOutLeftBig; 1394 | animation-name: fadeOutLeftBig; 1395 | } 1396 | 1397 | @-webkit-keyframes fadeOutRight { 1398 | 0% { 1399 | opacity: 1; 1400 | -webkit-transform: translateX(0); 1401 | transform: translateX(0); 1402 | } 1403 | 1404 | 100% { 1405 | opacity: 0; 1406 | -webkit-transform: translateX(20px); 1407 | transform: translateX(20px); 1408 | } 1409 | } 1410 | 1411 | @keyframes fadeOutRight { 1412 | 0% { 1413 | opacity: 1; 1414 | -webkit-transform: translateX(0); 1415 | -ms-transform: translateX(0); 1416 | transform: translateX(0); 1417 | } 1418 | 1419 | 100% { 1420 | opacity: 0; 1421 | -webkit-transform: translateX(20px); 1422 | -ms-transform: translateX(20px); 1423 | transform: translateX(20px); 1424 | } 1425 | } 1426 | 1427 | .fadeOutRight { 1428 | -webkit-animation-name: fadeOutRight; 1429 | animation-name: fadeOutRight; 1430 | } 1431 | 1432 | @-webkit-keyframes fadeOutRightBig { 1433 | 0% { 1434 | opacity: 1; 1435 | -webkit-transform: translateX(0); 1436 | transform: translateX(0); 1437 | } 1438 | 1439 | 100% { 1440 | opacity: 0; 1441 | -webkit-transform: translateX(2000px); 1442 | transform: translateX(2000px); 1443 | } 1444 | } 1445 | 1446 | @keyframes fadeOutRightBig { 1447 | 0% { 1448 | opacity: 1; 1449 | -webkit-transform: translateX(0); 1450 | -ms-transform: translateX(0); 1451 | transform: translateX(0); 1452 | } 1453 | 1454 | 100% { 1455 | opacity: 0; 1456 | -webkit-transform: translateX(2000px); 1457 | -ms-transform: translateX(2000px); 1458 | transform: translateX(2000px); 1459 | } 1460 | } 1461 | 1462 | .fadeOutRightBig { 1463 | -webkit-animation-name: fadeOutRightBig; 1464 | animation-name: fadeOutRightBig; 1465 | } 1466 | 1467 | @-webkit-keyframes fadeOutUp { 1468 | 0% { 1469 | opacity: 1; 1470 | -webkit-transform: translateY(0); 1471 | transform: translateY(0); 1472 | } 1473 | 1474 | 100% { 1475 | opacity: 0; 1476 | -webkit-transform: translateY(-20px); 1477 | transform: translateY(-20px); 1478 | } 1479 | } 1480 | 1481 | @keyframes fadeOutUp { 1482 | 0% { 1483 | opacity: 1; 1484 | -webkit-transform: translateY(0); 1485 | -ms-transform: translateY(0); 1486 | transform: translateY(0); 1487 | } 1488 | 1489 | 100% { 1490 | opacity: 0; 1491 | -webkit-transform: translateY(-20px); 1492 | -ms-transform: translateY(-20px); 1493 | transform: translateY(-20px); 1494 | } 1495 | } 1496 | 1497 | .fadeOutUp { 1498 | -webkit-animation-name: fadeOutUp; 1499 | animation-name: fadeOutUp; 1500 | } 1501 | 1502 | @-webkit-keyframes fadeOutUpBig { 1503 | 0% { 1504 | opacity: 1; 1505 | -webkit-transform: translateY(0); 1506 | transform: translateY(0); 1507 | } 1508 | 1509 | 100% { 1510 | opacity: 0; 1511 | -webkit-transform: translateY(-2000px); 1512 | transform: translateY(-2000px); 1513 | } 1514 | } 1515 | 1516 | @keyframes fadeOutUpBig { 1517 | 0% { 1518 | opacity: 1; 1519 | -webkit-transform: translateY(0); 1520 | -ms-transform: translateY(0); 1521 | transform: translateY(0); 1522 | } 1523 | 1524 | 100% { 1525 | opacity: 0; 1526 | -webkit-transform: translateY(-2000px); 1527 | -ms-transform: translateY(-2000px); 1528 | transform: translateY(-2000px); 1529 | } 1530 | } 1531 | 1532 | .fadeOutUpBig { 1533 | -webkit-animation-name: fadeOutUpBig; 1534 | animation-name: fadeOutUpBig; 1535 | } 1536 | 1537 | @-webkit-keyframes flip { 1538 | 0% { 1539 | -webkit-transform: perspective(400px) translateZ(0) rotateY(0) scale(1); 1540 | transform: perspective(400px) translateZ(0) rotateY(0) scale(1); 1541 | -webkit-animation-timing-function: ease-out; 1542 | animation-timing-function: ease-out; 1543 | } 1544 | 1545 | 40% { 1546 | -webkit-transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1); 1547 | transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1); 1548 | -webkit-animation-timing-function: ease-out; 1549 | animation-timing-function: ease-out; 1550 | } 1551 | 1552 | 50% { 1553 | -webkit-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1); 1554 | transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1); 1555 | -webkit-animation-timing-function: ease-in; 1556 | animation-timing-function: ease-in; 1557 | } 1558 | 1559 | 80% { 1560 | -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95); 1561 | transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95); 1562 | -webkit-animation-timing-function: ease-in; 1563 | animation-timing-function: ease-in; 1564 | } 1565 | 1566 | 100% { 1567 | -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1); 1568 | transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1); 1569 | -webkit-animation-timing-function: ease-in; 1570 | animation-timing-function: ease-in; 1571 | } 1572 | } 1573 | 1574 | @keyframes flip { 1575 | 0% { 1576 | -webkit-transform: perspective(400px) translateZ(0) rotateY(0) scale(1); 1577 | -ms-transform: perspective(400px) translateZ(0) rotateY(0) scale(1); 1578 | transform: perspective(400px) translateZ(0) rotateY(0) scale(1); 1579 | -webkit-animation-timing-function: ease-out; 1580 | animation-timing-function: ease-out; 1581 | } 1582 | 1583 | 40% { 1584 | -webkit-transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1); 1585 | -ms-transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1); 1586 | transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1); 1587 | -webkit-animation-timing-function: ease-out; 1588 | animation-timing-function: ease-out; 1589 | } 1590 | 1591 | 50% { 1592 | -webkit-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1); 1593 | -ms-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1); 1594 | transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1); 1595 | -webkit-animation-timing-function: ease-in; 1596 | animation-timing-function: ease-in; 1597 | } 1598 | 1599 | 80% { 1600 | -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95); 1601 | -ms-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95); 1602 | transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95); 1603 | -webkit-animation-timing-function: ease-in; 1604 | animation-timing-function: ease-in; 1605 | } 1606 | 1607 | 100% { 1608 | -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1); 1609 | -ms-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1); 1610 | transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1); 1611 | -webkit-animation-timing-function: ease-in; 1612 | animation-timing-function: ease-in; 1613 | } 1614 | } 1615 | 1616 | .animated.flip { 1617 | -webkit-backface-visibility: visible; 1618 | -ms-backface-visibility: visible; 1619 | backface-visibility: visible; 1620 | -webkit-animation-name: flip; 1621 | animation-name: flip; 1622 | } 1623 | 1624 | @-webkit-keyframes flipInX { 1625 | 0% { 1626 | -webkit-transform: perspective(400px) rotateX(90deg); 1627 | transform: perspective(400px) rotateX(90deg); 1628 | opacity: 0; 1629 | } 1630 | 1631 | 40% { 1632 | -webkit-transform: perspective(400px) rotateX(-10deg); 1633 | transform: perspective(400px) rotateX(-10deg); 1634 | } 1635 | 1636 | 70% { 1637 | -webkit-transform: perspective(400px) rotateX(10deg); 1638 | transform: perspective(400px) rotateX(10deg); 1639 | } 1640 | 1641 | 100% { 1642 | -webkit-transform: perspective(400px) rotateX(0deg); 1643 | transform: perspective(400px) rotateX(0deg); 1644 | opacity: 1; 1645 | } 1646 | } 1647 | 1648 | @keyframes flipInX { 1649 | 0% { 1650 | -webkit-transform: perspective(400px) rotateX(90deg); 1651 | -ms-transform: perspective(400px) rotateX(90deg); 1652 | transform: perspective(400px) rotateX(90deg); 1653 | opacity: 0; 1654 | } 1655 | 1656 | 40% { 1657 | -webkit-transform: perspective(400px) rotateX(-10deg); 1658 | -ms-transform: perspective(400px) rotateX(-10deg); 1659 | transform: perspective(400px) rotateX(-10deg); 1660 | } 1661 | 1662 | 70% { 1663 | -webkit-transform: perspective(400px) rotateX(10deg); 1664 | -ms-transform: perspective(400px) rotateX(10deg); 1665 | transform: perspective(400px) rotateX(10deg); 1666 | } 1667 | 1668 | 100% { 1669 | -webkit-transform: perspective(400px) rotateX(0deg); 1670 | -ms-transform: perspective(400px) rotateX(0deg); 1671 | transform: perspective(400px) rotateX(0deg); 1672 | opacity: 1; 1673 | } 1674 | } 1675 | 1676 | .flipInX { 1677 | -webkit-backface-visibility: visible !important; 1678 | -ms-backface-visibility: visible !important; 1679 | backface-visibility: visible !important; 1680 | -webkit-animation-name: flipInX; 1681 | animation-name: flipInX; 1682 | } 1683 | 1684 | @-webkit-keyframes flipInY { 1685 | 0% { 1686 | -webkit-transform: perspective(400px) rotateY(90deg); 1687 | transform: perspective(400px) rotateY(90deg); 1688 | opacity: 0; 1689 | } 1690 | 1691 | 40% { 1692 | -webkit-transform: perspective(400px) rotateY(-10deg); 1693 | transform: perspective(400px) rotateY(-10deg); 1694 | } 1695 | 1696 | 70% { 1697 | -webkit-transform: perspective(400px) rotateY(10deg); 1698 | transform: perspective(400px) rotateY(10deg); 1699 | } 1700 | 1701 | 100% { 1702 | -webkit-transform: perspective(400px) rotateY(0deg); 1703 | transform: perspective(400px) rotateY(0deg); 1704 | opacity: 1; 1705 | } 1706 | } 1707 | 1708 | @keyframes flipInY { 1709 | 0% { 1710 | -webkit-transform: perspective(400px) rotateY(90deg); 1711 | -ms-transform: perspective(400px) rotateY(90deg); 1712 | transform: perspective(400px) rotateY(90deg); 1713 | opacity: 0; 1714 | } 1715 | 1716 | 40% { 1717 | -webkit-transform: perspective(400px) rotateY(-10deg); 1718 | -ms-transform: perspective(400px) rotateY(-10deg); 1719 | transform: perspective(400px) rotateY(-10deg); 1720 | } 1721 | 1722 | 70% { 1723 | -webkit-transform: perspective(400px) rotateY(10deg); 1724 | -ms-transform: perspective(400px) rotateY(10deg); 1725 | transform: perspective(400px) rotateY(10deg); 1726 | } 1727 | 1728 | 100% { 1729 | -webkit-transform: perspective(400px) rotateY(0deg); 1730 | -ms-transform: perspective(400px) rotateY(0deg); 1731 | transform: perspective(400px) rotateY(0deg); 1732 | opacity: 1; 1733 | } 1734 | } 1735 | 1736 | .flipInY { 1737 | -webkit-backface-visibility: visible !important; 1738 | -ms-backface-visibility: visible !important; 1739 | backface-visibility: visible !important; 1740 | -webkit-animation-name: flipInY; 1741 | animation-name: flipInY; 1742 | } 1743 | 1744 | @-webkit-keyframes flipOutX { 1745 | 0% { 1746 | -webkit-transform: perspective(400px) rotateX(0deg); 1747 | transform: perspective(400px) rotateX(0deg); 1748 | opacity: 1; 1749 | } 1750 | 1751 | 100% { 1752 | -webkit-transform: perspective(400px) rotateX(90deg); 1753 | transform: perspective(400px) rotateX(90deg); 1754 | opacity: 0; 1755 | } 1756 | } 1757 | 1758 | @keyframes flipOutX { 1759 | 0% { 1760 | -webkit-transform: perspective(400px) rotateX(0deg); 1761 | -ms-transform: perspective(400px) rotateX(0deg); 1762 | transform: perspective(400px) rotateX(0deg); 1763 | opacity: 1; 1764 | } 1765 | 1766 | 100% { 1767 | -webkit-transform: perspective(400px) rotateX(90deg); 1768 | -ms-transform: perspective(400px) rotateX(90deg); 1769 | transform: perspective(400px) rotateX(90deg); 1770 | opacity: 0; 1771 | } 1772 | } 1773 | 1774 | .flipOutX { 1775 | -webkit-animation-name: flipOutX; 1776 | animation-name: flipOutX; 1777 | -webkit-backface-visibility: visible !important; 1778 | -ms-backface-visibility: visible !important; 1779 | backface-visibility: visible !important; 1780 | } 1781 | 1782 | @-webkit-keyframes flipOutY { 1783 | 0% { 1784 | -webkit-transform: perspective(400px) rotateY(0deg); 1785 | transform: perspective(400px) rotateY(0deg); 1786 | opacity: 1; 1787 | } 1788 | 1789 | 100% { 1790 | -webkit-transform: perspective(400px) rotateY(90deg); 1791 | transform: perspective(400px) rotateY(90deg); 1792 | opacity: 0; 1793 | } 1794 | } 1795 | 1796 | @keyframes flipOutY { 1797 | 0% { 1798 | -webkit-transform: perspective(400px) rotateY(0deg); 1799 | -ms-transform: perspective(400px) rotateY(0deg); 1800 | transform: perspective(400px) rotateY(0deg); 1801 | opacity: 1; 1802 | } 1803 | 1804 | 100% { 1805 | -webkit-transform: perspective(400px) rotateY(90deg); 1806 | -ms-transform: perspective(400px) rotateY(90deg); 1807 | transform: perspective(400px) rotateY(90deg); 1808 | opacity: 0; 1809 | } 1810 | } 1811 | 1812 | .flipOutY { 1813 | -webkit-backface-visibility: visible !important; 1814 | -ms-backface-visibility: visible !important; 1815 | backface-visibility: visible !important; 1816 | -webkit-animation-name: flipOutY; 1817 | animation-name: flipOutY; 1818 | } 1819 | 1820 | @-webkit-keyframes lightSpeedIn { 1821 | 0% { 1822 | -webkit-transform: translateX(100%) skewX(-30deg); 1823 | transform: translateX(100%) skewX(-30deg); 1824 | opacity: 0; 1825 | } 1826 | 1827 | 60% { 1828 | -webkit-transform: translateX(-20%) skewX(30deg); 1829 | transform: translateX(-20%) skewX(30deg); 1830 | opacity: 1; 1831 | } 1832 | 1833 | 80% { 1834 | -webkit-transform: translateX(0%) skewX(-15deg); 1835 | transform: translateX(0%) skewX(-15deg); 1836 | opacity: 1; 1837 | } 1838 | 1839 | 100% { 1840 | -webkit-transform: translateX(0%) skewX(0deg); 1841 | transform: translateX(0%) skewX(0deg); 1842 | opacity: 1; 1843 | } 1844 | } 1845 | 1846 | @keyframes lightSpeedIn { 1847 | 0% { 1848 | -webkit-transform: translateX(100%) skewX(-30deg); 1849 | -ms-transform: translateX(100%) skewX(-30deg); 1850 | transform: translateX(100%) skewX(-30deg); 1851 | opacity: 0; 1852 | } 1853 | 1854 | 60% { 1855 | -webkit-transform: translateX(-20%) skewX(30deg); 1856 | -ms-transform: translateX(-20%) skewX(30deg); 1857 | transform: translateX(-20%) skewX(30deg); 1858 | opacity: 1; 1859 | } 1860 | 1861 | 80% { 1862 | -webkit-transform: translateX(0%) skewX(-15deg); 1863 | -ms-transform: translateX(0%) skewX(-15deg); 1864 | transform: translateX(0%) skewX(-15deg); 1865 | opacity: 1; 1866 | } 1867 | 1868 | 100% { 1869 | -webkit-transform: translateX(0%) skewX(0deg); 1870 | -ms-transform: translateX(0%) skewX(0deg); 1871 | transform: translateX(0%) skewX(0deg); 1872 | opacity: 1; 1873 | } 1874 | } 1875 | 1876 | .lightSpeedIn { 1877 | -webkit-animation-name: lightSpeedIn; 1878 | animation-name: lightSpeedIn; 1879 | -webkit-animation-timing-function: ease-out; 1880 | animation-timing-function: ease-out; 1881 | } 1882 | 1883 | @-webkit-keyframes lightSpeedOut { 1884 | 0% { 1885 | -webkit-transform: translateX(0%) skewX(0deg); 1886 | transform: translateX(0%) skewX(0deg); 1887 | opacity: 1; 1888 | } 1889 | 1890 | 100% { 1891 | -webkit-transform: translateX(100%) skewX(-30deg); 1892 | transform: translateX(100%) skewX(-30deg); 1893 | opacity: 0; 1894 | } 1895 | } 1896 | 1897 | @keyframes lightSpeedOut { 1898 | 0% { 1899 | -webkit-transform: translateX(0%) skewX(0deg); 1900 | -ms-transform: translateX(0%) skewX(0deg); 1901 | transform: translateX(0%) skewX(0deg); 1902 | opacity: 1; 1903 | } 1904 | 1905 | 100% { 1906 | -webkit-transform: translateX(100%) skewX(-30deg); 1907 | -ms-transform: translateX(100%) skewX(-30deg); 1908 | transform: translateX(100%) skewX(-30deg); 1909 | opacity: 0; 1910 | } 1911 | } 1912 | 1913 | .lightSpeedOut { 1914 | -webkit-animation-name: lightSpeedOut; 1915 | animation-name: lightSpeedOut; 1916 | -webkit-animation-timing-function: ease-in; 1917 | animation-timing-function: ease-in; 1918 | } 1919 | 1920 | @-webkit-keyframes rotateIn { 1921 | 0% { 1922 | -webkit-transform-origin: center center; 1923 | transform-origin: center center; 1924 | -webkit-transform: rotate(-200deg); 1925 | transform: rotate(-200deg); 1926 | opacity: 0; 1927 | } 1928 | 1929 | 100% { 1930 | -webkit-transform-origin: center center; 1931 | transform-origin: center center; 1932 | -webkit-transform: rotate(0); 1933 | transform: rotate(0); 1934 | opacity: 1; 1935 | } 1936 | } 1937 | 1938 | @keyframes rotateIn { 1939 | 0% { 1940 | -webkit-transform-origin: center center; 1941 | -ms-transform-origin: center center; 1942 | transform-origin: center center; 1943 | -webkit-transform: rotate(-200deg); 1944 | -ms-transform: rotate(-200deg); 1945 | transform: rotate(-200deg); 1946 | opacity: 0; 1947 | } 1948 | 1949 | 100% { 1950 | -webkit-transform-origin: center center; 1951 | -ms-transform-origin: center center; 1952 | transform-origin: center center; 1953 | -webkit-transform: rotate(0); 1954 | -ms-transform: rotate(0); 1955 | transform: rotate(0); 1956 | opacity: 1; 1957 | } 1958 | } 1959 | 1960 | .rotateIn { 1961 | -webkit-animation-name: rotateIn; 1962 | animation-name: rotateIn; 1963 | } 1964 | 1965 | @-webkit-keyframes rotateInDownLeft { 1966 | 0% { 1967 | -webkit-transform-origin: left bottom; 1968 | transform-origin: left bottom; 1969 | -webkit-transform: rotate(-90deg); 1970 | transform: rotate(-90deg); 1971 | opacity: 0; 1972 | } 1973 | 1974 | 100% { 1975 | -webkit-transform-origin: left bottom; 1976 | transform-origin: left bottom; 1977 | -webkit-transform: rotate(0); 1978 | transform: rotate(0); 1979 | opacity: 1; 1980 | } 1981 | } 1982 | 1983 | @keyframes rotateInDownLeft { 1984 | 0% { 1985 | -webkit-transform-origin: left bottom; 1986 | -ms-transform-origin: left bottom; 1987 | transform-origin: left bottom; 1988 | -webkit-transform: rotate(-90deg); 1989 | -ms-transform: rotate(-90deg); 1990 | transform: rotate(-90deg); 1991 | opacity: 0; 1992 | } 1993 | 1994 | 100% { 1995 | -webkit-transform-origin: left bottom; 1996 | -ms-transform-origin: left bottom; 1997 | transform-origin: left bottom; 1998 | -webkit-transform: rotate(0); 1999 | -ms-transform: rotate(0); 2000 | transform: rotate(0); 2001 | opacity: 1; 2002 | } 2003 | } 2004 | 2005 | .rotateInDownLeft { 2006 | -webkit-animation-name: rotateInDownLeft; 2007 | animation-name: rotateInDownLeft; 2008 | } 2009 | 2010 | @-webkit-keyframes rotateInDownRight { 2011 | 0% { 2012 | -webkit-transform-origin: right bottom; 2013 | transform-origin: right bottom; 2014 | -webkit-transform: rotate(90deg); 2015 | transform: rotate(90deg); 2016 | opacity: 0; 2017 | } 2018 | 2019 | 100% { 2020 | -webkit-transform-origin: right bottom; 2021 | transform-origin: right bottom; 2022 | -webkit-transform: rotate(0); 2023 | transform: rotate(0); 2024 | opacity: 1; 2025 | } 2026 | } 2027 | 2028 | @keyframes rotateInDownRight { 2029 | 0% { 2030 | -webkit-transform-origin: right bottom; 2031 | -ms-transform-origin: right bottom; 2032 | transform-origin: right bottom; 2033 | -webkit-transform: rotate(90deg); 2034 | -ms-transform: rotate(90deg); 2035 | transform: rotate(90deg); 2036 | opacity: 0; 2037 | } 2038 | 2039 | 100% { 2040 | -webkit-transform-origin: right bottom; 2041 | -ms-transform-origin: right bottom; 2042 | transform-origin: right bottom; 2043 | -webkit-transform: rotate(0); 2044 | -ms-transform: rotate(0); 2045 | transform: rotate(0); 2046 | opacity: 1; 2047 | } 2048 | } 2049 | 2050 | .rotateInDownRight { 2051 | -webkit-animation-name: rotateInDownRight; 2052 | animation-name: rotateInDownRight; 2053 | } 2054 | 2055 | @-webkit-keyframes rotateInUpLeft { 2056 | 0% { 2057 | -webkit-transform-origin: left bottom; 2058 | transform-origin: left bottom; 2059 | -webkit-transform: rotate(90deg); 2060 | transform: rotate(90deg); 2061 | opacity: 0; 2062 | } 2063 | 2064 | 100% { 2065 | -webkit-transform-origin: left bottom; 2066 | transform-origin: left bottom; 2067 | -webkit-transform: rotate(0); 2068 | transform: rotate(0); 2069 | opacity: 1; 2070 | } 2071 | } 2072 | 2073 | @keyframes rotateInUpLeft { 2074 | 0% { 2075 | -webkit-transform-origin: left bottom; 2076 | -ms-transform-origin: left bottom; 2077 | transform-origin: left bottom; 2078 | -webkit-transform: rotate(90deg); 2079 | -ms-transform: rotate(90deg); 2080 | transform: rotate(90deg); 2081 | opacity: 0; 2082 | } 2083 | 2084 | 100% { 2085 | -webkit-transform-origin: left bottom; 2086 | -ms-transform-origin: left bottom; 2087 | transform-origin: left bottom; 2088 | -webkit-transform: rotate(0); 2089 | -ms-transform: rotate(0); 2090 | transform: rotate(0); 2091 | opacity: 1; 2092 | } 2093 | } 2094 | 2095 | .rotateInUpLeft { 2096 | -webkit-animation-name: rotateInUpLeft; 2097 | animation-name: rotateInUpLeft; 2098 | } 2099 | 2100 | @-webkit-keyframes rotateInUpRight { 2101 | 0% { 2102 | -webkit-transform-origin: right bottom; 2103 | transform-origin: right bottom; 2104 | -webkit-transform: rotate(-90deg); 2105 | transform: rotate(-90deg); 2106 | opacity: 0; 2107 | } 2108 | 2109 | 100% { 2110 | -webkit-transform-origin: right bottom; 2111 | transform-origin: right bottom; 2112 | -webkit-transform: rotate(0); 2113 | transform: rotate(0); 2114 | opacity: 1; 2115 | } 2116 | } 2117 | 2118 | @keyframes rotateInUpRight { 2119 | 0% { 2120 | -webkit-transform-origin: right bottom; 2121 | -ms-transform-origin: right bottom; 2122 | transform-origin: right bottom; 2123 | -webkit-transform: rotate(-90deg); 2124 | -ms-transform: rotate(-90deg); 2125 | transform: rotate(-90deg); 2126 | opacity: 0; 2127 | } 2128 | 2129 | 100% { 2130 | -webkit-transform-origin: right bottom; 2131 | -ms-transform-origin: right bottom; 2132 | transform-origin: right bottom; 2133 | -webkit-transform: rotate(0); 2134 | -ms-transform: rotate(0); 2135 | transform: rotate(0); 2136 | opacity: 1; 2137 | } 2138 | } 2139 | 2140 | .rotateInUpRight { 2141 | -webkit-animation-name: rotateInUpRight; 2142 | animation-name: rotateInUpRight; 2143 | } 2144 | 2145 | @-webkit-keyframes rotateOut { 2146 | 0% { 2147 | -webkit-transform-origin: center center; 2148 | transform-origin: center center; 2149 | -webkit-transform: rotate(0); 2150 | transform: rotate(0); 2151 | opacity: 1; 2152 | } 2153 | 2154 | 100% { 2155 | -webkit-transform-origin: center center; 2156 | transform-origin: center center; 2157 | -webkit-transform: rotate(200deg); 2158 | transform: rotate(200deg); 2159 | opacity: 0; 2160 | } 2161 | } 2162 | 2163 | @keyframes rotateOut { 2164 | 0% { 2165 | -webkit-transform-origin: center center; 2166 | -ms-transform-origin: center center; 2167 | transform-origin: center center; 2168 | -webkit-transform: rotate(0); 2169 | -ms-transform: rotate(0); 2170 | transform: rotate(0); 2171 | opacity: 1; 2172 | } 2173 | 2174 | 100% { 2175 | -webkit-transform-origin: center center; 2176 | -ms-transform-origin: center center; 2177 | transform-origin: center center; 2178 | -webkit-transform: rotate(200deg); 2179 | -ms-transform: rotate(200deg); 2180 | transform: rotate(200deg); 2181 | opacity: 0; 2182 | } 2183 | } 2184 | 2185 | .rotateOut { 2186 | -webkit-animation-name: rotateOut; 2187 | animation-name: rotateOut; 2188 | } 2189 | 2190 | @-webkit-keyframes rotateOutDownLeft { 2191 | 0% { 2192 | -webkit-transform-origin: left bottom; 2193 | transform-origin: left bottom; 2194 | -webkit-transform: rotate(0); 2195 | transform: rotate(0); 2196 | opacity: 1; 2197 | } 2198 | 2199 | 100% { 2200 | -webkit-transform-origin: left bottom; 2201 | transform-origin: left bottom; 2202 | -webkit-transform: rotate(90deg); 2203 | transform: rotate(90deg); 2204 | opacity: 0; 2205 | } 2206 | } 2207 | 2208 | @keyframes rotateOutDownLeft { 2209 | 0% { 2210 | -webkit-transform-origin: left bottom; 2211 | -ms-transform-origin: left bottom; 2212 | transform-origin: left bottom; 2213 | -webkit-transform: rotate(0); 2214 | -ms-transform: rotate(0); 2215 | transform: rotate(0); 2216 | opacity: 1; 2217 | } 2218 | 2219 | 100% { 2220 | -webkit-transform-origin: left bottom; 2221 | -ms-transform-origin: left bottom; 2222 | transform-origin: left bottom; 2223 | -webkit-transform: rotate(90deg); 2224 | -ms-transform: rotate(90deg); 2225 | transform: rotate(90deg); 2226 | opacity: 0; 2227 | } 2228 | } 2229 | 2230 | .rotateOutDownLeft { 2231 | -webkit-animation-name: rotateOutDownLeft; 2232 | animation-name: rotateOutDownLeft; 2233 | } 2234 | 2235 | @-webkit-keyframes rotateOutDownRight { 2236 | 0% { 2237 | -webkit-transform-origin: right bottom; 2238 | transform-origin: right bottom; 2239 | -webkit-transform: rotate(0); 2240 | transform: rotate(0); 2241 | opacity: 1; 2242 | } 2243 | 2244 | 100% { 2245 | -webkit-transform-origin: right bottom; 2246 | transform-origin: right bottom; 2247 | -webkit-transform: rotate(-90deg); 2248 | transform: rotate(-90deg); 2249 | opacity: 0; 2250 | } 2251 | } 2252 | 2253 | @keyframes rotateOutDownRight { 2254 | 0% { 2255 | -webkit-transform-origin: right bottom; 2256 | -ms-transform-origin: right bottom; 2257 | transform-origin: right bottom; 2258 | -webkit-transform: rotate(0); 2259 | -ms-transform: rotate(0); 2260 | transform: rotate(0); 2261 | opacity: 1; 2262 | } 2263 | 2264 | 100% { 2265 | -webkit-transform-origin: right bottom; 2266 | -ms-transform-origin: right bottom; 2267 | transform-origin: right bottom; 2268 | -webkit-transform: rotate(-90deg); 2269 | -ms-transform: rotate(-90deg); 2270 | transform: rotate(-90deg); 2271 | opacity: 0; 2272 | } 2273 | } 2274 | 2275 | .rotateOutDownRight { 2276 | -webkit-animation-name: rotateOutDownRight; 2277 | animation-name: rotateOutDownRight; 2278 | } 2279 | 2280 | @-webkit-keyframes rotateOutUpLeft { 2281 | 0% { 2282 | -webkit-transform-origin: left bottom; 2283 | transform-origin: left bottom; 2284 | -webkit-transform: rotate(0); 2285 | transform: rotate(0); 2286 | opacity: 1; 2287 | } 2288 | 2289 | 100% { 2290 | -webkit-transform-origin: left bottom; 2291 | transform-origin: left bottom; 2292 | -webkit-transform: rotate(-90deg); 2293 | transform: rotate(-90deg); 2294 | opacity: 0; 2295 | } 2296 | } 2297 | 2298 | @keyframes rotateOutUpLeft { 2299 | 0% { 2300 | -webkit-transform-origin: left bottom; 2301 | -ms-transform-origin: left bottom; 2302 | transform-origin: left bottom; 2303 | -webkit-transform: rotate(0); 2304 | -ms-transform: rotate(0); 2305 | transform: rotate(0); 2306 | opacity: 1; 2307 | } 2308 | 2309 | 100% { 2310 | -webkit-transform-origin: left bottom; 2311 | -ms-transform-origin: left bottom; 2312 | transform-origin: left bottom; 2313 | -webkit-transform: rotate(-90deg); 2314 | -ms-transform: rotate(-90deg); 2315 | transform: rotate(-90deg); 2316 | opacity: 0; 2317 | } 2318 | } 2319 | 2320 | .rotateOutUpLeft { 2321 | -webkit-animation-name: rotateOutUpLeft; 2322 | animation-name: rotateOutUpLeft; 2323 | } 2324 | 2325 | @-webkit-keyframes rotateOutUpRight { 2326 | 0% { 2327 | -webkit-transform-origin: right bottom; 2328 | transform-origin: right bottom; 2329 | -webkit-transform: rotate(0); 2330 | transform: rotate(0); 2331 | opacity: 1; 2332 | } 2333 | 2334 | 100% { 2335 | -webkit-transform-origin: right bottom; 2336 | transform-origin: right bottom; 2337 | -webkit-transform: rotate(90deg); 2338 | transform: rotate(90deg); 2339 | opacity: 0; 2340 | } 2341 | } 2342 | 2343 | @keyframes rotateOutUpRight { 2344 | 0% { 2345 | -webkit-transform-origin: right bottom; 2346 | -ms-transform-origin: right bottom; 2347 | transform-origin: right bottom; 2348 | -webkit-transform: rotate(0); 2349 | -ms-transform: rotate(0); 2350 | transform: rotate(0); 2351 | opacity: 1; 2352 | } 2353 | 2354 | 100% { 2355 | -webkit-transform-origin: right bottom; 2356 | -ms-transform-origin: right bottom; 2357 | transform-origin: right bottom; 2358 | -webkit-transform: rotate(90deg); 2359 | -ms-transform: rotate(90deg); 2360 | transform: rotate(90deg); 2361 | opacity: 0; 2362 | } 2363 | } 2364 | 2365 | .rotateOutUpRight { 2366 | -webkit-animation-name: rotateOutUpRight; 2367 | animation-name: rotateOutUpRight; 2368 | } 2369 | 2370 | @-webkit-keyframes slideInDown { 2371 | 0% { 2372 | opacity: 0; 2373 | -webkit-transform: translateY(-2000px); 2374 | transform: translateY(-2000px); 2375 | } 2376 | 2377 | 100% { 2378 | -webkit-transform: translateY(0); 2379 | transform: translateY(0); 2380 | } 2381 | } 2382 | 2383 | @keyframes slideInDown { 2384 | 0% { 2385 | opacity: 0; 2386 | -webkit-transform: translateY(-2000px); 2387 | -ms-transform: translateY(-2000px); 2388 | transform: translateY(-2000px); 2389 | } 2390 | 2391 | 100% { 2392 | -webkit-transform: translateY(0); 2393 | -ms-transform: translateY(0); 2394 | transform: translateY(0); 2395 | } 2396 | } 2397 | 2398 | .slideInDown { 2399 | -webkit-animation-name: slideInDown; 2400 | animation-name: slideInDown; 2401 | } 2402 | 2403 | @-webkit-keyframes slideInLeft { 2404 | 0% { 2405 | opacity: 0; 2406 | -webkit-transform: translateX(-2000px); 2407 | transform: translateX(-2000px); 2408 | } 2409 | 2410 | 100% { 2411 | -webkit-transform: translateX(0); 2412 | transform: translateX(0); 2413 | } 2414 | } 2415 | 2416 | @keyframes slideInLeft { 2417 | 0% { 2418 | opacity: 0; 2419 | -webkit-transform: translateX(-2000px); 2420 | -ms-transform: translateX(-2000px); 2421 | transform: translateX(-2000px); 2422 | } 2423 | 2424 | 100% { 2425 | -webkit-transform: translateX(0); 2426 | -ms-transform: translateX(0); 2427 | transform: translateX(0); 2428 | } 2429 | } 2430 | 2431 | .slideInLeft { 2432 | -webkit-animation-name: slideInLeft; 2433 | animation-name: slideInLeft; 2434 | } 2435 | 2436 | @-webkit-keyframes slideInRight { 2437 | 0% { 2438 | opacity: 0; 2439 | -webkit-transform: translateX(2000px); 2440 | transform: translateX(2000px); 2441 | } 2442 | 2443 | 100% { 2444 | -webkit-transform: translateX(0); 2445 | transform: translateX(0); 2446 | } 2447 | } 2448 | 2449 | @keyframes slideInRight { 2450 | 0% { 2451 | opacity: 0; 2452 | -webkit-transform: translateX(2000px); 2453 | -ms-transform: translateX(2000px); 2454 | transform: translateX(2000px); 2455 | } 2456 | 2457 | 100% { 2458 | -webkit-transform: translateX(0); 2459 | -ms-transform: translateX(0); 2460 | transform: translateX(0); 2461 | } 2462 | } 2463 | 2464 | .slideInRight { 2465 | -webkit-animation-name: slideInRight; 2466 | animation-name: slideInRight; 2467 | } 2468 | 2469 | @-webkit-keyframes slideOutLeft { 2470 | 0% { 2471 | -webkit-transform: translateX(0); 2472 | transform: translateX(0); 2473 | } 2474 | 2475 | 100% { 2476 | opacity: 0; 2477 | -webkit-transform: translateX(-2000px); 2478 | transform: translateX(-2000px); 2479 | } 2480 | } 2481 | 2482 | @keyframes slideOutLeft { 2483 | 0% { 2484 | -webkit-transform: translateX(0); 2485 | -ms-transform: translateX(0); 2486 | transform: translateX(0); 2487 | } 2488 | 2489 | 100% { 2490 | opacity: 0; 2491 | -webkit-transform: translateX(-2000px); 2492 | -ms-transform: translateX(-2000px); 2493 | transform: translateX(-2000px); 2494 | } 2495 | } 2496 | 2497 | .slideOutLeft { 2498 | -webkit-animation-name: slideOutLeft; 2499 | animation-name: slideOutLeft; 2500 | } 2501 | 2502 | @-webkit-keyframes slideOutRight { 2503 | 0% { 2504 | -webkit-transform: translateX(0); 2505 | transform: translateX(0); 2506 | } 2507 | 2508 | 100% { 2509 | opacity: 0; 2510 | -webkit-transform: translateX(2000px); 2511 | transform: translateX(2000px); 2512 | } 2513 | } 2514 | 2515 | @keyframes slideOutRight { 2516 | 0% { 2517 | -webkit-transform: translateX(0); 2518 | -ms-transform: translateX(0); 2519 | transform: translateX(0); 2520 | } 2521 | 2522 | 100% { 2523 | opacity: 0; 2524 | -webkit-transform: translateX(2000px); 2525 | -ms-transform: translateX(2000px); 2526 | transform: translateX(2000px); 2527 | } 2528 | } 2529 | 2530 | .slideOutRight { 2531 | -webkit-animation-name: slideOutRight; 2532 | animation-name: slideOutRight; 2533 | } 2534 | 2535 | @-webkit-keyframes slideOutUp { 2536 | 0% { 2537 | -webkit-transform: translateY(0); 2538 | transform: translateY(0); 2539 | } 2540 | 2541 | 100% { 2542 | opacity: 0; 2543 | -webkit-transform: translateY(-2000px); 2544 | transform: translateY(-2000px); 2545 | } 2546 | } 2547 | 2548 | @keyframes slideOutUp { 2549 | 0% { 2550 | -webkit-transform: translateY(0); 2551 | -ms-transform: translateY(0); 2552 | transform: translateY(0); 2553 | } 2554 | 2555 | 100% { 2556 | opacity: 0; 2557 | -webkit-transform: translateY(-2000px); 2558 | -ms-transform: translateY(-2000px); 2559 | transform: translateY(-2000px); 2560 | } 2561 | } 2562 | 2563 | .slideOutUp { 2564 | -webkit-animation-name: slideOutUp; 2565 | animation-name: slideOutUp; 2566 | } 2567 | 2568 | @-webkit-keyframes hinge { 2569 | 0% { 2570 | -webkit-transform: rotate(0); 2571 | transform: rotate(0); 2572 | -webkit-transform-origin: top left; 2573 | transform-origin: top left; 2574 | -webkit-animation-timing-function: ease-in-out; 2575 | animation-timing-function: ease-in-out; 2576 | } 2577 | 2578 | 20%, 60% { 2579 | -webkit-transform: rotate(80deg); 2580 | transform: rotate(80deg); 2581 | -webkit-transform-origin: top left; 2582 | transform-origin: top left; 2583 | -webkit-animation-timing-function: ease-in-out; 2584 | animation-timing-function: ease-in-out; 2585 | } 2586 | 2587 | 40% { 2588 | -webkit-transform: rotate(60deg); 2589 | transform: rotate(60deg); 2590 | -webkit-transform-origin: top left; 2591 | transform-origin: top left; 2592 | -webkit-animation-timing-function: ease-in-out; 2593 | animation-timing-function: ease-in-out; 2594 | } 2595 | 2596 | 80% { 2597 | -webkit-transform: rotate(60deg) translateY(0); 2598 | transform: rotate(60deg) translateY(0); 2599 | opacity: 1; 2600 | -webkit-transform-origin: top left; 2601 | transform-origin: top left; 2602 | -webkit-animation-timing-function: ease-in-out; 2603 | animation-timing-function: ease-in-out; 2604 | } 2605 | 2606 | 100% { 2607 | -webkit-transform: translateY(700px); 2608 | transform: translateY(700px); 2609 | opacity: 0; 2610 | } 2611 | } 2612 | 2613 | @keyframes hinge { 2614 | 0% { 2615 | -webkit-transform: rotate(0); 2616 | -ms-transform: rotate(0); 2617 | transform: rotate(0); 2618 | -webkit-transform-origin: top left; 2619 | -ms-transform-origin: top left; 2620 | transform-origin: top left; 2621 | -webkit-animation-timing-function: ease-in-out; 2622 | animation-timing-function: ease-in-out; 2623 | } 2624 | 2625 | 20%, 60% { 2626 | -webkit-transform: rotate(80deg); 2627 | -ms-transform: rotate(80deg); 2628 | transform: rotate(80deg); 2629 | -webkit-transform-origin: top left; 2630 | -ms-transform-origin: top left; 2631 | transform-origin: top left; 2632 | -webkit-animation-timing-function: ease-in-out; 2633 | animation-timing-function: ease-in-out; 2634 | } 2635 | 2636 | 40% { 2637 | -webkit-transform: rotate(60deg); 2638 | -ms-transform: rotate(60deg); 2639 | transform: rotate(60deg); 2640 | -webkit-transform-origin: top left; 2641 | -ms-transform-origin: top left; 2642 | transform-origin: top left; 2643 | -webkit-animation-timing-function: ease-in-out; 2644 | animation-timing-function: ease-in-out; 2645 | } 2646 | 2647 | 80% { 2648 | -webkit-transform: rotate(60deg) translateY(0); 2649 | -ms-transform: rotate(60deg) translateY(0); 2650 | transform: rotate(60deg) translateY(0); 2651 | opacity: 1; 2652 | -webkit-transform-origin: top left; 2653 | -ms-transform-origin: top left; 2654 | transform-origin: top left; 2655 | -webkit-animation-timing-function: ease-in-out; 2656 | animation-timing-function: ease-in-out; 2657 | } 2658 | 2659 | 100% { 2660 | -webkit-transform: translateY(700px); 2661 | -ms-transform: translateY(700px); 2662 | transform: translateY(700px); 2663 | opacity: 0; 2664 | } 2665 | } 2666 | 2667 | .hinge { 2668 | -webkit-animation-name: hinge; 2669 | animation-name: hinge; 2670 | } 2671 | 2672 | /* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ 2673 | 2674 | @-webkit-keyframes rollIn { 2675 | 0% { 2676 | opacity: 0; 2677 | -webkit-transform: translateX(-100%) rotate(-120deg); 2678 | transform: translateX(-100%) rotate(-120deg); 2679 | } 2680 | 2681 | 100% { 2682 | opacity: 1; 2683 | -webkit-transform: translateX(0px) rotate(0deg); 2684 | transform: translateX(0px) rotate(0deg); 2685 | } 2686 | } 2687 | 2688 | @keyframes rollIn { 2689 | 0% { 2690 | opacity: 0; 2691 | -webkit-transform: translateX(-100%) rotate(-120deg); 2692 | -ms-transform: translateX(-100%) rotate(-120deg); 2693 | transform: translateX(-100%) rotate(-120deg); 2694 | } 2695 | 2696 | 100% { 2697 | opacity: 1; 2698 | -webkit-transform: translateX(0px) rotate(0deg); 2699 | -ms-transform: translateX(0px) rotate(0deg); 2700 | transform: translateX(0px) rotate(0deg); 2701 | } 2702 | } 2703 | 2704 | .rollIn { 2705 | -webkit-animation-name: rollIn; 2706 | animation-name: rollIn; 2707 | } 2708 | 2709 | /* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ 2710 | 2711 | @-webkit-keyframes rollOut { 2712 | 0% { 2713 | opacity: 1; 2714 | -webkit-transform: translateX(0px) rotate(0deg); 2715 | transform: translateX(0px) rotate(0deg); 2716 | } 2717 | 2718 | 100% { 2719 | opacity: 0; 2720 | -webkit-transform: translateX(100%) rotate(120deg); 2721 | transform: translateX(100%) rotate(120deg); 2722 | } 2723 | } 2724 | 2725 | @keyframes rollOut { 2726 | 0% { 2727 | opacity: 1; 2728 | -webkit-transform: translateX(0px) rotate(0deg); 2729 | -ms-transform: translateX(0px) rotate(0deg); 2730 | transform: translateX(0px) rotate(0deg); 2731 | } 2732 | 2733 | 100% { 2734 | opacity: 0; 2735 | -webkit-transform: translateX(100%) rotate(120deg); 2736 | -ms-transform: translateX(100%) rotate(120deg); 2737 | transform: translateX(100%) rotate(120deg); 2738 | } 2739 | } 2740 | 2741 | .rollOut { 2742 | -webkit-animation-name: rollOut; 2743 | animation-name: rollOut; 2744 | } 2745 | -------------------------------------------------------------------------------- /css/site.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | font-size: 72px; 3 | line-height: 1.5; 4 | color: #2c3e50; 5 | font-weight: 100; 6 | } 7 | 8 | #container { 9 | width: 980px; 10 | margin: 0 auto; 11 | } 12 | 13 | section { 14 | height: 300px; 15 | margin: 60px 0; 16 | } 17 | 18 | .section--purple { 19 | background-color: #9b59b6; 20 | } 21 | 22 | .section--blue { 23 | background-color: #3498db; 24 | } 25 | 26 | .section--green { 27 | background-color: #2ecc71; 28 | } 29 | 30 | #main { 31 | text-align: center; 32 | } 33 | 34 | #more { 35 | margin: 20px auto 48px; 36 | } 37 | -------------------------------------------------------------------------------- /demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WOW 7 | 8 | 9 | 14 | 17 | 18 | 19 | 20 |
21 |
22 |

WOW.js

23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | 31 |
32 |
33 | 34 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /dist/wow.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var MutationObserver, Util, WeakMap, getComputedStyle, getComputedStyleRX, 3 | bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, 4 | indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; 5 | 6 | Util = (function() { 7 | function Util() {} 8 | 9 | Util.prototype.extend = function(custom, defaults) { 10 | var key, value; 11 | for (key in defaults) { 12 | value = defaults[key]; 13 | if (custom[key] == null) { 14 | custom[key] = value; 15 | } 16 | } 17 | return custom; 18 | }; 19 | 20 | Util.prototype.isMobile = function(agent) { 21 | return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(agent); 22 | }; 23 | 24 | Util.prototype.createEvent = function(event, bubble, cancel, detail) { 25 | var customEvent; 26 | if (bubble == null) { 27 | bubble = false; 28 | } 29 | if (cancel == null) { 30 | cancel = false; 31 | } 32 | if (detail == null) { 33 | detail = null; 34 | } 35 | if (document.createEvent != null) { 36 | customEvent = document.createEvent('CustomEvent'); 37 | customEvent.initCustomEvent(event, bubble, cancel, detail); 38 | } else if (document.createEventObject != null) { 39 | customEvent = document.createEventObject(); 40 | customEvent.eventType = event; 41 | } else { 42 | customEvent.eventName = event; 43 | } 44 | return customEvent; 45 | }; 46 | 47 | Util.prototype.emitEvent = function(elem, event) { 48 | if (elem.dispatchEvent != null) { 49 | return elem.dispatchEvent(event); 50 | } else if (event in (elem != null)) { 51 | return elem[event](); 52 | } else if (("on" + event) in (elem != null)) { 53 | return elem["on" + event](); 54 | } 55 | }; 56 | 57 | Util.prototype.addEvent = function(elem, event, fn) { 58 | if (elem.addEventListener != null) { 59 | return elem.addEventListener(event, fn, false); 60 | } else if (elem.attachEvent != null) { 61 | return elem.attachEvent("on" + event, fn); 62 | } else { 63 | return elem[event] = fn; 64 | } 65 | }; 66 | 67 | Util.prototype.removeEvent = function(elem, event, fn) { 68 | if (elem.removeEventListener != null) { 69 | return elem.removeEventListener(event, fn, false); 70 | } else if (elem.detachEvent != null) { 71 | return elem.detachEvent("on" + event, fn); 72 | } else { 73 | return delete elem[event]; 74 | } 75 | }; 76 | 77 | Util.prototype.innerHeight = function() { 78 | if ('innerHeight' in window) { 79 | return window.innerHeight; 80 | } else { 81 | return document.documentElement.clientHeight; 82 | } 83 | }; 84 | 85 | return Util; 86 | 87 | })(); 88 | 89 | WeakMap = this.WeakMap || this.MozWeakMap || (WeakMap = (function() { 90 | function WeakMap() { 91 | this.keys = []; 92 | this.values = []; 93 | } 94 | 95 | WeakMap.prototype.get = function(key) { 96 | var i, item, j, len, ref; 97 | ref = this.keys; 98 | for (i = j = 0, len = ref.length; j < len; i = ++j) { 99 | item = ref[i]; 100 | if (item === key) { 101 | return this.values[i]; 102 | } 103 | } 104 | }; 105 | 106 | WeakMap.prototype.set = function(key, value) { 107 | var i, item, j, len, ref; 108 | ref = this.keys; 109 | for (i = j = 0, len = ref.length; j < len; i = ++j) { 110 | item = ref[i]; 111 | if (item === key) { 112 | this.values[i] = value; 113 | return; 114 | } 115 | } 116 | this.keys.push(key); 117 | return this.values.push(value); 118 | }; 119 | 120 | return WeakMap; 121 | 122 | })()); 123 | 124 | MutationObserver = this.MutationObserver || this.WebkitMutationObserver || this.MozMutationObserver || (MutationObserver = (function() { 125 | function MutationObserver() { 126 | if (typeof console !== "undefined" && console !== null) { 127 | console.warn('MutationObserver is not supported by your browser.'); 128 | } 129 | if (typeof console !== "undefined" && console !== null) { 130 | console.warn('WOW.js cannot detect dom mutations, please call .sync() after loading new content.'); 131 | } 132 | } 133 | 134 | MutationObserver.notSupported = true; 135 | 136 | MutationObserver.prototype.observe = function() {}; 137 | 138 | return MutationObserver; 139 | 140 | })()); 141 | 142 | getComputedStyle = this.getComputedStyle || function(el, pseudo) { 143 | this.getPropertyValue = function(prop) { 144 | var ref; 145 | if (prop === 'float') { 146 | prop = 'styleFloat'; 147 | } 148 | if (getComputedStyleRX.test(prop)) { 149 | prop.replace(getComputedStyleRX, function(_, _char) { 150 | return _char.toUpperCase(); 151 | }); 152 | } 153 | return ((ref = el.currentStyle) != null ? ref[prop] : void 0) || null; 154 | }; 155 | return this; 156 | }; 157 | 158 | getComputedStyleRX = /(\-([a-z]){1})/g; 159 | 160 | this.WOW = (function() { 161 | WOW.prototype.defaults = { 162 | boxClass: 'wow', 163 | animateClass: 'animated', 164 | offset: 0, 165 | mobile: true, 166 | live: true, 167 | callback: null, 168 | scrollContainer: null 169 | }; 170 | 171 | function WOW(options) { 172 | if (options == null) { 173 | options = {}; 174 | } 175 | this.scrollCallback = bind(this.scrollCallback, this); 176 | this.scrollHandler = bind(this.scrollHandler, this); 177 | this.resetAnimation = bind(this.resetAnimation, this); 178 | this.start = bind(this.start, this); 179 | this.scrolled = true; 180 | this.config = this.util().extend(options, this.defaults); 181 | if (options.scrollContainer != null) { 182 | this.config.scrollContainer = document.querySelector(options.scrollContainer); 183 | } 184 | this.animationNameCache = new WeakMap(); 185 | this.wowEvent = this.util().createEvent(this.config.boxClass); 186 | } 187 | 188 | WOW.prototype.init = function() { 189 | var ref; 190 | this.element = window.document.documentElement; 191 | if ((ref = document.readyState) === "interactive" || ref === "complete") { 192 | this.start(); 193 | } else { 194 | this.util().addEvent(document, 'DOMContentLoaded', this.start); 195 | } 196 | return this.finished = []; 197 | }; 198 | 199 | WOW.prototype.start = function() { 200 | var box, j, len, ref; 201 | this.stopped = false; 202 | this.boxes = (function() { 203 | var j, len, ref, results; 204 | ref = this.element.querySelectorAll("." + this.config.boxClass); 205 | results = []; 206 | for (j = 0, len = ref.length; j < len; j++) { 207 | box = ref[j]; 208 | results.push(box); 209 | } 210 | return results; 211 | }).call(this); 212 | this.all = (function() { 213 | var j, len, ref, results; 214 | ref = this.boxes; 215 | results = []; 216 | for (j = 0, len = ref.length; j < len; j++) { 217 | box = ref[j]; 218 | results.push(box); 219 | } 220 | return results; 221 | }).call(this); 222 | if (this.boxes.length) { 223 | if (this.disabled()) { 224 | this.resetStyle(); 225 | } else { 226 | ref = this.boxes; 227 | for (j = 0, len = ref.length; j < len; j++) { 228 | box = ref[j]; 229 | this.applyStyle(box, true); 230 | } 231 | } 232 | } 233 | if (!this.disabled()) { 234 | this.util().addEvent(this.config.scrollContainer || window, 'scroll', this.scrollHandler); 235 | this.util().addEvent(window, 'resize', this.scrollHandler); 236 | this.interval = setInterval(this.scrollCallback, 50); 237 | } 238 | if (this.config.live) { 239 | return new MutationObserver((function(_this) { 240 | return function(records) { 241 | var k, len1, node, record, results; 242 | results = []; 243 | for (k = 0, len1 = records.length; k < len1; k++) { 244 | record = records[k]; 245 | results.push((function() { 246 | var l, len2, ref1, results1; 247 | ref1 = record.addedNodes || []; 248 | results1 = []; 249 | for (l = 0, len2 = ref1.length; l < len2; l++) { 250 | node = ref1[l]; 251 | results1.push(this.doSync(node)); 252 | } 253 | return results1; 254 | }).call(_this)); 255 | } 256 | return results; 257 | }; 258 | })(this)).observe(document.body, { 259 | childList: true, 260 | subtree: true 261 | }); 262 | } 263 | }; 264 | 265 | WOW.prototype.stop = function() { 266 | this.stopped = true; 267 | this.util().removeEvent(this.config.scrollContainer || window, 'scroll', this.scrollHandler); 268 | this.util().removeEvent(window, 'resize', this.scrollHandler); 269 | if (this.interval != null) { 270 | return clearInterval(this.interval); 271 | } 272 | }; 273 | 274 | WOW.prototype.sync = function(element) { 275 | if (MutationObserver.notSupported) { 276 | return this.doSync(this.element); 277 | } 278 | }; 279 | 280 | WOW.prototype.doSync = function(element) { 281 | var box, j, len, ref, results; 282 | if (element == null) { 283 | element = this.element; 284 | } 285 | if (element.nodeType !== 1) { 286 | return; 287 | } 288 | element = element.parentNode || element; 289 | ref = element.querySelectorAll("." + this.config.boxClass); 290 | results = []; 291 | for (j = 0, len = ref.length; j < len; j++) { 292 | box = ref[j]; 293 | if (indexOf.call(this.all, box) < 0) { 294 | this.boxes.push(box); 295 | this.all.push(box); 296 | if (this.stopped || this.disabled()) { 297 | this.resetStyle(); 298 | } else { 299 | this.applyStyle(box, true); 300 | } 301 | results.push(this.scrolled = true); 302 | } else { 303 | results.push(void 0); 304 | } 305 | } 306 | return results; 307 | }; 308 | 309 | WOW.prototype.show = function(box) { 310 | this.applyStyle(box); 311 | box.className = box.className + " " + this.config.animateClass; 312 | if (this.config.callback != null) { 313 | this.config.callback(box); 314 | } 315 | this.util().emitEvent(box, this.wowEvent); 316 | this.util().addEvent(box, 'animationend', this.resetAnimation); 317 | this.util().addEvent(box, 'oanimationend', this.resetAnimation); 318 | this.util().addEvent(box, 'webkitAnimationEnd', this.resetAnimation); 319 | this.util().addEvent(box, 'MSAnimationEnd', this.resetAnimation); 320 | return box; 321 | }; 322 | 323 | WOW.prototype.applyStyle = function(box, hidden) { 324 | var delay, duration, iteration; 325 | duration = box.getAttribute('data-wow-duration'); 326 | delay = box.getAttribute('data-wow-delay'); 327 | iteration = box.getAttribute('data-wow-iteration'); 328 | return this.animate((function(_this) { 329 | return function() { 330 | return _this.customStyle(box, hidden, duration, delay, iteration); 331 | }; 332 | })(this)); 333 | }; 334 | 335 | WOW.prototype.animate = (function() { 336 | if ('requestAnimationFrame' in window) { 337 | return function(callback) { 338 | return window.requestAnimationFrame(callback); 339 | }; 340 | } else { 341 | return function(callback) { 342 | return callback(); 343 | }; 344 | } 345 | })(); 346 | 347 | WOW.prototype.resetStyle = function() { 348 | var box, j, len, ref, results; 349 | ref = this.boxes; 350 | results = []; 351 | for (j = 0, len = ref.length; j < len; j++) { 352 | box = ref[j]; 353 | results.push(box.style.visibility = 'visible'); 354 | } 355 | return results; 356 | }; 357 | 358 | WOW.prototype.resetAnimation = function(event) { 359 | var target; 360 | if (event.type.toLowerCase().indexOf('animationend') >= 0) { 361 | target = event.target || event.srcElement; 362 | return target.className = target.className.replace(this.config.animateClass, '').trim(); 363 | } 364 | }; 365 | 366 | WOW.prototype.customStyle = function(box, hidden, duration, delay, iteration) { 367 | if (hidden) { 368 | this.cacheAnimationName(box); 369 | } 370 | box.style.visibility = hidden ? 'hidden' : 'visible'; 371 | if (duration) { 372 | this.vendorSet(box.style, { 373 | animationDuration: duration 374 | }); 375 | } 376 | if (delay) { 377 | this.vendorSet(box.style, { 378 | animationDelay: delay 379 | }); 380 | } 381 | if (iteration) { 382 | this.vendorSet(box.style, { 383 | animationIterationCount: iteration 384 | }); 385 | } 386 | this.vendorSet(box.style, { 387 | animationName: hidden ? 'none' : this.cachedAnimationName(box) 388 | }); 389 | return box; 390 | }; 391 | 392 | WOW.prototype.vendors = ["moz", "webkit"]; 393 | 394 | WOW.prototype.vendorSet = function(elem, properties) { 395 | var name, results, value, vendor; 396 | results = []; 397 | for (name in properties) { 398 | value = properties[name]; 399 | elem["" + name] = value; 400 | results.push((function() { 401 | var j, len, ref, results1; 402 | ref = this.vendors; 403 | results1 = []; 404 | for (j = 0, len = ref.length; j < len; j++) { 405 | vendor = ref[j]; 406 | results1.push(elem["" + vendor + (name.charAt(0).toUpperCase()) + (name.substr(1))] = value); 407 | } 408 | return results1; 409 | }).call(this)); 410 | } 411 | return results; 412 | }; 413 | 414 | WOW.prototype.vendorCSS = function(elem, property) { 415 | var j, len, ref, result, style, vendor; 416 | style = getComputedStyle(elem); 417 | result = style.getPropertyCSSValue(property); 418 | ref = this.vendors; 419 | for (j = 0, len = ref.length; j < len; j++) { 420 | vendor = ref[j]; 421 | result = result || style.getPropertyCSSValue("-" + vendor + "-" + property); 422 | } 423 | return result; 424 | }; 425 | 426 | WOW.prototype.animationName = function(box) { 427 | var animationName, error; 428 | try { 429 | animationName = this.vendorCSS(box, 'animation-name').cssText; 430 | } catch (error) { 431 | animationName = getComputedStyle(box).getPropertyValue('animation-name'); 432 | } 433 | if (animationName === 'none') { 434 | return ''; 435 | } else { 436 | return animationName; 437 | } 438 | }; 439 | 440 | WOW.prototype.cacheAnimationName = function(box) { 441 | return this.animationNameCache.set(box, this.animationName(box)); 442 | }; 443 | 444 | WOW.prototype.cachedAnimationName = function(box) { 445 | return this.animationNameCache.get(box); 446 | }; 447 | 448 | WOW.prototype.scrollHandler = function() { 449 | return this.scrolled = true; 450 | }; 451 | 452 | WOW.prototype.scrollCallback = function() { 453 | var box; 454 | if (this.scrolled) { 455 | this.scrolled = false; 456 | this.boxes = (function() { 457 | var j, len, ref, results; 458 | ref = this.boxes; 459 | results = []; 460 | for (j = 0, len = ref.length; j < len; j++) { 461 | box = ref[j]; 462 | if (!(box)) { 463 | continue; 464 | } 465 | if (this.isVisible(box)) { 466 | this.show(box); 467 | continue; 468 | } 469 | results.push(box); 470 | } 471 | return results; 472 | }).call(this); 473 | if (!(this.boxes.length || this.config.live)) { 474 | return this.stop(); 475 | } 476 | } 477 | }; 478 | 479 | WOW.prototype.offsetTop = function(element) { 480 | var top; 481 | while (element.offsetTop === void 0) { 482 | element = element.parentNode; 483 | } 484 | top = element.offsetTop; 485 | while (element = element.offsetParent) { 486 | top += element.offsetTop; 487 | } 488 | return top; 489 | }; 490 | 491 | WOW.prototype.isVisible = function(box) { 492 | var bottom, offset, top, viewBottom, viewTop; 493 | offset = box.getAttribute('data-wow-offset') || this.config.offset; 494 | viewTop = (this.config.scrollContainer && this.config.scrollContainer.scrollTop) || window.pageYOffset; 495 | viewBottom = viewTop + Math.min(this.element.clientHeight, this.util().innerHeight()) - offset; 496 | top = this.offsetTop(box); 497 | bottom = top + box.clientHeight; 498 | return top <= viewBottom && bottom >= viewTop; 499 | }; 500 | 501 | WOW.prototype.util = function() { 502 | return this._util != null ? this._util : this._util = new Util(); 503 | }; 504 | 505 | WOW.prototype.disabled = function() { 506 | return !this.config.mobile && this.util().isMobile(navigator.userAgent); 507 | }; 508 | 509 | return WOW; 510 | 511 | })(); 512 | 513 | }).call(this); 514 | -------------------------------------------------------------------------------- /dist/wow.min.js: -------------------------------------------------------------------------------- 1 | /*! WOW - v1.1.3 - 2016-05-06 2 | * Copyright (c) 2016 Matthieu Aussaguel;*/(function(){var a,b,c,d,e,f=function(a,b){return function(){return a.apply(b,arguments)}},g=[].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1};b=function(){function a(){}return a.prototype.extend=function(a,b){var c,d;for(c in b)d=b[c],null==a[c]&&(a[c]=d);return a},a.prototype.isMobile=function(a){return/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(a)},a.prototype.createEvent=function(a,b,c,d){var e;return null==b&&(b=!1),null==c&&(c=!1),null==d&&(d=null),null!=document.createEvent?(e=document.createEvent("CustomEvent"),e.initCustomEvent(a,b,c,d)):null!=document.createEventObject?(e=document.createEventObject(),e.eventType=a):e.eventName=a,e},a.prototype.emitEvent=function(a,b){return null!=a.dispatchEvent?a.dispatchEvent(b):b in(null!=a)?a[b]():"on"+b in(null!=a)?a["on"+b]():void 0},a.prototype.addEvent=function(a,b,c){return null!=a.addEventListener?a.addEventListener(b,c,!1):null!=a.attachEvent?a.attachEvent("on"+b,c):a[b]=c},a.prototype.removeEvent=function(a,b,c){return null!=a.removeEventListener?a.removeEventListener(b,c,!1):null!=a.detachEvent?a.detachEvent("on"+b,c):delete a[b]},a.prototype.innerHeight=function(){return"innerHeight"in window?window.innerHeight:document.documentElement.clientHeight},a}(),c=this.WeakMap||this.MozWeakMap||(c=function(){function a(){this.keys=[],this.values=[]}return a.prototype.get=function(a){var b,c,d,e,f;for(f=this.keys,b=d=0,e=f.length;e>d;b=++d)if(c=f[b],c===a)return this.values[b]},a.prototype.set=function(a,b){var c,d,e,f,g;for(g=this.keys,c=e=0,f=g.length;f>e;c=++e)if(d=g[c],d===a)return void(this.values[c]=b);return this.keys.push(a),this.values.push(b)},a}()),a=this.MutationObserver||this.WebkitMutationObserver||this.MozMutationObserver||(a=function(){function a(){"undefined"!=typeof console&&null!==console&&console.warn("MutationObserver is not supported by your browser."),"undefined"!=typeof console&&null!==console&&console.warn("WOW.js cannot detect dom mutations, please call .sync() after loading new content.")}return a.notSupported=!0,a.prototype.observe=function(){},a}()),d=this.getComputedStyle||function(a,b){return this.getPropertyValue=function(b){var c;return"float"===b&&(b="styleFloat"),e.test(b)&&b.replace(e,function(a,b){return b.toUpperCase()}),(null!=(c=a.currentStyle)?c[b]:void 0)||null},this},e=/(\-([a-z]){1})/g,this.WOW=function(){function e(a){null==a&&(a={}),this.scrollCallback=f(this.scrollCallback,this),this.scrollHandler=f(this.scrollHandler,this),this.resetAnimation=f(this.resetAnimation,this),this.start=f(this.start,this),this.scrolled=!0,this.config=this.util().extend(a,this.defaults),null!=a.scrollContainer&&(this.config.scrollContainer=document.querySelector(a.scrollContainer)),this.animationNameCache=new c,this.wowEvent=this.util().createEvent(this.config.boxClass)}return e.prototype.defaults={boxClass:"wow",animateClass:"animated",offset:0,mobile:!0,live:!0,callback:null,scrollContainer:null},e.prototype.init=function(){var a;return this.element=window.document.documentElement,"interactive"===(a=document.readyState)||"complete"===a?this.start():this.util().addEvent(document,"DOMContentLoaded",this.start),this.finished=[]},e.prototype.start=function(){var b,c,d,e;if(this.stopped=!1,this.boxes=function(){var a,c,d,e;for(d=this.element.querySelectorAll("."+this.config.boxClass),e=[],a=0,c=d.length;c>a;a++)b=d[a],e.push(b);return e}.call(this),this.all=function(){var a,c,d,e;for(d=this.boxes,e=[],a=0,c=d.length;c>a;a++)b=d[a],e.push(b);return e}.call(this),this.boxes.length)if(this.disabled())this.resetStyle();else for(e=this.boxes,c=0,d=e.length;d>c;c++)b=e[c],this.applyStyle(b,!0);return this.disabled()||(this.util().addEvent(this.config.scrollContainer||window,"scroll",this.scrollHandler),this.util().addEvent(window,"resize",this.scrollHandler),this.interval=setInterval(this.scrollCallback,50)),this.config.live?new a(function(a){return function(b){var c,d,e,f,g;for(g=[],c=0,d=b.length;d>c;c++)f=b[c],g.push(function(){var a,b,c,d;for(c=f.addedNodes||[],d=[],a=0,b=c.length;b>a;a++)e=c[a],d.push(this.doSync(e));return d}.call(a));return g}}(this)).observe(document.body,{childList:!0,subtree:!0}):void 0},e.prototype.stop=function(){return this.stopped=!0,this.util().removeEvent(this.config.scrollContainer||window,"scroll",this.scrollHandler),this.util().removeEvent(window,"resize",this.scrollHandler),null!=this.interval?clearInterval(this.interval):void 0},e.prototype.sync=function(b){return a.notSupported?this.doSync(this.element):void 0},e.prototype.doSync=function(a){var b,c,d,e,f;if(null==a&&(a=this.element),1===a.nodeType){for(a=a.parentNode||a,e=a.querySelectorAll("."+this.config.boxClass),f=[],c=0,d=e.length;d>c;c++)b=e[c],g.call(this.all,b)<0?(this.boxes.push(b),this.all.push(b),this.stopped||this.disabled()?this.resetStyle():this.applyStyle(b,!0),f.push(this.scrolled=!0)):f.push(void 0);return f}},e.prototype.show=function(a){return this.applyStyle(a),a.className=a.className+" "+this.config.animateClass,null!=this.config.callback&&this.config.callback(a),this.util().emitEvent(a,this.wowEvent),this.util().addEvent(a,"animationend",this.resetAnimation),this.util().addEvent(a,"oanimationend",this.resetAnimation),this.util().addEvent(a,"webkitAnimationEnd",this.resetAnimation),this.util().addEvent(a,"MSAnimationEnd",this.resetAnimation),a},e.prototype.applyStyle=function(a,b){var c,d,e;return d=a.getAttribute("data-wow-duration"),c=a.getAttribute("data-wow-delay"),e=a.getAttribute("data-wow-iteration"),this.animate(function(f){return function(){return f.customStyle(a,b,d,c,e)}}(this))},e.prototype.animate=function(){return"requestAnimationFrame"in window?function(a){return window.requestAnimationFrame(a)}:function(a){return a()}}(),e.prototype.resetStyle=function(){var a,b,c,d,e;for(d=this.boxes,e=[],b=0,c=d.length;c>b;b++)a=d[b],e.push(a.style.visibility="visible");return e},e.prototype.resetAnimation=function(a){var b;return a.type.toLowerCase().indexOf("animationend")>=0?(b=a.target||a.srcElement,b.className=b.className.replace(this.config.animateClass,"").trim()):void 0},e.prototype.customStyle=function(a,b,c,d,e){return b&&this.cacheAnimationName(a),a.style.visibility=b?"hidden":"visible",c&&this.vendorSet(a.style,{animationDuration:c}),d&&this.vendorSet(a.style,{animationDelay:d}),e&&this.vendorSet(a.style,{animationIterationCount:e}),this.vendorSet(a.style,{animationName:b?"none":this.cachedAnimationName(a)}),a},e.prototype.vendors=["moz","webkit"],e.prototype.vendorSet=function(a,b){var c,d,e,f;d=[];for(c in b)e=b[c],a[""+c]=e,d.push(function(){var b,d,g,h;for(g=this.vendors,h=[],b=0,d=g.length;d>b;b++)f=g[b],h.push(a[""+f+c.charAt(0).toUpperCase()+c.substr(1)]=e);return h}.call(this));return d},e.prototype.vendorCSS=function(a,b){var c,e,f,g,h,i;for(h=d(a),g=h.getPropertyCSSValue(b),f=this.vendors,c=0,e=f.length;e>c;c++)i=f[c],g=g||h.getPropertyCSSValue("-"+i+"-"+b);return g},e.prototype.animationName=function(a){var b;try{b=this.vendorCSS(a,"animation-name").cssText}catch(c){b=d(a).getPropertyValue("animation-name")}return"none"===b?"":b},e.prototype.cacheAnimationName=function(a){return this.animationNameCache.set(a,this.animationName(a))},e.prototype.cachedAnimationName=function(a){return this.animationNameCache.get(a)},e.prototype.scrollHandler=function(){return this.scrolled=!0},e.prototype.scrollCallback=function(){var a;return!this.scrolled||(this.scrolled=!1,this.boxes=function(){var b,c,d,e;for(d=this.boxes,e=[],b=0,c=d.length;c>b;b++)a=d[b],a&&(this.isVisible(a)?this.show(a):e.push(a));return e}.call(this),this.boxes.length||this.config.live)?void 0:this.stop()},e.prototype.offsetTop=function(a){for(var b;void 0===a.offsetTop;)a=a.parentNode;for(b=a.offsetTop;a=a.offsetParent;)b+=a.offsetTop;return b},e.prototype.isVisible=function(a){var b,c,d,e,f;return c=a.getAttribute("data-wow-offset")||this.config.offset,f=this.config.scrollContainer&&this.config.scrollContainer.scrollTop||window.pageYOffset,e=f+Math.min(this.element.clientHeight,this.util().innerHeight())-c,d=this.offsetTop(a),b=d+a.clientHeight,e>=d&&b>=f},e.prototype.util=function(){return null!=this._util?this._util:this._util=new b},e.prototype.disabled=function(){return!this.config.mobile&&this.util().isMobile(navigator.userAgent)},e}()}).call(this); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "wowjs", 3 | "title" : "WOW", 4 | "version" : "1.1.3", 5 | "description" : "", 6 | "keywords": [], 7 | "homepage" : "", 8 | "author" : { 9 | "name" : "Matt Delac", 10 | "email" : "matt@delac.io", 11 | "url" : "https://www.delac.io/" 12 | }, 13 | "main": "./dist/wow.js", 14 | "repository" : { 15 | "type" : "git", 16 | "url" : "git://github.com/matthieua/WOW.git" 17 | }, 18 | "bugs" : { 19 | "url" : "https://github.com/matthieua/WOW/issues" 20 | }, 21 | "licenses": [{ 22 | "type": "GPLv3", 23 | "url": "https://www.delac.io/WOW" 24 | }], 25 | "dependencies": { 26 | "animate.css": "latest" 27 | }, 28 | "devDependencies" : { 29 | "grunt" : "latest", 30 | "grunt-cli" : "latest", 31 | "grunt-contrib-watch" : "latest", 32 | "grunt-contrib-coffee" : "latest", 33 | "grunt-contrib-jasmine": "latest", 34 | "grunt-contrib-uglify" : "latest", 35 | "grunt-growl" : "latest" 36 | }, 37 | "scripts": { 38 | "test": "grunt travis" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /spec/coffeescripts/helpers/SpecHelper.coffee: -------------------------------------------------------------------------------- 1 | beforeEach -> -------------------------------------------------------------------------------- /spec/coffeescripts/wow-spec.coffee: -------------------------------------------------------------------------------- 1 | describe 'WOW', -> 2 | 3 | # Supress warnings: 4 | window.console = 5 | warn: -> 6 | 7 | # Time to wait after each scroll event: 8 | # (This should be >= the interval used by the plugin.) 9 | timeout = 100 10 | 11 | # Height of the PhantomJS window: 12 | winHeight = 300 13 | 14 | describe 'smoke test', -> 15 | 16 | it 'exists', -> 17 | expect WOW 18 | .toBeDefined() 19 | 20 | it "has an 'init' method", -> 21 | expect new WOW().init 22 | .toBeDefined() 23 | 24 | describe 'simple test environment', -> 25 | 26 | beforeEach -> 27 | loadFixtures 'simple.html' 28 | 29 | it 'emulates window height', -> 30 | expect document.documentElement.clientHeight 31 | .toBe winHeight 32 | 33 | it 'has boxes set up for testing', -> 34 | boxHeight = 200 35 | boxCount = $ '#simple' 36 | .children().length 37 | # Check each box height 38 | expect $('#simple').height() 39 | .toBe boxHeight*boxCount 40 | expect $('#simple-1').height() 41 | .toBe boxHeight 42 | expect $('#simple-2').height() 43 | .toBe boxHeight 44 | expect $('#simple-3').height() 45 | .toBe boxHeight 46 | expect $('#simple-4').height() 47 | .toBe boxHeight 48 | expect $('#simple-5').height() 49 | .toBe boxHeight 50 | # Check each box offset 51 | offset = $('#simple').offset().top 52 | expect $('#simple-1').offset().top 53 | .toBe offset + boxHeight*0 54 | expect $('#simple-2').offset().top 55 | .toBe offset + boxHeight*1 56 | expect $('#simple-3').offset().top 57 | .toBe offset + boxHeight*2 58 | expect $('#simple-4').offset().top 59 | .toBe offset + boxHeight*3 60 | expect $('#simple-5').offset().top 61 | .toBe offset + boxHeight*4 62 | style = $('#simple-5')[0].style 63 | expect style.background 64 | .toBe 'yellow' 65 | expect style.color 66 | .toBe 'red' 67 | 68 | describe 'library behaviour', -> 69 | 70 | wow = null 71 | 72 | beforeEach (done) -> 73 | loadFixtures 'simple.html' 74 | (wow = new WOW).init() 75 | setTimeout -> 76 | done() 77 | , timeout 78 | 79 | it 'animates elements that are fully visible on the page', -> 80 | expect $ '#simple-1' 81 | .toHaveClass 'animated' 82 | expect $('#simple-1').css 'visibility' 83 | .toBe 'visible' 84 | 85 | it "does not touch elements that don't have the marker class", -> 86 | expect $ '#simple-2' 87 | .not.toHaveClass 'animated' 88 | expect $('#simple-2').css 'visibility' 89 | .toBe 'visible' 90 | 91 | it 'does not animate elements not yet visible on the page', -> 92 | expect $ '#simple-3' 93 | .not.toHaveClass 'animated' 94 | expect $('#simple-3').css 'visibility' 95 | .not.toBe 'visible' 96 | expect $ '#simple-4' 97 | .not.toHaveClass 'animated' 98 | expect $('#simple-4').css 'visibility' 99 | .not.toBe 'visible' 100 | 101 | it 'animates elements after scrolling down and they become visible', (done) -> 102 | # Scroll down so that 150px of #simple-3 becomes visible. 103 | window.scrollTo 0, $('#simple-3').offset().top - winHeight + 150 104 | setTimeout -> 105 | expect $ '#simple-3' 106 | .toHaveClass 'animated' 107 | expect $('#simple-3').css 'visibility' 108 | .toBe 'visible' 109 | expect $ '#simple-4' 110 | .not.toHaveClass 'animated' 111 | expect $('#simple-4').css 'visibility' 112 | .not.toBe 'visible' 113 | # Scroll down so that 150px of #simple-4 becomes visible. 114 | window.scrollTo 0, $('#simple-4').offset().top - winHeight + 150 115 | setTimeout -> 116 | expect $ '#simple-4' 117 | .toHaveClass 'animated' 118 | expect $('#simple-4').css 'visibility' 119 | .toBe 'visible' 120 | done() 121 | , timeout 122 | , timeout 123 | 124 | it 'does not tamper with the style attribute', (done) -> 125 | # Scroll down so that 150px of #simple-5 becomes visible. 126 | window.scrollTo 0, $('#simple-5').offset().top - winHeight + 150 127 | setTimeout -> 128 | expect $ '#simple-5' 129 | .toHaveClass 'animated' 130 | expect $('#simple-5').css 'visibility' 131 | .toBe 'visible' 132 | expect $('#simple-5')[0].style.background 133 | .toBe 'yellow' 134 | expect $('#simple-5')[0].style.color 135 | .toBe 'red' 136 | done() 137 | , timeout 138 | 139 | it 'works with asynchronously loaded content', (done) -> 140 | $ '#simple' 141 | .append $ '
', 142 | id: 'simple-6' 143 | class: 'wow' 144 | wow.sync() 145 | # Scroll down so that 150px of #simple-6 becomes visible. 146 | window.scrollTo 0, $('#simple-6').offset().top - winHeight + 150 147 | setTimeout -> 148 | expect $ '#simple-6' 149 | .toHaveClass 'animated' 150 | expect $('#simple-6').css 'visibility' 151 | .toBe 'visible' 152 | done() 153 | , timeout 154 | 155 | it 'works with asynchronously loaded nested content', (done) -> 156 | $ '#simple' 157 | .append $ '
' 158 | .children() 159 | .first() 160 | .append $ '
', 161 | id: 'simple-7' 162 | class: 'wow' 163 | wow.sync() 164 | # Scroll down so that 150px of #simple-7 becomes visible. 165 | window.scrollTo 0, $('#simple-7').offset().top - winHeight + 150 166 | setTimeout -> 167 | expect $ '#simple-7' 168 | .toHaveClass 'animated' 169 | expect $('#simple-7').css 'visibility' 170 | .toBe 'visible' 171 | done() 172 | , timeout 173 | 174 | describe 'custom test environment', -> 175 | 176 | beforeEach -> 177 | loadFixtures 'custom.html' 178 | 179 | it 'emulates window height', -> 180 | expect document.documentElement.clientHeight 181 | .toBe winHeight 182 | 183 | it 'has boxes set up for testing', -> 184 | # Check each box height 185 | expect $('#custom').height() 186 | .toBe 800 187 | expect $('#custom-1').height() 188 | .toBe 200 189 | expect $('#custom-2').height() 190 | .toBe 200 191 | expect $('#custom-3').height() 192 | .toBe 200 193 | expect $('#custom-4').height() 194 | .toBe 200 195 | # Check each box offset 196 | offset = $('#custom').offset().top 197 | expect $('#custom-1').offset().top 198 | .toBe offset + 200*0 199 | expect $('#custom-2').offset().top 200 | .toBe offset + 200*1 201 | expect $('#custom-3').offset().top 202 | .toBe offset + 200*2 203 | expect $('#custom-4').offset().top 204 | .toBe offset + 200*3 205 | 206 | describe 'library behaviour with custom settings', -> 207 | 208 | called = false 209 | 210 | beforeEach (done) -> 211 | called = false 212 | loadFixtures 'custom.html' 213 | new WOW 214 | boxClass: 'block' 215 | animateClass: 'fancy' 216 | offset: 10 217 | callback: -> 218 | called = true 219 | .init() 220 | 221 | # Trigger custom event on dom object, event name is boxClass value 222 | $('.block').on 'block', -> 223 | $(this).addClass('triggered') 224 | 225 | setTimeout -> 226 | done() 227 | , timeout 228 | 229 | it "creates two instances of the WOW.js with different configs", -> 230 | wow1 = new WOW 231 | boxClass: 'block1' 232 | animateClass: 'fancy1' 233 | offset: 10 234 | wow2 = new WOW 235 | boxClass: 'block2' 236 | animateClass: 'fancy2' 237 | offset: 20 238 | 239 | expect wow1.config.boxClass 240 | .toBe "block1" 241 | expect wow1.config.animateClass 242 | .toBe "fancy1" 243 | expect wow1.config.offset 244 | .toBe 10 245 | 246 | it "does not touch elements that don't have the marker class", (done) -> 247 | # Scroll down so that 15px of #custom-1 becomes visible. 248 | window.scrollTo 0, $('#custom-1').offset().top - winHeight + 15 249 | setTimeout -> 250 | expect $ '#custom-1' 251 | .not.toHaveClass 'fancy' 252 | done() 253 | , timeout 254 | 255 | it "animates elements that are partially visible on the page based on the 'offset' config", (done) -> 256 | setTimeout -> 257 | # Scroll down so that 5px of #custom-2 becomes visible. 258 | window.scrollTo 0, $('#custom-2').offset().top - winHeight + 5 259 | expect $ '#custom-2' 260 | .not.toHaveClass 'fancy' 261 | window.scrollTo 0, $('#custom-2').offset().top - winHeight + 15 262 | setTimeout -> 263 | # Scroll down so that 15px of #custom-2 becomes visible. 264 | expect $ '#custom-2' 265 | .toHaveClass 'fancy' 266 | expect $('#custom-2').css 'visibility' 267 | .toBe 'visible' 268 | done() 269 | , timeout 270 | , timeout 271 | 272 | it 'does not animate elements not yet visible on the page', -> 273 | expect $ '#custom-3' 274 | .not.toHaveClass 'fancy' 275 | expect $ '#custom-4' 276 | .not.toHaveClass 'fancy' 277 | 278 | it 'animates elements after scrolling down and they become visible', (done) -> 279 | # Scroll down so that 150px of #custom-3 becomes visible. 280 | window.scrollTo 0, $('#custom-3').offset().top - winHeight + 150 281 | setTimeout -> 282 | expect $ '#custom-3' 283 | .toHaveClass 'fancy' 284 | expect $('#custom-3').css 'visibility' 285 | .toBe 'visible' 286 | expect $('#custom-3')[0].style.webkitAnimationIterationCount 287 | .toBe '2' 288 | expect $ '#custom-4' 289 | .not.toHaveClass 'fancy' 290 | # Scroll down so that 150px of #custom-4 becomes visible. 291 | window.scrollTo 0, $('#custom-4').offset().top - winHeight + 150 292 | setTimeout -> 293 | expect $ '#custom-4' 294 | .toHaveClass 'fancy' 295 | expect $('#custom-4').css 'visibility' 296 | .toBe 'visible' 297 | expect $('#custom-4')[0].style.webkitAnimationIterationCount 298 | .toBe 'infinite' 299 | expect $('#custom-4')[0].style.webkitAnimationDuration 300 | .toBe '2s' 301 | expect $('#custom-4')[0].style.webkitAnimationDelay 302 | .toBe '1s' 303 | done() 304 | , timeout 305 | , timeout 306 | 307 | it "fires the callback", (done) -> 308 | called = false # reset 309 | # Scroll down so that 150px of #custom-3 becomes visible. 310 | window.scrollTo 0, $('#custom-3').offset().top - winHeight + 150 311 | setTimeout -> 312 | expect called 313 | .toBe true 314 | done() 315 | , timeout 316 | 317 | it 'fires the callback on the visible element', (done) -> 318 | # Scroll down so that 150px of #custom-3 becomes visible. 319 | window.scrollTo 0, $('#custom-3').offset().top - winHeight + 150 320 | setTimeout -> 321 | expect $ '#custom-3' 322 | .toHaveClass 'triggered' 323 | expect $ '#custom-4' 324 | .not.toHaveClass 'triggered' 325 | # Scroll down so that 150px of #custom-4 becomes visible. 326 | window.scrollTo 0, $('#custom-4').offset().top - winHeight + 150 327 | setTimeout -> 328 | expect $ '#custom-3' 329 | .toHaveClass 'triggered' 330 | expect $ '#custom-4' 331 | .toHaveClass 'triggered' 332 | done() 333 | , timeout 334 | , timeout 335 | -------------------------------------------------------------------------------- /spec/javascripts/fixtures/custom.html: -------------------------------------------------------------------------------- 1 |
Test 1
Test 2
Test 3
Test 4
-------------------------------------------------------------------------------- /spec/javascripts/fixtures/simple.html: -------------------------------------------------------------------------------- 1 |
Test 1
Test 2
Test 3
Test 4
Test 5
-------------------------------------------------------------------------------- /spec/javascripts/helpers/SpecHelper.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | beforeEach(function() {}); 3 | 4 | }).call(this); 5 | -------------------------------------------------------------------------------- /spec/javascripts/libs/jasmine-jquery.js: -------------------------------------------------------------------------------- 1 | /*! 2 | Jasmine-jQuery: a set of jQuery helpers for Jasmine tests. 3 | 4 | Version 2.0.2 5 | 6 | https://github.com/velesin/jasmine-jquery 7 | 8 | Copyright (c) 2010-2014 Wojciech Zawistowski, Travis Jeffery 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining 11 | a copy of this software and associated documentation files (the 12 | "Software"), to deal in the Software without restriction, including 13 | without limitation the rights to use, copy, modify, merge, publish, 14 | distribute, sublicense, and/or sell copies of the Software, and to 15 | permit persons to whom the Software is furnished to do so, subject to 16 | the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 25 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 27 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | */ 29 | 30 | +function (window, jasmine, $) { "use strict"; 31 | 32 | jasmine.spiedEventsKey = function (selector, eventName) { 33 | return [$(selector).selector, eventName].toString() 34 | } 35 | 36 | jasmine.getFixtures = function () { 37 | return jasmine.currentFixtures_ = jasmine.currentFixtures_ || new jasmine.Fixtures() 38 | } 39 | 40 | jasmine.getStyleFixtures = function () { 41 | return jasmine.currentStyleFixtures_ = jasmine.currentStyleFixtures_ || new jasmine.StyleFixtures() 42 | } 43 | 44 | jasmine.Fixtures = function () { 45 | this.containerId = 'jasmine-fixtures' 46 | this.fixturesCache_ = {} 47 | this.fixturesPath = 'spec/javascripts/fixtures' 48 | } 49 | 50 | jasmine.Fixtures.prototype.set = function (html) { 51 | this.cleanUp() 52 | return this.createContainer_(html) 53 | } 54 | 55 | jasmine.Fixtures.prototype.appendSet= function (html) { 56 | this.addToContainer_(html) 57 | } 58 | 59 | jasmine.Fixtures.prototype.preload = function () { 60 | this.read.apply(this, arguments) 61 | } 62 | 63 | jasmine.Fixtures.prototype.load = function () { 64 | this.cleanUp() 65 | this.createContainer_(this.read.apply(this, arguments)) 66 | } 67 | 68 | jasmine.Fixtures.prototype.appendLoad = function () { 69 | this.addToContainer_(this.read.apply(this, arguments)) 70 | } 71 | 72 | jasmine.Fixtures.prototype.read = function () { 73 | var htmlChunks = [] 74 | , fixtureUrls = arguments 75 | 76 | for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) { 77 | htmlChunks.push(this.getFixtureHtml_(fixtureUrls[urlIndex])) 78 | } 79 | 80 | return htmlChunks.join('') 81 | } 82 | 83 | jasmine.Fixtures.prototype.clearCache = function () { 84 | this.fixturesCache_ = {} 85 | } 86 | 87 | jasmine.Fixtures.prototype.cleanUp = function () { 88 | $('#' + this.containerId).remove() 89 | } 90 | 91 | jasmine.Fixtures.prototype.sandbox = function (attributes) { 92 | var attributesToSet = attributes || {} 93 | return $('
').attr(attributesToSet) 94 | } 95 | 96 | jasmine.Fixtures.prototype.createContainer_ = function (html) { 97 | var container = $('
') 98 | .attr('id', this.containerId) 99 | .html(html) 100 | 101 | $(document.body).append(container) 102 | return container 103 | } 104 | 105 | jasmine.Fixtures.prototype.addToContainer_ = function (html){ 106 | var container = $(document.body).find('#'+this.containerId).append(html) 107 | 108 | if (!container.length) { 109 | this.createContainer_(html) 110 | } 111 | } 112 | 113 | jasmine.Fixtures.prototype.getFixtureHtml_ = function (url) { 114 | if (typeof this.fixturesCache_[url] === 'undefined') { 115 | this.loadFixtureIntoCache_(url) 116 | } 117 | return this.fixturesCache_[url] 118 | } 119 | 120 | jasmine.Fixtures.prototype.loadFixtureIntoCache_ = function (relativeUrl) { 121 | var self = this 122 | , url = this.makeFixtureUrl_(relativeUrl) 123 | , htmlText = '' 124 | , request = $.ajax({ 125 | async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded 126 | cache: false, 127 | url: url, 128 | success: function (data, status, $xhr) { 129 | htmlText = $xhr.responseText 130 | } 131 | }).fail(function () { 132 | throw new Error('Fixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + errorThrown.message + ')') 133 | }) 134 | 135 | var scripts = $($.parseHTML(htmlText, true)).find('script[src]') || []; 136 | 137 | scripts.each(function(){ 138 | $.ajax({ 139 | async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded 140 | cache: false, 141 | dataType: 'script', 142 | url: $(this).attr('src'), 143 | success: function (data, status, $xhr) { 144 | htmlText += '' 145 | }, 146 | error: function (jqXHR, status, errorThrown) { 147 | throw new Error('Script could not be loaded: ' + scriptSrc + ' (status: ' + status + ', message: ' + errorThrown.message + ')') 148 | } 149 | }); 150 | }) 151 | 152 | self.fixturesCache_[relativeUrl] = htmlText; 153 | } 154 | 155 | jasmine.Fixtures.prototype.makeFixtureUrl_ = function (relativeUrl){ 156 | return this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl 157 | } 158 | 159 | jasmine.Fixtures.prototype.proxyCallTo_ = function (methodName, passedArguments) { 160 | return this[methodName].apply(this, passedArguments) 161 | } 162 | 163 | 164 | jasmine.StyleFixtures = function () { 165 | this.fixturesCache_ = {} 166 | this.fixturesNodes_ = [] 167 | this.fixturesPath = 'spec/javascripts/fixtures' 168 | } 169 | 170 | jasmine.StyleFixtures.prototype.set = function (css) { 171 | this.cleanUp() 172 | this.createStyle_(css) 173 | } 174 | 175 | jasmine.StyleFixtures.prototype.appendSet = function (css) { 176 | this.createStyle_(css) 177 | } 178 | 179 | jasmine.StyleFixtures.prototype.preload = function () { 180 | this.read_.apply(this, arguments) 181 | } 182 | 183 | jasmine.StyleFixtures.prototype.load = function () { 184 | this.cleanUp() 185 | this.createStyle_(this.read_.apply(this, arguments)) 186 | } 187 | 188 | jasmine.StyleFixtures.prototype.appendLoad = function () { 189 | this.createStyle_(this.read_.apply(this, arguments)) 190 | } 191 | 192 | jasmine.StyleFixtures.prototype.cleanUp = function () { 193 | while(this.fixturesNodes_.length) { 194 | this.fixturesNodes_.pop().remove() 195 | } 196 | } 197 | 198 | jasmine.StyleFixtures.prototype.createStyle_ = function (html) { 199 | var styleText = $('
').html(html).text() 200 | , style = $('') 201 | 202 | this.fixturesNodes_.push(style) 203 | $('head').append(style) 204 | } 205 | 206 | jasmine.StyleFixtures.prototype.clearCache = jasmine.Fixtures.prototype.clearCache 207 | jasmine.StyleFixtures.prototype.read_ = jasmine.Fixtures.prototype.read 208 | jasmine.StyleFixtures.prototype.getFixtureHtml_ = jasmine.Fixtures.prototype.getFixtureHtml_ 209 | jasmine.StyleFixtures.prototype.loadFixtureIntoCache_ = jasmine.Fixtures.prototype.loadFixtureIntoCache_ 210 | jasmine.StyleFixtures.prototype.makeFixtureUrl_ = jasmine.Fixtures.prototype.makeFixtureUrl_ 211 | jasmine.StyleFixtures.prototype.proxyCallTo_ = jasmine.Fixtures.prototype.proxyCallTo_ 212 | 213 | jasmine.getJSONFixtures = function () { 214 | return jasmine.currentJSONFixtures_ = jasmine.currentJSONFixtures_ || new jasmine.JSONFixtures() 215 | } 216 | 217 | jasmine.JSONFixtures = function () { 218 | this.fixturesCache_ = {} 219 | this.fixturesPath = 'spec/javascripts/fixtures/json' 220 | } 221 | 222 | jasmine.JSONFixtures.prototype.load = function () { 223 | this.read.apply(this, arguments) 224 | return this.fixturesCache_ 225 | } 226 | 227 | jasmine.JSONFixtures.prototype.read = function () { 228 | var fixtureUrls = arguments 229 | 230 | for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) { 231 | this.getFixtureData_(fixtureUrls[urlIndex]) 232 | } 233 | 234 | return this.fixturesCache_ 235 | } 236 | 237 | jasmine.JSONFixtures.prototype.clearCache = function () { 238 | this.fixturesCache_ = {} 239 | } 240 | 241 | jasmine.JSONFixtures.prototype.getFixtureData_ = function (url) { 242 | if (!this.fixturesCache_[url]) this.loadFixtureIntoCache_(url) 243 | return this.fixturesCache_[url] 244 | } 245 | 246 | jasmine.JSONFixtures.prototype.loadFixtureIntoCache_ = function (relativeUrl) { 247 | var self = this 248 | , url = this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl 249 | 250 | $.ajax({ 251 | async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded 252 | cache: false, 253 | dataType: 'json', 254 | url: url, 255 | success: function (data) { 256 | self.fixturesCache_[relativeUrl] = data 257 | }, 258 | error: function (jqXHR, status, errorThrown) { 259 | throw new Error('JSONFixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + errorThrown.message + ')') 260 | } 261 | }) 262 | } 263 | 264 | jasmine.JSONFixtures.prototype.proxyCallTo_ = function (methodName, passedArguments) { 265 | return this[methodName].apply(this, passedArguments) 266 | } 267 | 268 | jasmine.jQuery = function () {} 269 | 270 | jasmine.jQuery.browserTagCaseIndependentHtml = function (html) { 271 | return $('
').append(html).html() 272 | } 273 | 274 | jasmine.jQuery.elementToString = function (element) { 275 | return $(element).map(function () { return this.outerHTML; }).toArray().join(', ') 276 | } 277 | 278 | var data = { 279 | spiedEvents: {} 280 | , handlers: [] 281 | } 282 | 283 | jasmine.jQuery.events = { 284 | spyOn: function (selector, eventName) { 285 | var handler = function (e) { 286 | data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] = jasmine.util.argsToArray(arguments) 287 | } 288 | 289 | $(selector).on(eventName, handler) 290 | data.handlers.push(handler) 291 | 292 | return { 293 | selector: selector, 294 | eventName: eventName, 295 | handler: handler, 296 | reset: function (){ 297 | delete data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] 298 | } 299 | } 300 | }, 301 | 302 | args: function (selector, eventName) { 303 | var actualArgs = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] 304 | 305 | if (!actualArgs) { 306 | throw "There is no spy for " + eventName + " on " + selector.toString() + ". Make sure to create a spy using spyOnEvent." 307 | } 308 | 309 | return actualArgs 310 | }, 311 | 312 | wasTriggered: function (selector, eventName) { 313 | return !!(data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]) 314 | }, 315 | 316 | wasTriggeredWith: function (selector, eventName, expectedArgs, util, customEqualityTesters) { 317 | var actualArgs = jasmine.jQuery.events.args(selector, eventName).slice(1) 318 | 319 | if (Object.prototype.toString.call(expectedArgs) !== '[object Array]') 320 | actualArgs = actualArgs[0] 321 | 322 | return util.equals(expectedArgs, actualArgs, customEqualityTesters) 323 | }, 324 | 325 | wasPrevented: function (selector, eventName) { 326 | var args = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] 327 | , e = args ? args[0] : undefined 328 | 329 | return e && e.isDefaultPrevented() 330 | }, 331 | 332 | wasStopped: function (selector, eventName) { 333 | var args = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] 334 | , e = args ? args[0] : undefined 335 | return e && e.isPropagationStopped() 336 | }, 337 | 338 | cleanUp: function () { 339 | data.spiedEvents = {} 340 | data.handlers = [] 341 | } 342 | } 343 | 344 | var hasProperty = function (actualValue, expectedValue) { 345 | if (expectedValue === undefined) 346 | return actualValue !== undefined 347 | 348 | return actualValue === expectedValue 349 | } 350 | 351 | beforeEach(function () { 352 | jasmine.addMatchers({ 353 | toHaveClass: function () { 354 | return { 355 | compare: function (actual, className) { 356 | return { pass: $(actual).hasClass(className) } 357 | } 358 | } 359 | }, 360 | 361 | toHaveCss: function () { 362 | return { 363 | compare: function (actual, css) { 364 | for (var prop in css){ 365 | var value = css[prop] 366 | // see issue #147 on gh 367 | ;if (value === 'auto' && $(actual).get(0).style[prop] === 'auto') continue 368 | if ($(actual).css(prop) !== value) return { pass: false } 369 | } 370 | return { pass: true } 371 | } 372 | } 373 | }, 374 | 375 | toBeVisible: function () { 376 | return { 377 | compare: function (actual) { 378 | return { pass: $(actual).is(':visible') } 379 | } 380 | } 381 | }, 382 | 383 | toBeHidden: function () { 384 | return { 385 | compare: function (actual) { 386 | return { pass: $(actual).is(':hidden') } 387 | } 388 | } 389 | }, 390 | 391 | toBeSelected: function () { 392 | return { 393 | compare: function (actual) { 394 | return { pass: $(actual).is(':selected') } 395 | } 396 | } 397 | }, 398 | 399 | toBeChecked: function () { 400 | return { 401 | compare: function (actual) { 402 | return { pass: $(actual).is(':checked') } 403 | } 404 | } 405 | }, 406 | 407 | toBeEmpty: function () { 408 | return { 409 | compare: function (actual) { 410 | return { pass: $(actual).is(':empty') } 411 | } 412 | } 413 | }, 414 | 415 | toBeInDOM: function () { 416 | return { 417 | compare: function (actual) { 418 | return { pass: $.contains(document.documentElement, $(actual)[0]) } 419 | } 420 | } 421 | }, 422 | 423 | toExist: function () { 424 | return { 425 | compare: function (actual) { 426 | return { pass: $(actual).length } 427 | } 428 | } 429 | }, 430 | 431 | toHaveLength: function () { 432 | return { 433 | compare: function (actual, length) { 434 | return { pass: $(actual).length === length } 435 | } 436 | } 437 | }, 438 | 439 | toHaveAttr: function () { 440 | return { 441 | compare: function (actual, attributeName, expectedAttributeValue) { 442 | return { pass: hasProperty($(actual).attr(attributeName), expectedAttributeValue) } 443 | } 444 | } 445 | }, 446 | 447 | toHaveProp: function () { 448 | return { 449 | compare: function (actual, propertyName, expectedPropertyValue) { 450 | return { pass: hasProperty($(actual).prop(propertyName), expectedPropertyValue) } 451 | } 452 | } 453 | }, 454 | 455 | toHaveId: function () { 456 | return { 457 | compare: function (actual, id) { 458 | return { pass: $(actual).attr('id') == id } 459 | } 460 | } 461 | }, 462 | 463 | toHaveHtml: function () { 464 | return { 465 | compare: function (actual, html) { 466 | return { pass: $(actual).html() == jasmine.jQuery.browserTagCaseIndependentHtml(html) } 467 | } 468 | } 469 | }, 470 | 471 | toContainHtml: function () { 472 | return { 473 | compare: function (actual, html) { 474 | var actualHtml = $(actual).html() 475 | , expectedHtml = jasmine.jQuery.browserTagCaseIndependentHtml(html) 476 | 477 | return { pass: (actualHtml.indexOf(expectedHtml) >= 0) } 478 | } 479 | } 480 | }, 481 | 482 | toHaveText: function () { 483 | return { 484 | compare: function (actual, text) { 485 | var trimmedText = $.trim($(actual).text()) 486 | 487 | if (text && $.isFunction(text.test)) { 488 | return { pass: text.test(trimmedText) } 489 | } else { 490 | return { pass: trimmedText == text } 491 | } 492 | } 493 | } 494 | }, 495 | 496 | toContainText: function () { 497 | return { 498 | compare: function (actual, text) { 499 | var trimmedText = $.trim($(actual).text()) 500 | 501 | if (text && $.isFunction(text.test)) { 502 | return { pass: text.test(trimmedText) } 503 | } else { 504 | return { pass: trimmedText.indexOf(text) != -1 } 505 | } 506 | } 507 | } 508 | }, 509 | 510 | toHaveValue: function () { 511 | return { 512 | compare: function (actual, value) { 513 | return { pass: $(actual).val() === value } 514 | } 515 | } 516 | }, 517 | 518 | toHaveData: function () { 519 | return { 520 | compare: function (actual, key, expectedValue) { 521 | return { pass: hasProperty($(actual).data(key), expectedValue) } 522 | } 523 | } 524 | }, 525 | 526 | toContainElement: function () { 527 | return { 528 | compare: function (actual, selector) { 529 | if (window.debug) debugger 530 | return { pass: $(actual).find(selector).length } 531 | } 532 | } 533 | }, 534 | 535 | toBeMatchedBy: function () { 536 | return { 537 | compare: function (actual, selector) { 538 | return { pass: $(actual).filter(selector).length } 539 | } 540 | } 541 | }, 542 | 543 | toBeDisabled: function () { 544 | return { 545 | compare: function (actual, selector) { 546 | return { pass: $(actual).is(':disabled') } 547 | } 548 | } 549 | }, 550 | 551 | toBeFocused: function (selector) { 552 | return { 553 | compare: function (actual, selector) { 554 | return { pass: $(actual)[0] === $(actual)[0].ownerDocument.activeElement } 555 | } 556 | } 557 | }, 558 | 559 | toHandle: function () { 560 | return { 561 | compare: function (actual, event) { 562 | var events = $._data($(actual).get(0), "events") 563 | 564 | if (!events || !event || typeof event !== "string") { 565 | return { pass: false } 566 | } 567 | 568 | var namespaces = event.split(".") 569 | , eventType = namespaces.shift() 570 | , sortedNamespaces = namespaces.slice(0).sort() 571 | , namespaceRegExp = new RegExp("(^|\\.)" + sortedNamespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") 572 | 573 | if (events[eventType] && namespaces.length) { 574 | for (var i = 0; i < events[eventType].length; i++) { 575 | var namespace = events[eventType][i].namespace 576 | 577 | if (namespaceRegExp.test(namespace)) 578 | return { pass: true } 579 | } 580 | } else { 581 | return { pass: (events[eventType] && events[eventType].length > 0) } 582 | } 583 | 584 | return { pass: false } 585 | } 586 | } 587 | }, 588 | 589 | toHandleWith: function () { 590 | return { 591 | compare: function (actual, eventName, eventHandler) { 592 | var normalizedEventName = eventName.split('.')[0] 593 | , stack = $._data($(actual).get(0), "events")[normalizedEventName] 594 | 595 | for (var i = 0; i < stack.length; i++) { 596 | if (stack[i].handler == eventHandler) return { pass: true } 597 | } 598 | 599 | return { pass: false } 600 | } 601 | } 602 | }, 603 | 604 | toHaveBeenTriggeredOn: function () { 605 | return { 606 | compare: function (actual, selector) { 607 | var result = { pass: jasmine.jQuery.events.wasTriggered(selector, actual) } 608 | 609 | result.message = result.pass ? 610 | "Expected event " + $(actual) + " not to have been triggered on " + selector : 611 | "Expected event " + $(actual) + " to have been triggered on " + selector 612 | 613 | return result; 614 | } 615 | } 616 | }, 617 | 618 | toHaveBeenTriggered: function (){ 619 | return { 620 | compare: function (actual) { 621 | var eventName = actual.eventName 622 | , selector = actual.selector 623 | , result = { pass: jasmine.jQuery.events.wasTriggered(selector, eventName) } 624 | 625 | result.message = result.pass ? 626 | "Expected event " + eventName + " not to have been triggered on " + selector : 627 | "Expected event " + eventName + " to have been triggered on " + selector 628 | 629 | return result 630 | } 631 | } 632 | }, 633 | 634 | toHaveBeenTriggeredOnAndWith: function (j$, customEqualityTesters) { 635 | return { 636 | compare: function (actual, selector, expectedArgs) { 637 | var wasTriggered = jasmine.jQuery.events.wasTriggered(selector, actual) 638 | , result = { pass: wasTriggered && jasmine.jQuery.events.wasTriggeredWith(selector, actual, expectedArgs, j$, customEqualityTesters) } 639 | 640 | if (wasTriggered) { 641 | var actualArgs = jasmine.jQuery.events.args(selector, actual, expectedArgs)[1] 642 | result.message = result.pass ? 643 | "Expected event " + actual + " not to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs) : 644 | "Expected event " + actual + " to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs) 645 | 646 | } else { 647 | // todo check on this 648 | result.message = result.pass ? 649 | "Expected event " + actual + " not to have been triggered on " + selector : 650 | "Expected event " + actual + " to have been triggered on " + selector 651 | } 652 | 653 | return result 654 | } 655 | } 656 | }, 657 | 658 | toHaveBeenPreventedOn: function () { 659 | return { 660 | compare: function (actual, selector) { 661 | var result = { pass: jasmine.jQuery.events.wasPrevented(selector, actual) } 662 | 663 | result.message = result.pass ? 664 | "Expected event " + actual + " not to have been prevented on " + selector : 665 | "Expected event " + actual + " to have been prevented on " + selector 666 | 667 | return result 668 | } 669 | } 670 | }, 671 | 672 | toHaveBeenPrevented: function () { 673 | return { 674 | compare: function (actual) { 675 | var eventName = actual.eventName 676 | , selector = actual.selector 677 | , result = { pass: jasmine.jQuery.events.wasPrevented(selector, eventName) } 678 | 679 | result.message = result.pass ? 680 | "Expected event " + eventName + " not to have been prevented on " + selector : 681 | "Expected event " + eventName + " to have been prevented on " + selector 682 | 683 | return result 684 | } 685 | } 686 | }, 687 | 688 | toHaveBeenStoppedOn: function () { 689 | return { 690 | compare: function (actual, selector) { 691 | var result = { pass: jasmine.jQuery.events.wasStopped(selector, actual) } 692 | 693 | result.message = result.pass ? 694 | "Expected event " + actual + " not to have been stopped on " + selector : 695 | "Expected event " + actual + " to have been stopped on " + selector 696 | 697 | return result; 698 | } 699 | } 700 | }, 701 | 702 | toHaveBeenStopped: function () { 703 | return { 704 | compare: function (actual) { 705 | var eventName = actual.eventName 706 | , selector = actual.selector 707 | , result = { pass: jasmine.jQuery.events.wasStopped(selector, eventName) } 708 | 709 | result.message = result.pass ? 710 | "Expected event " + eventName + " not to have been stopped on " + selector : 711 | "Expected event " + eventName + " to have been stopped on " + selector 712 | 713 | return result 714 | } 715 | } 716 | } 717 | }) 718 | 719 | jasmine.getEnv().addCustomEqualityTester(function(a, b) { 720 | if (a && b) { 721 | if (a instanceof $ || jasmine.isDomNode(a)) { 722 | var $a = $(a) 723 | 724 | if (b instanceof $) 725 | return $a.length == b.length && a.is(b) 726 | 727 | return $a.is(b); 728 | } 729 | 730 | if (b instanceof $ || jasmine.isDomNode(b)) { 731 | var $b = $(b) 732 | 733 | if (a instanceof jQuery) 734 | return a.length == $b.length && $b.is(a) 735 | 736 | return $(b).is(a); 737 | } 738 | } 739 | }) 740 | 741 | jasmine.getEnv().addCustomEqualityTester(function (a, b) { 742 | if (a instanceof jQuery && b instanceof jQuery && a.size() == b.size()) 743 | return a.is(b) 744 | }) 745 | }) 746 | 747 | afterEach(function () { 748 | jasmine.getFixtures().cleanUp() 749 | jasmine.getStyleFixtures().cleanUp() 750 | jasmine.jQuery.events.cleanUp() 751 | }) 752 | 753 | window.readFixtures = function () { 754 | return jasmine.getFixtures().proxyCallTo_('read', arguments) 755 | } 756 | 757 | window.preloadFixtures = function () { 758 | jasmine.getFixtures().proxyCallTo_('preload', arguments) 759 | } 760 | 761 | window.loadFixtures = function () { 762 | jasmine.getFixtures().proxyCallTo_('load', arguments) 763 | } 764 | 765 | window.appendLoadFixtures = function () { 766 | jasmine.getFixtures().proxyCallTo_('appendLoad', arguments) 767 | } 768 | 769 | window.setFixtures = function (html) { 770 | return jasmine.getFixtures().proxyCallTo_('set', arguments) 771 | } 772 | 773 | window.appendSetFixtures = function () { 774 | jasmine.getFixtures().proxyCallTo_('appendSet', arguments) 775 | } 776 | 777 | window.sandbox = function (attributes) { 778 | return jasmine.getFixtures().sandbox(attributes) 779 | } 780 | 781 | window.spyOnEvent = function (selector, eventName) { 782 | return jasmine.jQuery.events.spyOn(selector, eventName) 783 | } 784 | 785 | window.preloadStyleFixtures = function () { 786 | jasmine.getStyleFixtures().proxyCallTo_('preload', arguments) 787 | } 788 | 789 | window.loadStyleFixtures = function () { 790 | jasmine.getStyleFixtures().proxyCallTo_('load', arguments) 791 | } 792 | 793 | window.appendLoadStyleFixtures = function () { 794 | jasmine.getStyleFixtures().proxyCallTo_('appendLoad', arguments) 795 | } 796 | 797 | window.setStyleFixtures = function (html) { 798 | jasmine.getStyleFixtures().proxyCallTo_('set', arguments) 799 | } 800 | 801 | window.appendSetStyleFixtures = function (html) { 802 | jasmine.getStyleFixtures().proxyCallTo_('appendSet', arguments) 803 | } 804 | 805 | window.loadJSONFixtures = function () { 806 | return jasmine.getJSONFixtures().proxyCallTo_('load', arguments) 807 | } 808 | 809 | window.getJSONFixture = function (url) { 810 | return jasmine.getJSONFixtures().proxyCallTo_('read', arguments)[url] 811 | } 812 | }(window, window.jasmine, window.jQuery); 813 | -------------------------------------------------------------------------------- /spec/javascripts/wow-spec.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | describe('WOW', function() { 3 | var timeout, winHeight; 4 | window.console = { 5 | warn: function() {} 6 | }; 7 | timeout = 100; 8 | winHeight = 300; 9 | describe('smoke test', function() { 10 | it('exists', function() { 11 | return expect(WOW).toBeDefined(); 12 | }); 13 | return it("has an 'init' method", function() { 14 | return expect(new WOW().init).toBeDefined(); 15 | }); 16 | }); 17 | describe('simple test environment', function() { 18 | beforeEach(function() { 19 | return loadFixtures('simple.html'); 20 | }); 21 | it('emulates window height', function() { 22 | return expect(document.documentElement.clientHeight).toBe(winHeight); 23 | }); 24 | return it('has boxes set up for testing', function() { 25 | var boxCount, boxHeight, offset, style; 26 | boxHeight = 200; 27 | boxCount = $('#simple').children().length; 28 | expect($('#simple').height()).toBe(boxHeight * boxCount); 29 | expect($('#simple-1').height()).toBe(boxHeight); 30 | expect($('#simple-2').height()).toBe(boxHeight); 31 | expect($('#simple-3').height()).toBe(boxHeight); 32 | expect($('#simple-4').height()).toBe(boxHeight); 33 | expect($('#simple-5').height()).toBe(boxHeight); 34 | offset = $('#simple').offset().top; 35 | expect($('#simple-1').offset().top).toBe(offset + boxHeight * 0); 36 | expect($('#simple-2').offset().top).toBe(offset + boxHeight * 1); 37 | expect($('#simple-3').offset().top).toBe(offset + boxHeight * 2); 38 | expect($('#simple-4').offset().top).toBe(offset + boxHeight * 3); 39 | expect($('#simple-5').offset().top).toBe(offset + boxHeight * 4); 40 | style = $('#simple-5')[0].style; 41 | expect(style.background).toBe('yellow'); 42 | return expect(style.color).toBe('red'); 43 | }); 44 | }); 45 | describe('library behaviour', function() { 46 | var wow; 47 | wow = null; 48 | beforeEach(function(done) { 49 | loadFixtures('simple.html'); 50 | (wow = new WOW).init(); 51 | return setTimeout(function() { 52 | return done(); 53 | }, timeout); 54 | }); 55 | it('animates elements that are fully visible on the page', function() { 56 | expect($('#simple-1')).toHaveClass('animated'); 57 | return expect($('#simple-1').css('visibility')).toBe('visible'); 58 | }); 59 | it("does not touch elements that don't have the marker class", function() { 60 | expect($('#simple-2')).not.toHaveClass('animated'); 61 | return expect($('#simple-2').css('visibility')).toBe('visible'); 62 | }); 63 | it('does not animate elements not yet visible on the page', function() { 64 | expect($('#simple-3')).not.toHaveClass('animated'); 65 | expect($('#simple-3').css('visibility')).not.toBe('visible'); 66 | expect($('#simple-4')).not.toHaveClass('animated'); 67 | return expect($('#simple-4').css('visibility')).not.toBe('visible'); 68 | }); 69 | it('animates elements after scrolling down and they become visible', function(done) { 70 | window.scrollTo(0, $('#simple-3').offset().top - winHeight + 150); 71 | return setTimeout(function() { 72 | expect($('#simple-3')).toHaveClass('animated'); 73 | expect($('#simple-3').css('visibility')).toBe('visible'); 74 | expect($('#simple-4')).not.toHaveClass('animated'); 75 | expect($('#simple-4').css('visibility')).not.toBe('visible'); 76 | window.scrollTo(0, $('#simple-4').offset().top - winHeight + 150); 77 | return setTimeout(function() { 78 | expect($('#simple-4')).toHaveClass('animated'); 79 | expect($('#simple-4').css('visibility')).toBe('visible'); 80 | return done(); 81 | }, timeout); 82 | }, timeout); 83 | }); 84 | it('does not tamper with the style attribute', function(done) { 85 | window.scrollTo(0, $('#simple-5').offset().top - winHeight + 150); 86 | return setTimeout(function() { 87 | expect($('#simple-5')).toHaveClass('animated'); 88 | expect($('#simple-5').css('visibility')).toBe('visible'); 89 | expect($('#simple-5')[0].style.background).toBe('yellow'); 90 | expect($('#simple-5')[0].style.color).toBe('red'); 91 | return done(); 92 | }, timeout); 93 | }); 94 | it('works with asynchronously loaded content', function(done) { 95 | $('#simple').append($('
', { 96 | id: 'simple-6', 97 | "class": 'wow' 98 | })); 99 | wow.sync(); 100 | window.scrollTo(0, $('#simple-6').offset().top - winHeight + 150); 101 | return setTimeout(function() { 102 | expect($('#simple-6')).toHaveClass('animated'); 103 | expect($('#simple-6').css('visibility')).toBe('visible'); 104 | return done(); 105 | }, timeout); 106 | }); 107 | return it('works with asynchronously loaded nested content', function(done) { 108 | $('#simple').append($('
')).children().first().append($('
', { 109 | id: 'simple-7', 110 | "class": 'wow' 111 | })); 112 | wow.sync(); 113 | window.scrollTo(0, $('#simple-7').offset().top - winHeight + 150); 114 | return setTimeout(function() { 115 | expect($('#simple-7')).toHaveClass('animated'); 116 | expect($('#simple-7').css('visibility')).toBe('visible'); 117 | return done(); 118 | }, timeout); 119 | }); 120 | }); 121 | describe('custom test environment', function() { 122 | beforeEach(function() { 123 | return loadFixtures('custom.html'); 124 | }); 125 | it('emulates window height', function() { 126 | return expect(document.documentElement.clientHeight).toBe(winHeight); 127 | }); 128 | return it('has boxes set up for testing', function() { 129 | var offset; 130 | expect($('#custom').height()).toBe(800); 131 | expect($('#custom-1').height()).toBe(200); 132 | expect($('#custom-2').height()).toBe(200); 133 | expect($('#custom-3').height()).toBe(200); 134 | expect($('#custom-4').height()).toBe(200); 135 | offset = $('#custom').offset().top; 136 | expect($('#custom-1').offset().top).toBe(offset + 200 * 0); 137 | expect($('#custom-2').offset().top).toBe(offset + 200 * 1); 138 | expect($('#custom-3').offset().top).toBe(offset + 200 * 2); 139 | return expect($('#custom-4').offset().top).toBe(offset + 200 * 3); 140 | }); 141 | }); 142 | return describe('library behaviour with custom settings', function() { 143 | var called; 144 | called = false; 145 | beforeEach(function(done) { 146 | called = false; 147 | loadFixtures('custom.html'); 148 | new WOW({ 149 | boxClass: 'block', 150 | animateClass: 'fancy', 151 | offset: 10, 152 | callback: function() { 153 | return called = true; 154 | } 155 | }).init(); 156 | $('.block').on('block', function() { 157 | return $(this).addClass('triggered'); 158 | }); 159 | return setTimeout(function() { 160 | return done(); 161 | }, timeout); 162 | }); 163 | it("creates two instances of the WOW.js with different configs", function() { 164 | var wow1, wow2; 165 | wow1 = new WOW({ 166 | boxClass: 'block1', 167 | animateClass: 'fancy1', 168 | offset: 10 169 | }); 170 | wow2 = new WOW({ 171 | boxClass: 'block2', 172 | animateClass: 'fancy2', 173 | offset: 20 174 | }); 175 | expect(wow1.config.boxClass).toBe("block1"); 176 | expect(wow1.config.animateClass).toBe("fancy1"); 177 | return expect(wow1.config.offset).toBe(10); 178 | }); 179 | it("does not touch elements that don't have the marker class", function(done) { 180 | window.scrollTo(0, $('#custom-1').offset().top - winHeight + 15); 181 | return setTimeout(function() { 182 | expect($('#custom-1')).not.toHaveClass('fancy'); 183 | return done(); 184 | }, timeout); 185 | }); 186 | it("animates elements that are partially visible on the page based on the 'offset' config", function(done) { 187 | return setTimeout(function() { 188 | window.scrollTo(0, $('#custom-2').offset().top - winHeight + 5); 189 | expect($('#custom-2')).not.toHaveClass('fancy'); 190 | window.scrollTo(0, $('#custom-2').offset().top - winHeight + 15); 191 | return setTimeout(function() { 192 | expect($('#custom-2')).toHaveClass('fancy'); 193 | expect($('#custom-2').css('visibility')).toBe('visible'); 194 | return done(); 195 | }, timeout); 196 | }, timeout); 197 | }); 198 | it('does not animate elements not yet visible on the page', function() { 199 | expect($('#custom-3')).not.toHaveClass('fancy'); 200 | return expect($('#custom-4')).not.toHaveClass('fancy'); 201 | }); 202 | it('animates elements after scrolling down and they become visible', function(done) { 203 | window.scrollTo(0, $('#custom-3').offset().top - winHeight + 150); 204 | return setTimeout(function() { 205 | expect($('#custom-3')).toHaveClass('fancy'); 206 | expect($('#custom-3').css('visibility')).toBe('visible'); 207 | expect($('#custom-3')[0].style.webkitAnimationIterationCount).toBe('2'); 208 | expect($('#custom-4')).not.toHaveClass('fancy'); 209 | window.scrollTo(0, $('#custom-4').offset().top - winHeight + 150); 210 | return setTimeout(function() { 211 | expect($('#custom-4')).toHaveClass('fancy'); 212 | expect($('#custom-4').css('visibility')).toBe('visible'); 213 | expect($('#custom-4')[0].style.webkitAnimationIterationCount).toBe('infinite'); 214 | expect($('#custom-4')[0].style.webkitAnimationDuration).toBe('2s'); 215 | expect($('#custom-4')[0].style.webkitAnimationDelay).toBe('1s'); 216 | return done(); 217 | }, timeout); 218 | }, timeout); 219 | }); 220 | it("fires the callback", function(done) { 221 | called = false; 222 | window.scrollTo(0, $('#custom-3').offset().top - winHeight + 150); 223 | return setTimeout(function() { 224 | expect(called).toBe(true); 225 | return done(); 226 | }, timeout); 227 | }); 228 | return it('fires the callback on the visible element', function(done) { 229 | window.scrollTo(0, $('#custom-3').offset().top - winHeight + 150); 230 | return setTimeout(function() { 231 | expect($('#custom-3')).toHaveClass('triggered'); 232 | expect($('#custom-4')).not.toHaveClass('triggered'); 233 | window.scrollTo(0, $('#custom-4').offset().top - winHeight + 150); 234 | return setTimeout(function() { 235 | expect($('#custom-3')).toHaveClass('triggered'); 236 | expect($('#custom-4')).toHaveClass('triggered'); 237 | return done(); 238 | }, timeout); 239 | }, timeout); 240 | }); 241 | }); 242 | }); 243 | 244 | }).call(this); 245 | -------------------------------------------------------------------------------- /src/wow.coffee: -------------------------------------------------------------------------------- 1 | # 2 | # Name : wow 3 | # Author : Matt Delac, https://www.delac.io/, @mattdelac_ 4 | # Version : 1.1.2 5 | # Repo : https://github.com/matthieua/WOW 6 | # Website : https://www.delac.io/WOW 7 | # 8 | 9 | 10 | class Util 11 | extend: (custom, defaults) -> 12 | custom[key] ?= value for key, value of defaults 13 | custom 14 | 15 | isMobile: (agent) -> 16 | /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(agent) 17 | 18 | createEvent: (event, bubble = false, cancel = false, detail = null) -> 19 | if document.createEvent? # W3C DOM 20 | customEvent = document.createEvent('CustomEvent') 21 | customEvent.initCustomEvent(event, bubble, cancel, detail) 22 | else if document.createEventObject? # IE DOM < 9 23 | customEvent = document.createEventObject() 24 | customEvent.eventType = event 25 | else 26 | customEvent.eventName = event 27 | 28 | customEvent 29 | 30 | emitEvent: (elem, event) -> 31 | if elem.dispatchEvent? # W3C DOM 32 | elem.dispatchEvent(event) 33 | else if event of elem? 34 | elem[event]() 35 | else if "on#{event}" of elem? 36 | elem["on#{event}"]() 37 | 38 | addEvent: (elem, event, fn) -> 39 | if elem.addEventListener? # W3C DOM 40 | elem.addEventListener event, fn, false 41 | else if elem.attachEvent? # IE DOM 42 | elem.attachEvent "on#{event}", fn 43 | else # fallback 44 | elem[event] = fn 45 | 46 | removeEvent: (elem, event, fn) -> 47 | if elem.removeEventListener? # W3C DOM 48 | elem.removeEventListener event, fn, false 49 | else if elem.detachEvent? # IE DOM 50 | elem.detachEvent "on#{event}", fn 51 | else # fallback 52 | delete elem[event] 53 | 54 | innerHeight: -> 55 | if 'innerHeight' of window 56 | window.innerHeight 57 | else document.documentElement.clientHeight 58 | 59 | # Minimalistic WeakMap shim, just in case. 60 | WeakMap = @WeakMap or @MozWeakMap or \ 61 | class WeakMap 62 | constructor: -> 63 | @keys = [] 64 | @values = [] 65 | 66 | get: (key) -> 67 | for item, i in @keys 68 | if item is key 69 | return @values[i] 70 | 71 | set: (key, value) -> 72 | for item, i in @keys 73 | if item is key 74 | @values[i] = value 75 | return 76 | @keys.push(key) 77 | @values.push(value) 78 | 79 | # Dummy MutationObserver, to avoid raising exceptions. 80 | MutationObserver = @MutationObserver or @WebkitMutationObserver or @MozMutationObserver or \ 81 | class MutationObserver 82 | constructor: -> 83 | console?.warn 'MutationObserver is not supported by your browser.' 84 | console?.warn 'WOW.js cannot detect dom mutations, please call .sync() after loading new content.' 85 | 86 | @notSupported: true 87 | 88 | observe: -> 89 | 90 | # getComputedStyle shim, from http://stackoverflow.com/a/21797294 91 | getComputedStyle = @getComputedStyle or \ 92 | (el, pseudo) -> 93 | @getPropertyValue = (prop) -> 94 | prop = 'styleFloat' if prop is 'float' 95 | prop.replace(getComputedStyleRX, (_, _char)-> 96 | _char.toUpperCase() 97 | ) if getComputedStyleRX.test prop 98 | el.currentStyle?[prop] or null 99 | @ 100 | getComputedStyleRX = /(\-([a-z]){1})/g 101 | 102 | class @WOW 103 | defaults: 104 | boxClass: 'wow' 105 | animateClass: 'animated' 106 | offset: 0 107 | mobile: true 108 | live: true 109 | callback: null 110 | scrollContainer: null 111 | 112 | constructor: (options = {}) -> 113 | @scrolled = true 114 | @config = @util().extend(options, @defaults) 115 | if options.scrollContainer? 116 | @config.scrollContainer = document.querySelector(options.scrollContainer) 117 | # Map of elements to animation names: 118 | @animationNameCache = new WeakMap() 119 | @wowEvent = @util().createEvent(@config.boxClass) 120 | 121 | init: -> 122 | @element = window.document.documentElement 123 | if document.readyState in ["interactive", "complete"] 124 | @start() 125 | else 126 | @util().addEvent document, 'DOMContentLoaded', @start 127 | @finished = [] 128 | 129 | start: => 130 | @stopped = false 131 | @boxes = (box for box in @element.querySelectorAll(".#{@config.boxClass}")) 132 | @all = (box for box in @boxes) 133 | if @boxes.length 134 | if @disabled() 135 | @resetStyle() 136 | else 137 | @applyStyle(box, true) for box in @boxes 138 | if !@disabled() 139 | @util().addEvent @config.scrollContainer || window, 'scroll', @scrollHandler 140 | @util().addEvent window, 'resize', @scrollHandler 141 | @interval = setInterval @scrollCallback, 50 142 | if @config.live 143 | new MutationObserver (records) => 144 | for record in records 145 | @doSync(node) for node in record.addedNodes or [] 146 | .observe document.body, 147 | childList: true 148 | subtree: true 149 | 150 | # unbind the scroll event 151 | stop: -> 152 | @stopped = true 153 | @util().removeEvent @config.scrollContainer || window, 'scroll', @scrollHandler 154 | @util().removeEvent window, 'resize', @scrollHandler 155 | clearInterval @interval if @interval? 156 | 157 | sync: (element) -> 158 | @doSync(@element) if MutationObserver.notSupported 159 | 160 | doSync: (element) -> 161 | element ?= @element 162 | return unless element.nodeType is 1 163 | element = element.parentNode or element 164 | for box in element.querySelectorAll(".#{@config.boxClass}") 165 | unless box in @all 166 | @boxes.push box 167 | @all.push box 168 | if @stopped or @disabled() 169 | @resetStyle() 170 | else 171 | @applyStyle(box, true) 172 | @scrolled = true 173 | 174 | # show box element 175 | show: (box) -> 176 | @applyStyle(box) 177 | box.className = "#{box.className} #{@config.animateClass}" 178 | @config.callback(box) if @config.callback? 179 | @util().emitEvent(box, @wowEvent) 180 | 181 | @util().addEvent(box, 'animationend', @resetAnimation) 182 | @util().addEvent(box, 'oanimationend', @resetAnimation) 183 | @util().addEvent(box, 'webkitAnimationEnd', @resetAnimation) 184 | @util().addEvent(box, 'MSAnimationEnd', @resetAnimation) 185 | 186 | box 187 | 188 | applyStyle: (box, hidden) -> 189 | duration = box.getAttribute('data-wow-duration') 190 | delay = box.getAttribute('data-wow-delay') 191 | iteration = box.getAttribute('data-wow-iteration') 192 | 193 | @animate => @customStyle(box, hidden, duration, delay, iteration) 194 | 195 | animate: (-> 196 | if 'requestAnimationFrame' of window 197 | (callback) -> 198 | window.requestAnimationFrame callback 199 | else 200 | (callback) -> 201 | callback() 202 | )() 203 | 204 | resetStyle: -> 205 | box.style.visibility = 'visible' for box in @boxes 206 | 207 | resetAnimation: (event) => 208 | if event.type.toLowerCase().indexOf('animationend') >= 0 209 | target = event.target || event.srcElement 210 | target.className = target.className.replace(@config.animateClass, '').trim() 211 | 212 | customStyle: (box, hidden, duration, delay, iteration) -> 213 | @cacheAnimationName(box) if hidden 214 | box.style.visibility = if hidden then 'hidden' else 'visible' 215 | 216 | @vendorSet box.style, animationDuration: duration if duration 217 | @vendorSet box.style, animationDelay: delay if delay 218 | @vendorSet box.style, animationIterationCount: iteration if iteration 219 | @vendorSet box.style, animationName: if hidden then 'none' else @cachedAnimationName(box) 220 | 221 | box 222 | 223 | vendors: ["moz", "webkit"] 224 | vendorSet: (elem, properties) -> 225 | for name, value of properties 226 | elem["#{name}"] = value 227 | elem["#{vendor}#{name.charAt(0).toUpperCase()}#{name.substr 1}"] = value for vendor in @vendors 228 | vendorCSS: (elem, property) -> 229 | style = getComputedStyle(elem) 230 | result = style.getPropertyCSSValue(property) 231 | result = result or style.getPropertyCSSValue("-#{vendor}-#{property}") for vendor in @vendors 232 | result 233 | 234 | animationName: (box) -> 235 | try 236 | animationName = @vendorCSS(box, 'animation-name').cssText 237 | catch # Opera, fall back to plain property value 238 | animationName = getComputedStyle(box).getPropertyValue('animation-name') 239 | if animationName is 'none' 240 | '' # SVG/Firefox, unable to get animation name? 241 | else 242 | animationName 243 | 244 | cacheAnimationName: (box) -> 245 | # https://bugzilla.mozilla.org/show_bug.cgi?id=921834 246 | # box.dataset is not supported for SVG elements in Firefox 247 | @animationNameCache.set(box, @animationName(box)) 248 | cachedAnimationName: (box) -> 249 | @animationNameCache.get(box) 250 | 251 | # fast window.scroll callback 252 | scrollHandler: => 253 | @scrolled = true 254 | 255 | scrollCallback: => 256 | if @scrolled 257 | @scrolled = false 258 | @boxes = for box in @boxes when box 259 | if @isVisible(box) 260 | @show(box) 261 | continue 262 | box 263 | @stop() unless @boxes.length or @config.live 264 | 265 | 266 | # Calculate element offset top 267 | offsetTop: (element) -> 268 | # SVG elements don't have an offsetTop in Firefox. 269 | # This will use their nearest parent that has an offsetTop. 270 | # Also, using ('offsetTop' of element) causes an exception in Firefox. 271 | element = element.parentNode while element.offsetTop is undefined 272 | top = element.offsetTop 273 | top += element.offsetTop while element = element.offsetParent 274 | top 275 | 276 | # check if box is visible 277 | isVisible: (box) -> 278 | offset = box.getAttribute('data-wow-offset') or @config.offset 279 | viewTop = (@config.scrollContainer && @config.scrollContainer.scrollTop) || window.pageYOffset 280 | viewBottom = viewTop + Math.min(@element.clientHeight, @util().innerHeight()) - offset 281 | top = @offsetTop(box) 282 | bottom = top + box.clientHeight 283 | 284 | top <= viewBottom and bottom >= viewTop 285 | 286 | util: -> 287 | @_util ?= new Util() 288 | 289 | disabled: -> 290 | not @config.mobile and @util().isMobile(navigator.userAgent) 291 | --------------------------------------------------------------------------------