vendor: 21,376 bytes, lines 1-708
1/*! 2 * jQuery Transit - CSS3 transitions and transformations 3 * (c) 2011-2012 Rico Sta. Cruz <[email protected]> 4 * MIT Licensed. 5 * 6 * http://ricostacruz.com/jquery.transit 7 * http://github.com/rstacruz/jquery.transit 8 */ 9 10(function($) { 11 $.transit = { 12 version: "0.9.9", 13 14 // Map of $.css() keys to values for 'transitionProperty'. 15 // See https://developer.mozilla.org/en/CSS/CSS_transitions#Properties_that_can_be_animated 16 propertyMap: { 17 marginLeft : 'margin', 18 marginRight : 'margin', 19 marginBottom : 'margin', 20 marginTop : 'margin', 21 paddingLeft : 'padding', 22 paddingRight : 'padding', 23 paddingBottom : 'padding', 24 paddingTop : 'padding' 25 }, 26 27 // Will simply transition "instantly" if false 28 enabled: true, 29 30 // Set this to false if you don't want to use the transition end property. 31 useTransitionEnd: false 32 }; 33 34 var div = document.createElement('div'); 35 var support = {}; 36 37 // Helper function to get the proper vendor property name. 38 // (`transition` => `WebkitTransition`) 39 function getVendorPropertyName(prop) { 40 // Handle unprefixed versions (FF16+, for example) 41 if (prop in div.style) return prop; 42 43 var prefixes = ['Moz', 'Webkit', 'O', 'ms']; 44 var prop_ = prop.charAt(0).toUpperCase() + prop.substr(1); 45 46 if (prop in div.style) { return prop; } 47 48 for (var i=0; i<prefixes.length; ++i) { 49 var vendorProp = prefixes[i] + prop_; 50 if (vendorProp in div.style) { return vendorProp; } 51 } 52 } 53 54 // Helper function to check if transform3D is supported. 55 // Should return true for Webkits and Firefox 10+. 56 function checkTransform3dSupport() { 57 div.style[support.transform] = ''; 58 div.style[support.transform] = 'rotateY(90deg)'; 59 return div.style[support.transform] !== ''; 60 } 61 62 var isChrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1; 63 64 // Check for the browser's transitions support. 65 support.transition = getVendorPropertyName('transition'); 66 support.transitionDelay = getVendorPropertyName('transitionDelay'); 67 support.transform = getVendorPropertyName('transform'); 68 support.transformOrigin = getVendorPropertyName('transformOrigin'); 69 support.transform3d = checkTransform3dSupport(); 70 71 var eventNames = { 72 'transition': 'transitionEnd', 73 'MozTransition': 'transitionend', 74 'OTransition': 'oTransitionEnd', 75 'WebkitTransition': 'webkitTransitionEnd', 76 'msTransition': 'MSTransitionEnd' 77 }; 78 79 // Detect the 'transitionend' event needed. 80 var transitionEnd = support.transitionEnd = eventNames[support.transition] || null; 81 82 // Populate jQuery's `$.support` with the vendor prefixes we know. 83 // As per [jQuery's cssHooks documentation](http://api.jquery.com/jQuery.cssHooks/), 84 // we set $.support.transition to a string of the actual property name used. 85 for (var key in support) { 86 if (support.hasOwnProperty(key) && typeof $.support[key] === 'undefined') { 87 $.support[key] = support[key]; 88 } 89 } 90 91 // Avoid memory leak in IE. 92 div = null; 93 94 // ## $.cssEase 95 // List of easing aliases that you can use with `$.fn.transition`. 96 $.cssEase = { 97 '_default': 'ease', 98 'in': 'ease-in', 99 'out': 'ease-out', 100 'in-out': 'ease-in-out', 101 'snap': 'cubic-bezier(0,1,.5,1)', 102 // Penner equations 103 'easeOutCubic': 'cubic-bezier(.215,.61,.355,1)', 104 'easeInOutCubic': 'cubic-bezier(.645,.045,.355,1)', 105 'easeInCirc': 'cubic-bezier(.6,.04,.98,.335)', 106 'easeOutCirc': 'cubic-bezier(.075,.82,.165,1)', 107 'easeInOutCirc': 'cubic-bezier(.785,.135,.15,.86)', 108 'easeInExpo': 'cubic-bezier(.95,.05,.795,.035)', 109 'easeOutExpo': 'cubic-bezier(.19,1,.22,1)', 110 'easeInOutExpo': 'cubic-bezier(1,0,0,1)', 111 'easeInQuad': 'cubic-bezier(.55,.085,.68,.53)', 112 'easeOutQuad': 'cubic-bezier(.25,.46,.45,.94)', 113 'easeInOutQuad': 'cubic-bezier(.455,.03,.515,.955)', 114 'easeInQuart': 'cubic-bezier(.895,.03,.685,.22)', 115 'easeOutQuart': 'cubic-bezier(.165,.84,.44,1)', 116 'easeInOutQuart': 'cubic-bezier(.77,0,.175,1)', 117 'easeInQuint': 'cubic-bezier(.755,.05,.855,.06)', 118 'easeOutQuint': 'cubic-bezier(.23,1,.32,1)', 119 'easeInOutQuint': 'cubic-bezier(.86,0,.07,1)', 120 'easeInSine': 'cubic-bezier(.47,0,.745,.715)', 121 'easeOutSine': 'cubic-bezier(.39,.575,.565,1)', 122 'easeInOutSine': 'cubic-bezier(.445,.05,.55,.95)', 123 'easeInBack': 'cubic-bezier(.6,-.28,.735,.045)', 124 'easeOutBack': 'cubic-bezier(.175, .885,.32,1.275)', 125 'easeInOutBack': 'cubic-bezier(.68,-.55,.265,1.55)' 126 }; 127 128 // ## 'transform' CSS hook 129 // Allows you to use the `transform` property in CSS. 130 // 131 // $("#hello").css({ transform: "rotate(90deg)" }); 132 // 133 // $("#hello").css('transform'); 134 // //=> { rotate: '90deg' } 135 // 136 $.cssHooks['transit:transform'] = { 137 // The getter returns a `Transform` object. 138 get: function(elem) { 139 return $(elem).data('transform') || new Transform(); 140 }, 141 142 // The setter accepts a `Transform` object or a string. 143 set: function(elem, v) { 144 var value = v; 145 146 if (!(value instanceof Transform)) { 147 value = new Transform(value); 148 } 149 150 // We've seen the 3D version of Scale() not work in Chrome when the 151 // element being scaled extends outside of the viewport. Thus, we're 152 // forcing Chrome to not use the 3d transforms as well. Not sure if 153 // translate is affectede, but not risking it. Detection code from 154 // http://davidwalsh.name/detecting-google-chrome-javascript 155 if (support.transform === 'WebkitTransform' && !isChrome) { 156 elem.style[support.transform] = value.toString(true); 157 } else { 158 elem.style[support.transform] = value.toString(); 159 } 160 161 $(elem).data('transform', value); 162 } 163 }; 164 165 // Add a CSS hook for `.css({ transform: '...' })`. 166 // In jQuery 1.8+, this will intentionally override the default `transform` 167 // CSS hook so it'll play well with Transit. (see issue #62) 168 $.cssHooks.transform = { 169 set: $.cssHooks['transit:transform'].set 170 }; 171 172 // jQuery 1.8+ supports prefix-free transitions, so these polyfills will not 173 // be necessary. 174 if ($.fn.jquery < "1.8") { 175 // ## 'transformOrigin' CSS hook 176 // Allows the use for `transformOrigin` to define where scaling and rotation 177 // is pivoted. 178 // 179 // $("#hello").css({ transformOrigin: '0 0' }); 180 // 181 $.cssHooks.transformOrigin = { 182 get: function(elem) { 183 return elem.style[support.transformOrigin]; 184 }, 185 set: function(elem, value) { 186 elem.style[support.transformOrigin] = value; 187 } 188 }; 189 190 // ## 'transition' CSS hook 191 // Allows you to use the `transition` property in CSS. 192 // 193 // $("#hello").css({ transition: 'all 0 ease 0' }); 194 // 195 $.cssHooks.transition = { 196 get: function(elem) { 197 return elem.style[support.transition]; 198 }, 199 set: function(elem, value) { 200 elem.style[support.transition] = value; 201 } 202 }; 203 } 204 205 // ## Other CSS hooks 206 // Allows you to rotate, scale and translate. 207 registerCssHook('scale'); 208 registerCssHook('translate'); 209 registerCssHook('rotate'); 210 registerCssHook('rotateX'); 211 registerCssHook('rotateY'); 212 registerCssHook('rotate3d'); 213 registerCssHook('perspective'); 214 registerCssHook('skewX'); 215 registerCssHook('skewY'); 216 registerCssHook('x', true); 217 registerCssHook('y', true); 218 219 // ## Transform class 220 // This is the main class of a transformation property that powers 221 // `$.fn.css({ transform: '...' })`. 222 // 223 // This is, in essence, a dictionary object with key/values as `-transform` 224 // properties. 225 // 226 // var t = new Transform("rotate(90) scale(4)"); 227 // 228 // t.rotate //=> "90deg" 229 // t.scale //=> "4,4" 230 // 231 // Setters are accounted for. 232 // 233 // t.set('rotate', 4) 234 // t.rotate //=> "4deg" 235 // 236 // Convert it to a CSS string using the `toString()` and `toString(true)` (for WebKit) 237 // functions. 238 // 239 // t.toString() //=> "rotate(90deg) scale(4,4)" 240 // t.toString(true) //=> "rotate(90deg) scale3d(4,4,0)" (WebKit version) 241 // 242 function Transform(str) { 243 if (typeof str === 'string') { this.parse(str); } 244 return this; 245 } 246 247 Transform.prototype = { 248 // ### setFromString() 249 // Sets a property from a string. 250 // 251 // t.setFromString('scale', '2,4'); 252 // // Same as set('scale', '2', '4'); 253 // 254 setFromString: function(prop, val) { 255 var args = 256 (typeof val === 'string') ? val.split(',') : 257 (val.constructor === Array) ? val : 258 [ val ]; 259 260 args.unshift(prop); 261 262 Transform.prototype.set.apply(this, args); 263 }, 264 265 // ### set() 266 // Sets a property. 267 // 268 // t.set('scale', 2, 4); 269 // 270 set: function(prop) { 271 var args = Array.prototype.slice.apply(arguments, [1]); 272 if (this.setter[prop]) { 273 this.setter[prop].apply(this, args); 274 } else { 275 this[prop] = args.join(','); 276 } 277 }, 278 279 get: function(prop) { 280 if (this.getter[prop]) { 281 return this.getter[prop].apply(this); 282 } else { 283 return this[prop] || 0; 284 } 285 }, 286 287 setter: { 288 // ### rotate 289 // 290 // .css({ rotate: 30 }) 291 // .css({ rotate: "30" }) 292 // .css({ rotate: "30deg" }) 293 // .css({ rotate: "30deg" }) 294 // 295 rotate: function(theta) { 296 this.rotate = unit(theta, 'deg'); 297 }, 298 299 rotateX: function(theta) { 300 this.rotateX = unit(theta, 'deg'); 301 }, 302 303 rotateY: function(theta) { 304 this.rotateY = unit(theta, 'deg'); 305 }, 306 307 // ### scale 308 // 309 // .css({ scale: 9 }) //=> "scale(9,9)" 310 // .css({ scale: '3,2' }) //=> "scale(3,2)" 311 // 312 scale: function(x, y) { 313 if (y === undefined) { y = x; } 314 this.scale = x + "," + y; 315 }, 316 317 // ### skewX + skewY 318 skewX: function(x) { 319 this.skewX = unit(x, 'deg'); 320 }, 321 322 skewY: function(y) { 323 this.skewY = unit(y, 'deg'); 324 }, 325 326 // ### perspectvie 327 perspective: function(dist) { 328 this.perspective = unit(dist, 'px'); 329 }, 330 331 // ### x / y 332 // Translations. Notice how this keeps the other value. 333 // 334 // .css({ x: 4 }) //=> "translate(4px, 0)" 335 // .css({ y: 10 }) //=> "translate(4px, 10px)" 336 // 337 x: function(x) { 338 this.set('translate', x, null); 339 }, 340 341 y: function(y) { 342 this.set('translate', null, y); 343 }, 344 345 // ### translate 346 // Notice how this keeps the other value. 347 // 348 // .css({ translate: '2, 5' }) //=> "translate(2px, 5px)" 349 // 350 translate: function(x, y) { 351 if (this._translateX === undefined) { this._translateX = 0; } 352 if (this._translateY === undefined) { this._translateY = 0; } 353 354 if (x !== null && x !== undefined) { this._translateX = unit(x, 'px'); } 355 if (y !== null && y !== undefined) { this._translateY = unit(y, 'px'); } 356 357 this.translate = this._translateX + "," + this._translateY; 358 } 359 }, 360 361 getter: { 362 x: function() { 363 return this._translateX || 0; 364 }, 365 366 y: function() { 367 return this._translateY || 0; 368 }, 369 370 scale: function() { 371 var s = (this.scale || "1,1").split(','); 372 if (s[0]) { s[0] = parseFloat(s[0]); } 373 if (s[1]) { s[1] = parseFloat(s[1]); } 374 375 // "2.5,2.5" => 2.5 376 // "2.5,1" => [2.5,1] 377 return (s[0] === s[1]) ? s[0] : s; 378 }, 379 380 rotate3d: function() { 381 var s = (this.rotate3d || "0,0,0,0deg").split(','); 382 for (var i=0; i<=3; ++i) { 383 if (s[i]) { s[i] = parseFloat(s[i]); } 384 } 385 if (s[3]) { s[3] = unit(s[3], 'deg'); } 386 387 return s; 388 } 389 }, 390 391 // ### parse() 392 // Parses from a string. Called on constructor. 393 parse: function(str) { 394 var self = this; 395 str.replace(/([a-zA-Z0-9]+)\((.*?)\)/g, function(x, prop, val) { 396 self.setFromString(prop, val); 397 }); 398 }, 399 400 // ### toString() 401 // Converts to a `transition` CSS property string. If `use3d` is given, 402 // it converts to a `-webkit-transition` CSS property string instead. 403 toString: function(use3d) { 404 var re = []; 405 406 for (var i in this) { 407 if (this.hasOwnProperty(i)) { 408 // Don't use 3D transformations if the browser can't support it. 409 if ((!support.transform3d) && ( 410 (i === 'rotateX') || 411 (i === 'rotateY') || 412 (i === 'perspective') || 413 (i === 'transformOrigin'))) { continue; } 414 415 if (i[0] !== '_') { 416 if (use3d && (i === 'scale')) { 417 re.push(i + "3d(" + this[i] + ",1)"); 418 } else if (use3d && (i === 'translate')) { 419 re.push(i + "3d(" + this[i] + ",0)"); 420 } else { 421 re.push(i + "(" + this[i] + ")"); 422 } 423 } 424 } 425 } 426 427 return re.join(" "); 428 } 429 }; 430 431 function callOrQueue(self, queue, fn) { 432 if (queue === true) { 433 self.queue(fn); 434 } else if (queue) { 435 self.queue(queue, fn); 436 } else { 437 fn(); 438 } 439 } 440 441 // ### getProperties(dict) 442 // Returns properties (for `transition-property`) for dictionary `props`. The 443 // value of `props` is what you would expect in `$.css(...)`. 444 function getProperties(props) { 445 var re = []; 446 447 $.each(props, function(key) { 448 key = $.camelCase(key); // Convert "text-align" => "textAlign" 449 key = $.transit.propertyMap[key] || $.cssProps[key] || key; 450 key = uncamel(key); // Convert back to dasherized 451 452 if ($.inArray(key, re) === -1) { re.push(key); } 453 }); 454 455 return re; 456 } 457 458 // ### getTransition() 459 // Returns the transition string to be used for the `transition` CSS property. 460 // 461 // Example: 462 // 463 // getTransition({ opacity: 1, rotate: 30 }, 500, 'ease'); 464 // //=> 'opacity 500ms ease, -webkit-transform 500ms ease' 465 // 466 function getTransition(properties, duration, easing, delay) { 467 // Get the CSS properties needed. 468 var props = getProperties(properties); 469 470 // Account for aliases (`in` => `ease-in`). 471 if ($.cssEase[easing]) { easing = $.cssEase[easing]; } 472 473 // Build the duration/easing/delay attributes for it. 474 var attribs = '' + toMS(duration) + ' ' + easing; 475 if (parseInt(delay, 10) > 0) { attribs += ' ' + toMS(delay); } 476 477 // For more properties, add them this way: 478 // "margin 200ms ease, padding 200ms ease, ..." 479 var transitions = []; 480 $.each(props, function(i, name) { 481 transitions.push(name + ' ' + attribs); 482 }); 483 484 return transitions.join(', '); 485 } 486 487 // ## $.fn.transition 488 // Works like $.fn.animate(), but uses CSS transitions. 489 // 490 // $("...").transition({ opacity: 0.1, scale: 0.3 }); 491 // 492 // // Specific duration 493 // $("...").transition({ opacity: 0.1, scale: 0.3 }, 500); 494 // 495 // // With duration and easing 496 // $("...").transition({ opacity: 0.1, scale: 0.3 }, 500, 'in'); 497 // 498 // // With callback 499 // $("...").transition({ opacity: 0.1, scale: 0.3 }, function() { ... }); 500 // 501 // // With everything 502 // $("...").transition({ opacity: 0.1, scale: 0.3 }, 500, 'in', function() { ... }); 503 // 504 // // Alternate syntax 505 // $("...").transition({ 506 // opacity: 0.1, 507 // duration: 200, 508 // delay: 40, 509 // easing: 'in', 510 // complete: function() { /* ... */ } 511 // }); 512 // 513 $.fn.transition = $.fn.transit = function(properties, duration, easing, callback) { 514 var self = this; 515 var delay = 0; 516 var queue = true; 517 518 var theseProperties = jQuery.extend(true, {}, properties); 519 520 // Account for `.transition(properties, callback)`. 521 if (typeof duration === 'function') { 522 callback = duration; 523 duration = undefined; 524 } 525 526 // Account for `.transition(properties, options)`. 527 if (typeof duration === 'object') { 528 easing = duration.easing; 529 delay = duration.delay || 0; 530 queue = duration.queue || true; 531 callback = duration.complete; 532 duration = duration.duration; 533 } 534 535 // Account for `.transition(properties, duration, callback)`. 536 if (typeof easing === 'function') { 537 callback = easing; 538 easing = undefined; 539 } 540 541 // Alternate syntax. 542 if (typeof theseProperties.easing !== 'undefined') { 543 easing = theseProperties.easing; 544 delete theseProperties.easing; 545 } 546 547 if (typeof theseProperties.duration !== 'undefined') { 548 duration = theseProperties.duration; 549 delete theseProperties.duration; 550 } 551 552 if (typeof theseProperties.complete !== 'undefined') { 553 callback = theseProperties.complete; 554 delete theseProperties.complete; 555 } 556 557 if (typeof theseProperties.queue !== 'undefined') { 558 queue = theseProperties.queue; 559 delete theseProperties.queue; 560 } 561 562 if (typeof theseProperties.delay !== 'undefined') { 563 delay = theseProperties.delay; 564 delete theseProperties.delay; 565 } 566 567 // Set defaults. (`400` duration, `ease` easing) 568 if (typeof duration === 'undefined') { duration = $.fx.speeds._default; } 569 if (typeof easing === 'undefined') { easing = $.cssEase._default; } 570 571 duration = toMS(duration); 572 573 // Build the `transition` property. 574 var transitionValue = getTransition(theseProperties, duration, easing, delay); 575 576 // Compute delay until callback. 577 // If this becomes 0, don't bother setting the transition property. 578 var work = $.transit.enabled && support.transition; 579 var i = work ? (parseInt(duration, 10) + parseInt(delay, 10)) : 0; 580 581 // If there's nothing to do... 582 if (i === 0) { 583 var fn = function(next) { 584 self.css(theseProperties); 585 if (callback) { callback.apply(self); } 586 if (next) { next(); } 587 }; 588 589 callOrQueue(self, queue, fn); 590 return self; 591 } 592 593 // Save the old transitions of each element so we can restore it later. 594 var oldTransitions = {}; 595 596 var run = function(nextCall) { 597 var bound = false; 598 599 // Prepare the callback. 600 var cb = function() { 601 if (bound) { self.unbind(transitionEnd, cb); } 602 603 if (i > 0) { 604 self.each(function() { 605 this.style[support.transition] = (oldTransitions[this] || null); 606 }); 607 } 608 609 if (typeof callback === 'function') { callback.apply(self); } 610 if (typeof nextCall === 'function') { nextCall(); } 611 }; 612 613 if ((i > 0) && (transitionEnd) && ($.transit.useTransitionEnd)) { 614 // Use the 'transitionend' event if it's available. 615 bound = true; 616 self.bind(transitionEnd, cb); 617 } else { 618 // Fallback to timers if the 'transitionend' event isn't supported. 619 window.setTimeout(cb, i); 620 } 621 622 // Apply transitions. 623 self.each(function() { 624 if (i > 0) { 625 this.style[support.transition] = transitionValue; 626 } 627 $(this).css(properties); 628 }); 629 }; 630 631 // Defer running. This allows the browser to paint any pending CSS it hasn't 632 // painted yet before doing the transitions. 633 var deferredRun = function(next) { 634 this.offsetWidth; // force a repaint 635 run(next); 636 }; 637 638 // Use jQuery's fx queue. 639 callOrQueue(self, queue, deferredRun); 640 641 // Chainability. 642 return this; 643 }; 644 645 function registerCssHook(prop, isPixels) { 646 // For certain properties, the 'px' should not be implied. 647 if (!isPixels) { $.cssNumber[prop] = true; } 648 649 $.transit.propertyMap[prop] = support.transform; 650 651 $.cssHooks[prop] = { 652 get: function(elem) { 653 var t = $(elem).css('transit:transform'); 654 return t.get(prop); 655 }, 656 657 set: function(elem, value) { 658 var t = $(elem).css('transit:transform'); 659 t.setFromString(prop, value); 660 661 $(elem).css({ 'transit:transform': t }); 662 } 663 }; 664 665 } 666 667 // ### uncamel(str) 668 // Converts a camelcase string to a dasherized string. 669 // (`marginLeft` => `margin-left`) 670 function uncamel(str) { 671 return str.replace(/([A-Z])/g, function(letter) { return '-' + letter.toLowerCase(); }); 672 } 673 674 // ### unit(number, unit) 675 // Ensures that number `number` has a unit. If no unit is found, assume the 676 // default is `unit`. 677 // 678 // unit(2, 'px') //=> "2px" 679 // unit("30deg", 'rad') //=> "30deg" 680 // 681 function unit(i, units) { 682 if ((typeof i === "string") && (!i.match(/^[\-0-9\.]+$/))) { 683 return i; 684 } else { 685 return "" + i + units; 686 } 687 } 688 689 // ### toMS(duration) 690 // Converts given `duration` to a millisecond string. 691 // 692 // toMS('fast') => $.fx.speeds[i] => "200ms" 693 // toMS('normal') //=> $.fx.speeds._default => "400ms" 694 // toMS(10) //=> '10ms' 695 // toMS('100ms') //=> '100ms' 696 // 697 function toMS(duration) { 698 var i = duration; 699 700 // Allow string durations like 'fast' and 'slow', without overriding numeric values. 701 if (typeof i === 'string' && (!i.match(/^[\-0-9\.]+/))) { i = $.fx.speeds[i] || $.fx.speeds._default; } 702 703 return unit(i, 'ms'); 704 } 705 706 // Export some functions for testable-ness. 707 $.transit.getTransitionValue = getTransition; 708})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.