PageSourceSearch

https://flexben.my/public/plugins/jquery.transit/jquery.transit.js

js flexben.my collected 2026-09-24 15:06:54 UTC 21,840 bytes, 727 lines download raw bytes

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