fx.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. // Zepto.js
  2. // (c) 2010-2014 Thomas Fuchs
  3. // Zepto.js may be freely distributed under the MIT license.
  4. ; (function ($, undefined) {
  5. var prefix = '', eventPrefix, endEventName, endAnimationName,
  6. vendors = { Webkit: 'webkit', Moz: '', O: 'o' },
  7. document = window.document, testEl = document.createElement('div'),
  8. supportedTransforms = /^((translate|rotate|scale)(X|Y|Z|3d)?|matrix(3d)?|perspective|skew(X|Y)?)$/i,
  9. transform,
  10. transitionProperty, transitionDuration, transitionTiming, transitionDelay,
  11. animationName, animationDuration, animationTiming, animationDelay,
  12. cssReset = {}
  13. function dasherize(str) { return str.replace(/([a-z])([A-Z])/, '$1-$2').toLowerCase() }
  14. function normalizeEvent(name) { return eventPrefix ? eventPrefix + name : name.toLowerCase() }
  15. $.each(vendors, function (vendor, event) {
  16. if (testEl.style[vendor + 'TransitionProperty'] !== undefined) {
  17. prefix = '-' + vendor.toLowerCase() + '-'
  18. eventPrefix = event
  19. return false
  20. }
  21. })
  22. transform = prefix + 'transform'
  23. cssReset[transitionProperty = prefix + 'transition-property'] =
  24. cssReset[transitionDuration = prefix + 'transition-duration'] =
  25. cssReset[transitionDelay = prefix + 'transition-delay'] =
  26. cssReset[transitionTiming = prefix + 'transition-timing-function'] =
  27. cssReset[animationName = prefix + 'animation-name'] =
  28. cssReset[animationDuration = prefix + 'animation-duration'] =
  29. cssReset[animationDelay = prefix + 'animation-delay'] =
  30. cssReset[animationTiming = prefix + 'animation-timing-function'] = ''
  31. $.fx = {
  32. off: (eventPrefix === undefined && testEl.style.transitionProperty === undefined),
  33. speeds: { _default: 400, fast: 200, slow: 600 },
  34. cssPrefix: prefix,
  35. transitionEnd: normalizeEvent('TransitionEnd'),
  36. animationEnd: normalizeEvent('AnimationEnd')
  37. }
  38. $.fn.animate = function (properties, duration, ease, callback, delay) {
  39. if ($.isFunction(duration))
  40. callback = duration, ease = undefined, duration = undefined
  41. if ($.isFunction(ease))
  42. callback = ease, ease = undefined
  43. if ($.isPlainObject(duration))
  44. ease = duration.easing, callback = duration.complete, delay = duration.delay, duration = duration.duration
  45. if (duration) duration = (typeof duration == 'number' ? duration :
  46. ($.fx.speeds[duration] || $.fx.speeds._default)) / 1000
  47. if (delay) delay = parseFloat(delay) / 1000
  48. return this.anim(properties, duration, ease, callback, delay)
  49. }
  50. $.fn.anim = function (properties, duration, ease, callback, delay) {
  51. var key, cssValues = {}, cssProperties, transforms = '',
  52. that = this, wrappedCallback, endEvent = $.fx.transitionEnd,
  53. fired = false
  54. if (duration === undefined) duration = $.fx.speeds._default / 1000
  55. if (delay === undefined) delay = 0
  56. if ($.fx.off) duration = 0
  57. if (typeof properties == 'string') {
  58. // keyframe animation
  59. cssValues[animationName] = properties
  60. cssValues[animationDuration] = duration + 's'
  61. cssValues[animationDelay] = delay + 's'
  62. cssValues[animationTiming] = (ease || 'linear')
  63. endEvent = $.fx.animationEnd
  64. } else {
  65. cssProperties = []
  66. // CSS transitions
  67. for (key in properties)
  68. if (supportedTransforms.test(key)) transforms += key + '(' + properties[key] + ') '
  69. else cssValues[key] = properties[key], cssProperties.push(dasherize(key))
  70. if (transforms) cssValues[transform] = transforms, cssProperties.push(transform)
  71. if (duration > 0 && typeof properties === 'object') {
  72. cssValues[transitionProperty] = cssProperties.join(', ')
  73. cssValues[transitionDuration] = duration + 's'
  74. cssValues[transitionDelay] = delay + 's'
  75. cssValues[transitionTiming] = (ease || 'linear')
  76. }
  77. }
  78. wrappedCallback = function (event) {
  79. if (typeof event !== 'undefined') {
  80. if (event.target !== event.currentTarget) return // makes sure the event didn't bubble from "below"
  81. $(event.target).unbind(endEvent, wrappedCallback)
  82. } else
  83. $(this).unbind(endEvent, wrappedCallback) // triggered by setTimeout
  84. fired = true
  85. $(this).css(cssReset)
  86. callback && callback.call(this)
  87. }
  88. if (duration > 0) {
  89. this.bind(endEvent, wrappedCallback)
  90. // transitionEnd is not always firing on older Android phones
  91. // so make sure it gets fired
  92. setTimeout(function () {
  93. if (fired) return
  94. wrappedCallback.call(that)
  95. }, (duration * 1000) + 25)
  96. }
  97. // trigger page reflow so new elements can animate
  98. this.size() && this.get(0).clientLeft
  99. this.css(cssValues)
  100. if (duration <= 0) setTimeout(function () {
  101. that.each(function () { wrappedCallback.call(this) })
  102. }, 0)
  103. return this
  104. }
  105. testEl = null
  106. })(Zepto)