style.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojox.fx.style"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.fx.style"] = true;
  8. dojo.provide("dojox.fx.style");
  9. dojo.experimental("dojox.fx.style");
  10. //
  11. // summary:
  12. // dojox.fx CSS Class Animations:
  13. //
  14. // description:
  15. // a set of functions to animate properties based on
  16. // normalized CSS class definitions.
  17. //
  18. // provides: addClass, removeClass, and toggleClass
  19. //
  20. dojo.require("dojo.fx");
  21. (function(){
  22. var d = dojo;
  23. var _getStyleSnapshot = function(/* Object */cache){
  24. // summary:
  25. // uses a dojo.getComputedStyle(node) cache reference and
  26. // iterates through the 'documented/supported animate-able'
  27. // properties.
  28. //
  29. // returns: Array
  30. // an array of raw, calculcated values (no keys), to be normalized/compared
  31. // elsewhere
  32. return d.map(dojox.fx._allowedProperties, function(style){
  33. return cache[style]; // String
  34. }); // Array
  35. };
  36. var _getCalculatedStyleChanges = function(node, cssClass, addClass){
  37. // summary: Calculate the difference in style properties between two states
  38. // description:
  39. // calculate and normalize(?) the differences between two states
  40. // of a node (args.node) by quickly adding or removing a class, and
  41. // iterateing over the results of dojox.fx._getStyleSnapshot()
  42. //
  43. // addClass:
  44. // true to calculate what adding a class would do,
  45. // false to calculate what removing the class would do
  46. node = d.byId(node);
  47. var cs = d.getComputedStyle(node);
  48. // take our snapShots
  49. var _before = _getStyleSnapshot(cs);
  50. d[(addClass ? "addClass" : "removeClass")](node, cssClass);
  51. var _after = _getStyleSnapshot(cs);
  52. d[(addClass ? "removeClass" : "addClass")](node, cssClass);
  53. var calculated = {}, i = 0;
  54. d.forEach(dojox.fx._allowedProperties, function(prop){
  55. if(_before[i] != _after[i]){
  56. // FIXME: the static units: px is not good, either. need to parse unit from computed style?
  57. calculated[prop] = parseInt(_after[i]) /* start: parseInt(_before[i]), units: 'px' */ ;
  58. }
  59. i++;
  60. });
  61. return calculated;
  62. };
  63. d.mixin(dojox.fx,{
  64. addClass: function(node, cssClass, args){
  65. // summary:
  66. // Animate the effects of adding a class to a node
  67. //
  68. // description:
  69. // Creates an animation that will animate
  70. // the properties of a node to the properties
  71. // defined in a standard CSS .class definition.
  72. // (calculating the differences itself)
  73. //
  74. // node: String|DomNode
  75. // A String ID or DomNode referce to animate
  76. //
  77. // cssClass: String
  78. // The CSS class name to add to the node
  79. //
  80. // args: Object?
  81. // Additional optional `dojo.animateProperty` arguments, such as
  82. // duration, easing and so on.
  83. //
  84. // example:
  85. // |
  86. // | .bar { line-height: 12px; }
  87. // | .foo { line-height: 40px; }
  88. // | <div class="bar" id="test">
  89. // | Multi<br>line<br>text
  90. // | </div>
  91. // |
  92. // | // animate to line-height:40px
  93. // | dojo.fx.addClass("test", "foo").play();
  94. //
  95. node = d.byId(node);
  96. var pushClass = (function(n){
  97. // summary: onEnd we want to add the class to the node
  98. // (as dojo.addClass naturally would) in case our
  99. // class parsing misses anything the browser would
  100. // otherwise interpret. this may cause some flicker,
  101. // and will only apply the class so children can inherit
  102. // after the animation is done (potentially more flicker)
  103. return function(){
  104. d.addClass(n, cssClass);
  105. n.style.cssText = _beforeStyle;
  106. }
  107. })(node);
  108. // _getCalculatedStleChanges is the core of our style/class animations
  109. var mixedProperties = _getCalculatedStyleChanges(node, cssClass, true);
  110. var _beforeStyle = node.style.cssText;
  111. var _anim = d.animateProperty(d.mixin({
  112. node: node,
  113. properties: mixedProperties
  114. }, args));
  115. d.connect(_anim, "onEnd", _anim, pushClass);
  116. return _anim; // dojo.Animation
  117. },
  118. removeClass: function(node, cssClass, args){
  119. // summary: Animate the effects of removing a class from a node
  120. // description:
  121. // Creates an animation that will animate the properties of a
  122. // node (args.node) to the properties calculated after removing
  123. // a standard CSS className from a that node.
  124. //
  125. // calls dojo.removeClass(args.cssClass) onEnd of animation
  126. //
  127. // standard dojo.Animation object rules apply.
  128. //
  129. // example:
  130. // | // animate the removal of "foo" from a node with id="bar"
  131. // | dojox.fx.removeClass("bar", "foo").play()
  132. node = d.byId(node);
  133. var pullClass = (function(n){
  134. // summary: onEnd we want to remove the class from the node
  135. // (as dojo.removeClass naturally would) in case our class
  136. // parsing misses anything the browser would otherwise
  137. // interpret. this may cause some flicker, and will only
  138. // apply the class so children can inherit after the
  139. // animation is done (potentially more flicker)
  140. //
  141. return function(){
  142. d.removeClass(n, cssClass);
  143. n.style.cssText = _beforeStyle;
  144. }
  145. })(node);
  146. var mixedProperties = _getCalculatedStyleChanges(node, cssClass);
  147. var _beforeStyle = node.style.cssText;
  148. var _anim = d.animateProperty(d.mixin({
  149. node: node,
  150. properties: mixedProperties
  151. }, args));
  152. d.connect(_anim, "onEnd", _anim, pullClass);
  153. return _anim; // dojo.Animation
  154. },
  155. toggleClass: function(node, cssClass, condition, args){
  156. // summary:
  157. // Animate the effects of Toggling a class on a Node
  158. //
  159. // description:
  160. // creates an animation that will animate the effect of
  161. // toggling a class on or off of a node.
  162. // Adds a class to node if not present, or removes if present.
  163. // Pass a boolean condition if you want to explicitly add or remove.
  164. //
  165. // node: String|DomNode
  166. // The domNode (or string of the id) to toggle
  167. // cssClass: String
  168. // String of the classname to add to the node
  169. // condition: Boolean?
  170. // If passed, true means to add the class, false means to remove.
  171. // args: Object?
  172. // Additional `dojo.Animation` args to pass along.
  173. //
  174. // example:
  175. // | // add the class "sampleClass" to a node id="theNode"
  176. // | dojox.fx.toggleClass("theNode","sampleClass",true).play();
  177. // example:
  178. // | // toggle the class "sampleClass" on the node id="theNode"
  179. // | dojox.fx.toggleClass("theNode","sampleClass").play();
  180. if(typeof condition == "undefined"){
  181. condition = !d.hasClass(node, cssClass);
  182. }
  183. return dojox.fx[(condition ? "addClass" : "removeClass")](node, cssClass, args); // dojo.Animation
  184. },
  185. _allowedProperties: [
  186. // summary: Our pseudo map of properties we will check for.
  187. // description:
  188. // it should be much more intuitive. a way to normalize and
  189. // "predict" intent, or even something more clever ...
  190. // open to suggestions.
  191. // no-brainers:
  192. "width",
  193. "height",
  194. // only if position = absolute || relative?
  195. "left", "top", // "right", "bottom",
  196. // these need to be filtered through dojo.colors?
  197. // "background", // normalize to:
  198. /* "backgroundImage", */
  199. // "backgroundPosition", // FIXME: to be effective, this needs "#px #px"?
  200. "backgroundColor",
  201. "color",
  202. // "border",
  203. //"borderBottomColor",
  204. "borderBottomWidth",
  205. //"borderTopColor",
  206. "borderTopWidth",
  207. //"borderLeftColor",
  208. "borderLeftWidth",
  209. //"borderRightColor",
  210. "borderRightWidth",
  211. // "padding", // normalize to:
  212. "paddingLeft", "paddingRight", "paddingTop", "paddingBottom",
  213. // "margin", // normalize to:
  214. "marginLeft", "marginTop", "marginRight", "marginBottom",
  215. // unit import/delicate?:
  216. "lineHeight",
  217. "letterSpacing",
  218. "fontSize"
  219. ]
  220. });
  221. })();
  222. }