Last active
August 29, 2015 13:56
-
-
Save macgyver/8874337 to your computer and use it in GitHub Desktop.
calculate and execute css transitions to/from automatically computed values
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# requires: jQuery as $ and underscore as _, uses Modernizr if available | |
# normalized string for transitionEnd event name | |
transitionEnd = "webkitTransitionEnd oTransitionEnd transitionend" | |
# feature test for CSS transitions in the browser | |
hasTransitions = Modernizr?.csstransitions or ( -> | |
return _.some [ | |
"transition", | |
"webkitTransition", | |
"MozTransition", | |
"OTransition" | |
], (propertyName) -> | |
# silly, but _.has fails here, these are weird objects | |
# https://bugzilla.mozilla.org/show_bug.cgi?id=967061 | |
return not _.isUndefined document.body.style[propertyName] | |
)() | |
# we can remove this nonsense once safari updates to a more current | |
# version of webkit without the rubber-banding auto css transitions | |
isSafari = window.navigator.vendor is "Apple Computer, Inc." and window.navigator.userAgent.indexOf("Safari") > -1 | |
# helper for css transitions to auto-computed values, | |
# see _older_floats or notifications.coffee | |
# todo: In the future, in order to encourage the very best style, | |
# I'd like for the change to be based only on the toggle of | |
# a class name, but this pair of functions works ok for now | |
# | |
# $el - the element on which the transition will occur | |
# props - the properties being animated, | |
# most likely ⊂ ["height", "width"] | |
# change - a function that makes the change that will affect layout | |
# revert - a function that defines how to revert the change | |
# optional, defaults to the `change` param if omitted. | |
transitionAuto: ($el, props, change, revert=false) -> | |
# without transitions, just make the change and be done with it | |
if not hasTransitions or isSafari | |
return change() | |
# allow string input, representing an array with a single element | |
if (typeof props) is "string" | |
props = [props] | |
# if only one fn is provided, it is a toggle fn | |
revert = revert or change | |
setToAuto = -> | |
$el.removeAttr "style" | |
getStylesAsMap = -> | |
# jquery's .css seems busted for this signature (in our build) :( | |
# revisit this when/if we ever upgrade jQuery, `$el.css props` should suffice | |
_.reduce props, (map, prop) -> | |
map[prop] = $el.css prop | |
return map | |
, {} | |
# clear styles, letting auto-computed values define the "before" state | |
setToAuto() | |
beforeStyles = getStylesAsMap() | |
# quickly change, assess to determine the "after" state, then revert | |
change() | |
afterStyles = getStylesAsMap() | |
revert() | |
# set the css explicitly to the "beforeStyles" | |
$el.css beforeStyles | |
# finally trigger the transition to the explicit "afterStyles" | |
setTimeout _.bind( -> | |
change() | |
$el.addClass("transitioning").css afterStyles | |
# last of all, wait for the transition and then clean up | |
$el.one transitionEnd, -> | |
$el.removeClass "transitioning" | |
setToAuto() | |
, this), 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment