├── .babelrc ├── .eslintignore ├── .eslintrc ├── .gitignore ├── LICENSE ├── README.md ├── _config.yml ├── dist ├── jquery.keyframes.js └── jquery.keyframes.min.js ├── example └── index.html ├── package-lock.json ├── package.json └── src └── jquery.keyframes.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["@babel/preset-env", { 4 | "targets": { 5 | "browsers": ["last 2 versions"] 6 | } 7 | }] 8 | ] 9 | } -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "airbnb", 3 | "env": { 4 | "browser": true, 5 | "node": false 6 | }, 7 | "rules": { 8 | "indent": ["warn", 4], 9 | "no-restricted-syntax": 0, 10 | "guard-for-in": 0, 11 | "func-names": 0 12 | } 13 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.com 2 | *.class 3 | *.dll 4 | *.exe 5 | *.o 6 | *.so 7 | *.7z 8 | *.dmg 9 | *.gz 10 | *.iso 11 | *.jar 12 | *.rar 13 | *.tar 14 | *.zip 15 | *.log 16 | *.sql 17 | *.sqlite 18 | .DS_Store 19 | .DS_Store? 20 | ._* 21 | .Spotlight-V100 22 | .Trashes 23 | ehthumbs.db 24 | Thumbs.db 25 | node_modules 26 | prepros.cfg 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 jQuery.Keyframes (https://github.com/Keyframes/jQuery.Keyframes) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | jQuery.Keyframes 2 | =========== 3 | 4 | [![npm version](https://img.shields.io/npm/v/jquerykeyframes.svg?style=flat-square)](https://www.npmjs.org/package/jquerykeyframes) 5 | 6 | This library is a wrapper around [Keyframes.js](https://github.com/Keyframes/Keyframes), a vanilla js library that allows dynamic generation of CSS keyframes with callback events and other niceness. 7 | 8 | Overview 9 | -------- 10 | CSS3 introduced fancy features like transformations, translations, rotations and scaling. 11 | jQuery has a very nice built in *$(selector).animate()* function which allows for easy setup of these animations. 12 | However, jQuery's animate() does not support multiple keyframes. jQuery.Keyframes helps you accomplish just that. 13 | 14 | Requirements 15 | ------------ 16 | 17 | ```html 18 | 19 | ``` 20 | 21 | Installation 22 | ------------ 23 | Include script in your document using the following line: 24 | 25 | ```html 26 | 27 | ``` 28 | 29 | Be sure to define and play animations only after the page has loaded using `window.onload`. 30 | 31 | Usage 32 | ------------- 33 | 34 | **Detecting CSS animation support** 35 | 36 | ```javascript 37 | var supportedFlag = $.keyframe.isSupported(); 38 | ``` 39 | 40 | **Adding a new animation sequence (keyframe)** 41 | 42 | ```javascript 43 | $.keyframe.define([{ 44 | name: 'trapdoor-sequence', 45 | '0%': {'height': '70px'}, 46 | '30%': {'height': '10px'}, 47 | '60%': {'height': '30px'}, 48 | '100%': {'height': '10px'} 49 | }]); 50 | ``` 51 | 52 | **Adding a single frame style** 53 | 54 | ```javascript 55 | $.keyframe.define({ 56 | name: 'ball-roll', 57 | from: { 58 | 'transform': 'rotate(0deg)' 59 | }, 60 | to: { 61 | 'transform': 'rotate(360deg)' 62 | } 63 | }); 64 | ``` 65 | 66 | **Adding multiple frame styles** 67 | 68 | ```javascript 69 | $.keyframe.define([{ 70 | name: 'roll-clockwise', 71 | '0%': { 72 | 'margin-left' : '0px', 73 | 'background-color' : 'red', 74 | 'transform' : 'rotate(0deg)' 75 | }, 76 | '100%': { 77 | 'margin-left' : '600px', 78 | 'transform' : 'rotate(360deg)' 79 | } 80 | },{ 81 | name: 'roll-anti-clockwise', 82 | '0%': { 83 | 'margin-left' : '0px', 84 | 'background-color' : 'red', 85 | 'transform' : 'rotate(0deg)' 86 | }, 87 | '100%': { 88 | 'margin-left' : '600px', 89 | 'transform' : 'rotate(-360deg)' 90 | } 91 | } 92 | ]); 93 | ``` 94 | 95 | **Adding styles and properties in array fashion** 96 | 97 | *Gives resemblance to CSS styling definitions* 98 | 99 | ```javascript 100 | var shake_start = {'transform': 'translate(0px)'}; 101 | var shake_odd1 = {'transform': 'translate(-10px, -10px)'}; 102 | var shake_even1 = {'transform': 'translate(10px, 10px)'}; 103 | var shake_odd2 = {'transform': 'translate(10px, -10px)'}; 104 | var shake_even2 = {'transform': 'translate(-10px, 10px)'}; 105 | 106 | $.keyframe.define([{ 107 | name: 'crazy', 108 | '0%': shake_start, 109 | '10%': shake_odd2, 110 | '20%': shake_even1, 111 | '30%': shake_odd2, 112 | '40%': shake_even2, 113 | '50%': shake_odd2, 114 | '60%': shake_even1, 115 | '75.3%': shake_odd1, 116 | '80.45%': shake_even2, 117 | '91.6%': shake_odd1 118 | } 119 | ]); 120 | ``` 121 | 122 | *Please note, you can add as many properties to the array as you want to* 123 | 124 | **Responsive animations** 125 | ```javascript 126 | $.keyframe.define([{ 127 | name: 'roll-clockwise', 128 | media: 'screen and (max-width: 700px)', 129 | from: { 130 | 'margin-left' : '0px' 131 | }, 132 | to: { 133 | 'margin-left' : '600px' 134 | } 135 | } 136 | ]); 137 | ``` 138 | 139 | **Playing an animation** 140 | 141 | The css3 animation methods available are better documented here: http://www.w3schools.com/css/css3_animations.asp 142 | 143 | ```javascript 144 | $(selector).playKeyframe({ 145 | name: 'trapdoor-sequence', // name of the keyframe you want to bind to the selected element 146 | duration: '1s', // [optional, default: 0, in ms] how long you want it to last in milliseconds 147 | timingFunction: 'linear', // [optional, default: ease] specifies the speed curve of the animation 148 | delay: '0s', //[optional, default: 0s] how long you want to wait before the animation starts 149 | iterationCount: 'infinite', //[optional, default:1] how many times you want the animation to repeat 150 | direction: 'normal', //[optional, default: 'normal'] which direction you want the frames to flow 151 | fillMode: 'forwards', //[optional, default: 'forward'] how to apply the styles outside the animation time, default value is forwards 152 | complete: function(){} //[optional] Function fired after the animation is complete. If repeat is infinite, the function will be fired every time the animation is restarted. 153 | }); 154 | ``` 155 | 156 | **Playing an animation (shorthand)** 157 | 158 | ```javascript 159 | $(selector).playKeyframe( 160 | 'trapdoor-sequence 1s linear 0s infinite normal forwards', 161 | complete 162 | ); 163 | ``` 164 | 165 | **Playing multiple animations** 166 | 167 | ```javascript 168 | $(selector).playKeyframe([ 169 | 'trapdoor-sequence 1s linear 0s infinite', 170 | { 171 | name: 'ball-roll', 172 | duration: "3s", 173 | timingFunction: 'ease', 174 | iterationCount: 1 175 | } 176 | ], complete); 177 | ``` 178 | 179 | **Reset the animation** 180 | 181 | ```javascript 182 | $(selector).resetKeyframe(callback); 183 | ``` 184 | 185 | **Freeze keyframe animation and kill callbacks** 186 | 187 | ```javascript 188 | $(selector).pauseKeyframe(); 189 | ``` 190 | 191 | **Resume keyframe animation** 192 | 193 | ```javascript 194 | $(selector).resumeKeyframe(); 195 | ``` 196 | 197 | Who is using jQuery.Keyframes? 198 | ------------------------------ 199 | 200 | * Hipster Gallery: http://labs.bebensiganteng.com/html5/hipstergallery/#thumbnails/0 201 | * Ronneby Wordpress Theme: https://themeforest.net/item/ronneby-highperformance-wordpress-theme/11776839?s_rank=1 202 | * Brooklyn Wordpress Theme: https://themeforest.net/item/brooklyn-responsive-multipurpose-wordpress-theme/6221179 203 | * Contrive Wordpress Theme: https://themeforest.net/item/contrive-building-construction-html5-template/14535825 204 | * DFD-Native Wordpress Theme: https://themeforest.net/item/native-powerful-startup-development-tool/19200310 205 | * Sunday Wordpress Theme: http://themes.dfd.name/sunday/promo/ 206 | 207 | Plugins! 208 | -------- 209 | See other plugins that allow for spritesheets & more complex movement paths: https://github.com/Keyframes 210 | 211 | - [Keyframes.Pathfinder](https://github.com/Keyframes/Keyframes.Pathfinder): A plugin for jQuery.Keyframes that generates complex movement paths 212 | - [Keyframes.Spritesheet](https://github.com/Keyframes/Keyframes.Spritesheet): Keyframes.Spritesheet easily generates css3 keyframes for elements using animated spritesheets. 213 | 214 | Changelog 215 | --------- 216 | **1.0.0** 217 | * Moved to use [keyframes.js](https://github.com/Keyframes/Keyframes) as a base 218 | **0.1.0** 219 | * Remove all vendor prefix functionality (if you need this stick with 0.0.9) 220 | * Remove debug output 221 | * Source code now in ES6 222 | * Remove advanced example 223 | * Add jQuery 3.x to example 224 | * Add linting 225 | **0.0.9** 226 | * Add debug output 227 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /dist/jquery.keyframes.js: -------------------------------------------------------------------------------- 1 | (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { 188 | _ = 0; 189 | continue; 190 | } 191 | 192 | if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) { 193 | _.label = op[1]; 194 | break; 195 | } 196 | 197 | if (op[0] === 6 && _.label < t[1]) { 198 | _.label = t[1]; 199 | t = op; 200 | break; 201 | } 202 | 203 | if (t && _.label < t[2]) { 204 | _.label = t[2]; 205 | 206 | _.ops.push(op); 207 | 208 | break; 209 | } 210 | 211 | if (t[2]) _.ops.pop(); 212 | 213 | _.trys.pop(); 214 | 215 | continue; 216 | } 217 | 218 | op = body.call(thisArg, _); 219 | } catch (e) { 220 | op = [6, e]; 221 | y = 0; 222 | } finally { 223 | f = t = 0; 224 | } 225 | } 226 | 227 | if (op[0] & 5) throw op[1]; 228 | return { 229 | value: op[0] ? op[1] : void 0, 230 | done: true 231 | }; 232 | } 233 | }; 234 | 235 | var __importDefault = void 0 && (void 0).__importDefault || function (mod) { 236 | return mod && mod.__esModule ? mod : { 237 | "default": mod 238 | }; 239 | }; 240 | 241 | Object.defineProperty(exports, "__esModule", { 242 | value: true 243 | }); 244 | 245 | var add_px_to_style_1 = __importDefault(require("add-px-to-style")); 246 | 247 | var hyphenate_style_name_1 = __importDefault(require("hyphenate-style-name")); 248 | 249 | var wait = function wait() { 250 | return new Promise(function (accept) { 251 | requestAnimationFrame(function () { 252 | accept(); 253 | }); 254 | }); 255 | }; 256 | 257 | var isBrowser = typeof window !== 'undefined'; 258 | var keyframesSheet; 259 | 260 | if (isBrowser) { 261 | var styleElem = document.createElement('style'); 262 | styleElem.setAttribute('id', 'keyframesjs-stylesheet'); 263 | document.head.appendChild(styleElem); 264 | keyframesSheet = styleElem.sheet; 265 | } 266 | 267 | var voidFunction = function voidFunction() {}; 268 | 269 | var objToCss = function objToCss(obj) { 270 | if (!Object.keys(obj).length) { 271 | return ''; 272 | } 273 | 274 | var result = ''; 275 | 276 | for (var key in obj) { 277 | result += hyphenate_style_name_1["default"](key) + ":" + add_px_to_style_1["default"](key, obj[key]) + ";"; 278 | } 279 | 280 | return result; 281 | }; 282 | 283 | var Keyframes = function () { 284 | function Keyframes(elem) { 285 | this.queueStore = []; 286 | this.callbacks = { 287 | onStart: voidFunction, 288 | onBeforeStart: voidFunction, 289 | onIteration: voidFunction, 290 | onEnd: voidFunction 291 | }; 292 | this.animationendListener = voidFunction; 293 | this.animationiterationListener = voidFunction; 294 | this.mountedElement = elem; 295 | } 296 | 297 | Keyframes.isSupported = function () { 298 | return document.body.style.animationName !== undefined; 299 | }; 300 | 301 | Keyframes.prototype.reset = function () { 302 | return __awaiter(this, void 0, void 0, function () { 303 | return __generator(this, function (_a) { 304 | switch (_a.label) { 305 | case 0: 306 | this.removeEvents(); 307 | this.mountedElement.style.animationPlayState = 'running'; 308 | this.mountedElement.style.animation = 'none'; 309 | return [4, wait()]; 310 | 311 | case 1: 312 | _a.sent(); 313 | 314 | return [2, this]; 315 | } 316 | }); 317 | }); 318 | }; 319 | 320 | Keyframes.prototype.pause = function () { 321 | this.mountedElement.style.animationPlayState = 'paused'; 322 | return this; 323 | }; 324 | 325 | Keyframes.prototype.resume = function () { 326 | this.mountedElement.style.animationPlayState = 'running'; 327 | return this; 328 | }; 329 | 330 | Keyframes.prototype.play = function (animationOptions, callbacks) { 331 | var _this = this; 332 | 333 | if (this.mountedElement.style.animationName === this.getAnimationName(animationOptions)) { 334 | requestAnimationFrame(function () { 335 | return __awaiter(_this, void 0, void 0, function () { 336 | return __generator(this, function (_a) { 337 | switch (_a.label) { 338 | case 0: 339 | return [4, this.reset()]; 340 | 341 | case 1: 342 | _a.sent(); 343 | 344 | this.play(animationOptions, callbacks); 345 | return [2]; 346 | } 347 | }); 348 | }); 349 | }); 350 | return this; 351 | } 352 | 353 | var _a = callbacks || {}, 354 | _b = _a.onBeforeStart, 355 | onBeforeStart = _b === void 0 ? null : _b, 356 | _c = _a.onStart, 357 | onStart = _c === void 0 ? null : _c, 358 | _d = _a.onIteration, 359 | onIteration = _d === void 0 ? null : _d, 360 | _e = _a.onEnd, 361 | onEnd = _e === void 0 ? null : _e; 362 | 363 | var animationcss = Keyframes.playCSS(animationOptions); 364 | 365 | var addEvent = function addEvent(type, eventCallback) { 366 | var listenerName = type + "Listener"; 367 | 368 | _this.mountedElement.removeEventListener(type, _this[listenerName]); 369 | 370 | _this[listenerName] = eventCallback; 371 | 372 | _this.mountedElement.addEventListener(type, _this[listenerName]); 373 | }; 374 | 375 | if (onBeforeStart) { 376 | onBeforeStart(); 377 | } 378 | 379 | this.mountedElement.style.animationPlayState = 'running'; 380 | this.mountedElement.style.animation = animationcss; 381 | 382 | if (onIteration) { 383 | addEvent('animationiteration', onIteration); 384 | } 385 | 386 | if (onEnd) { 387 | addEvent('animationend', onEnd); 388 | } 389 | 390 | if (onStart) { 391 | requestAnimationFrame(onStart); 392 | } 393 | 394 | return this; 395 | }; 396 | 397 | Keyframes.prototype.removeEvents = function () { 398 | this.mountedElement.removeEventListener('animationiteration', this.animationiterationListener); 399 | this.mountedElement.removeEventListener('animationend', this.animationendListener); 400 | return this; 401 | }; 402 | 403 | Keyframes.prototype.playNext = function () { 404 | var _this = this; 405 | 406 | var animationOption = this.queueStore.pop(); 407 | 408 | if (animationOption) { 409 | this.play(animationOption, { 410 | onEnd: function onEnd() { 411 | return _this.playNext(); 412 | }, 413 | onIteration: this.callbacks.onIteration 414 | }); 415 | } else if (this.callbacks.onEnd) { 416 | this.callbacks.onEnd(); 417 | } 418 | }; 419 | 420 | Keyframes.prototype.updateCallbacks = function (callbacks) { 421 | if (callbacks) { 422 | this.callbacks = __assign(__assign({}, this.callbacks), callbacks); 423 | } 424 | }; 425 | 426 | Keyframes.prototype.queue = function (animationOptions, callbacks) { 427 | var currentQueueLength = this.queueStore.length; 428 | this.updateCallbacks(callbacks); 429 | 430 | if (animationOptions.constructor === Array) { 431 | this.queueStore = animationOptions.reverse().concat(this.queueStore); 432 | } else { 433 | this.queueStore.unshift(animationOptions); 434 | } 435 | 436 | if (!currentQueueLength) { 437 | if (this.callbacks.onBeforeStart) { 438 | this.callbacks.onBeforeStart(); 439 | } 440 | 441 | this.playNext(); 442 | 443 | if (this.callbacks.onStart) { 444 | requestAnimationFrame(this.callbacks.onStart); 445 | } 446 | } 447 | 448 | return this; 449 | }; 450 | 451 | Keyframes.prototype.resetQueue = function () { 452 | return __awaiter(this, void 0, void 0, function () { 453 | return __generator(this, function (_a) { 454 | switch (_a.label) { 455 | case 0: 456 | return [4, wait()]; 457 | 458 | case 1: 459 | _a.sent(); 460 | 461 | this.removeEvents(); 462 | this.queueStore = []; 463 | return [4, this.reset()]; 464 | 465 | case 2: 466 | _a.sent(); 467 | 468 | return [2, this]; 469 | } 470 | }); 471 | }); 472 | }; 473 | 474 | Keyframes.prototype.chain = function (animationOptions, callbacks) { 475 | return __awaiter(this, void 0, void 0, function () { 476 | return __generator(this, function (_a) { 477 | switch (_a.label) { 478 | case 0: 479 | return [4, this.resetQueue()]; 480 | 481 | case 1: 482 | _a.sent(); 483 | 484 | this.queue(animationOptions, callbacks); 485 | return [2, this]; 486 | } 487 | }); 488 | }); 489 | }; 490 | 491 | Keyframes.prototype.getAnimationName = function (animationObject) { 492 | switch (animationObject.constructor) { 493 | case Array: 494 | { 495 | return animationObject.map(this.getAnimationName).join(', '); 496 | } 497 | 498 | case String: 499 | { 500 | return animationObject.split(' ')[0]; 501 | } 502 | 503 | default: 504 | { 505 | return animationObject.name; 506 | } 507 | } 508 | }; 509 | 510 | Keyframes.playCSS = function (animationOptions) { 511 | var animObjToStr = function animObjToStr(obj) { 512 | var newObj = __assign({ 513 | duration: '0s', 514 | timingFunction: 'ease', 515 | delay: '0s', 516 | iterationCount: 1, 517 | direction: 'normal', 518 | fillMode: 'forwards' 519 | }, obj); 520 | 521 | return [newObj.name, newObj.duration, newObj.timingFunction, newObj.delay, newObj.iterationCount, newObj.direction, newObj.fillMode].join(' '); 522 | }; 523 | 524 | if (animationOptions.constructor === Array) { 525 | var animationOptionArray = animationOptions; 526 | var animationOptionsStrings = []; 527 | 528 | for (var i = 0; i < animationOptionArray.length; i += 1) { 529 | animationOptionsStrings.push(animationOptionArray[i].constructor === String ? animationOptionArray[i] : animObjToStr(animationOptionArray[i])); 530 | } 531 | 532 | return animationOptionsStrings.join(', '); 533 | } 534 | 535 | if (animationOptions.constructor === String) { 536 | return animationOptions; 537 | } 538 | 539 | return animObjToStr(animationOptions); 540 | }; 541 | 542 | Keyframes.generateCSS = function (frameData) { 543 | var css = "@keyframes " + frameData.name + " {"; 544 | 545 | for (var key in frameData) { 546 | if (key !== 'name' && key !== 'media' && key !== 'complete') { 547 | var cssRuleObject = objToCss(frameData[key]); 548 | css += key + " {" + cssRuleObject + "}"; 549 | } 550 | } 551 | 552 | css += '}'; 553 | 554 | if (frameData.media) { 555 | css = "@media " + frameData.media + "{" + css + "}"; 556 | } 557 | 558 | return css; 559 | }; 560 | 561 | Keyframes.generate = function (frameData) { 562 | var css = this.generateCSS(frameData); 563 | var oldFrameIndex = Keyframes.rules.indexOf(frameData.name); 564 | 565 | if (oldFrameIndex > -1) { 566 | Keyframes.sheet.deleteRule(oldFrameIndex); 567 | Keyframes.rules.splice(oldFrameIndex, 1); 568 | } 569 | 570 | var ruleIndex = (Keyframes.sheet.cssRules || Keyframes.sheet.rules).length; 571 | Keyframes.sheet.insertRule(css, ruleIndex); 572 | Keyframes.rules[ruleIndex] = frameData.name; 573 | }; 574 | 575 | Keyframes.define = function (frameOptions) { 576 | if (frameOptions.length) { 577 | for (var i = 0; i < frameOptions.length; i += 1) { 578 | this.generate(frameOptions[i]); 579 | } 580 | } else { 581 | this.generate(frameOptions); 582 | } 583 | }; 584 | 585 | Keyframes.defineCSS = function (frameOptions) { 586 | if (frameOptions.length) { 587 | var css = ''; 588 | 589 | for (var i = 0; i < frameOptions.length; i += 1) { 590 | css += this.generateCSS(frameOptions[i]); 591 | } 592 | 593 | return css; 594 | } 595 | 596 | return this.generateCSS(frameOptions); 597 | }; 598 | 599 | Keyframes.plugin = function (pluginFunc) { 600 | if (pluginFunc.constructor === Array) { 601 | for (var i = 0; i < pluginFunc.length; i += 1) { 602 | pluginFunc[i](this); 603 | } 604 | } else { 605 | pluginFunc(this); 606 | } 607 | }; 608 | 609 | Keyframes.sheet = keyframesSheet; 610 | Keyframes.rules = []; 611 | return Keyframes; 612 | }(); 613 | 614 | if (isBrowser) { 615 | window.Keyframes = Keyframes; 616 | } 617 | 618 | exports["default"] = Keyframes; 619 | 620 | },{"add-px-to-style":3,"hyphenate-style-name":4}],3:[function(require,module,exports){ 621 | "use strict"; 622 | 623 | /* The following list is defined in React's core */ 624 | var IS_UNITLESS = { 625 | animationIterationCount: true, 626 | boxFlex: true, 627 | boxFlexGroup: true, 628 | boxOrdinalGroup: true, 629 | columnCount: true, 630 | flex: true, 631 | flexGrow: true, 632 | flexPositive: true, 633 | flexShrink: true, 634 | flexNegative: true, 635 | flexOrder: true, 636 | gridRow: true, 637 | gridColumn: true, 638 | fontWeight: true, 639 | lineClamp: true, 640 | lineHeight: true, 641 | opacity: true, 642 | order: true, 643 | orphans: true, 644 | tabSize: true, 645 | widows: true, 646 | zIndex: true, 647 | zoom: true, 648 | // SVG-related properties 649 | fillOpacity: true, 650 | stopOpacity: true, 651 | strokeDashoffset: true, 652 | strokeOpacity: true, 653 | strokeWidth: true 654 | }; 655 | 656 | module.exports = function (name, value) { 657 | if (typeof value === 'number' && !IS_UNITLESS[name]) { 658 | return value + 'px'; 659 | } else { 660 | return value; 661 | } 662 | }; 663 | 664 | },{}],4:[function(require,module,exports){ 665 | 'use strict'; 666 | /* eslint-disable no-var, prefer-template */ 667 | 668 | var uppercasePattern = /[A-Z]/g; 669 | var msPattern = /^ms-/; 670 | var cache = {}; 671 | 672 | function toHyphenLower(match) { 673 | return '-' + match.toLowerCase(); 674 | } 675 | 676 | function hyphenateStyleName(name) { 677 | if (cache.hasOwnProperty(name)) { 678 | return cache[name]; 679 | } 680 | 681 | var hName = name.replace(uppercasePattern, toHyphenLower); 682 | return cache[name] = msPattern.test(hName) ? '-' + hName : hName; 683 | } 684 | 685 | module.exports = hyphenateStyleName; 686 | 687 | },{}]},{},[1]); 688 | -------------------------------------------------------------------------------- /dist/jquery.keyframes.min.js: -------------------------------------------------------------------------------- 1 | !function o(a,u,s){function l(t,e){if(!u[t]){if(!a[t]){var n="function"==typeof require&&require;if(!e&&n)return n(t,!0);if(c)return c(t,!0);var r=new Error("Cannot find module '"+t+"'");throw r.code="MODULE_NOT_FOUND",r}var i=u[t]={exports:{}};a[t][0].call(i.exports,function(e){return l(a[t][1][e]||e)},i,i.exports,o,a,u,s)}return u[t].exports}for(var c="function"==typeof require&&require,e=0;ea[0]&&t[1] 2 | 3 | 4 | 5 | jQuery-Keyframes Example 6 | 7 | 8 | 9 | 134 | 135 | 159 | 160 | 161 | 162 |
163 |
: )
164 |
165 | 166 | 167 | 168 | 169 | 170 | 171 |
172 | 173 | 174 | 175 |
176 |
Callback count: 0 177 |
178 |
179 | 180 | 181 | 182 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquerykeyframes", 3 | "version": "1.0.8", 4 | "description": "jQuery-Keyframes allows dynamic generation of CSS3 keyframes with callback events and other niceness.", 5 | "main": "dist/jquery.keyframes.min.js", 6 | "scripts": { 7 | "prepare": "npm run build", 8 | "build": "npm run es6 && npm run browserify && npm run minify && npm run cleanup", 9 | "es6": "babel src/jquery.keyframes.js -o dist/jquery.keyframes.es6.js --no-comments", 10 | "browserify": "browserify dist/jquery.keyframes.es6.js -o dist/jquery.keyframes.js -t [ babelify --global --presets [ @babel/preset-env ] ]", 11 | "cleanup": "rm dist/jquery.keyframes.es6.js", 12 | "minify": "uglifyjs --compress --mangle -- dist/jquery.keyframes.js > dist/jquery.keyframes.min.js", 13 | "watch": "nodemon --watch example/example.html --watch src --exec 'npm run build'" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/Keyframes/jQuery.Keyframes.git" 18 | }, 19 | "keywords": [ 20 | "animation", 21 | "keyframes", 22 | "jquery", 23 | "css3" 24 | ], 25 | "author": "krazyjakee", 26 | "license": "MIT", 27 | "bugs": { 28 | "url": "https://github.com/Keyframes/jQuery.Keyframes/issues" 29 | }, 30 | "homepage": "https://github.com/Keyframes/jQuery.Keyframes", 31 | "dependencies": { 32 | "@keyframes/core": "^2.0.2", 33 | "jquery": "^3.4.1" 34 | }, 35 | "devDependencies": { 36 | "@babel/cli": "^7.7.0", 37 | "@babel/core": "^7.7.2", 38 | "@babel/preset-env": "^7.7.1", 39 | "babelify": "^10.0.0", 40 | "browserify": "^16.5.0", 41 | "eslint": "^6.6.0", 42 | "eslint-config-airbnb": "^18.0.1", 43 | "eslint-plugin-import": "^2.18.2", 44 | "eslint-plugin-jsx-a11y": "^6.2.3", 45 | "eslint-plugin-react": "^7.16.0", 46 | "nodemon": "^1.19.4", 47 | "uglify-js": "^3.6.9" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/jquery.keyframes.js: -------------------------------------------------------------------------------- 1 | /* global $ */ 2 | import Keyframes from '@keyframes/core'; 3 | 4 | (($) => { 5 | const doForEach = ($el, cb) => { 6 | $el.each((_, elem) => { 7 | if (elem.Keyframes) { 8 | cb(elem.Keyframes); 9 | } else { 10 | elem.Keyframes = new Keyframes(elem); 11 | cb(elem.Keyframes); 12 | } 13 | }); 14 | }; 15 | 16 | $.keyframe = { 17 | isSupported: Keyframes.isSupported, 18 | generate: Keyframes.generate, 19 | generateCSS: Keyframes.generateCSS, 20 | define: Keyframes.define, 21 | }; 22 | 23 | $.fn.resetKeyframe = function (cb) { 24 | const $this = this; 25 | doForEach($this, kf => kf.reset().then(cb)); 26 | }; 27 | 28 | $.fn.pauseKeyframe = function () { 29 | const $this = this; 30 | doForEach($this, kf => kf.pause()); 31 | }; 32 | 33 | $.fn.resumeKeyframe = function () { 34 | const $this = this; 35 | doForEach($this, kf => kf.resume()); 36 | }; 37 | 38 | $.fn.playKeyframe = function (frameOptions, callbacks) { 39 | const $this = this; 40 | let cb = callbacks; 41 | if (frameOptions.complete) { 42 | callbacks = frameOptions.complete; 43 | } 44 | if (typeof callbacks === 'function') { 45 | cb = { 46 | onIteration: callbacks, 47 | onEnd: callbacks, 48 | }; 49 | } 50 | doForEach($this, kf => kf.play(frameOptions, cb)); 51 | }; 52 | })(jQuery); 53 | --------------------------------------------------------------------------------