//>>built define("dojox/fx/style", ["dojo/_base/kernel","dojo/_base/lang","dojo/_base/fx","dojo/fx","./_base","dojo/_base/array","dojo/dom","dojo/dom-style","dojo/dom-class", "dojo/_base/connect"], function(dojo,lang,baseFx,coreFx,dojoxFx,arrayUtil,dom,domStyle,domClass,connectUtil){ dojo.experimental("dojox.fx.style"); // summary: // dojox.fx CSS Class Animations: // // description: // a set of functions to animate properties based on // normalized CSS class definitions. // // provides: addClass, removeClass, and toggleClass // var _getStyleSnapshot = function(/* Object */cache){ // summary: // uses a dojo.getComputedStyle(node) cache reference and // iterates through the 'documented/supported animate-able' // properties. // // returns: Array // an array of raw, calculcated values (no keys), to be normalized/compared // elsewhere return arrayUtil.map(dojoxFx._allowedProperties, function(style){ return cache[style]; // String }); // Array }; var _getCalculatedStyleChanges = function(node, cssClass, addClass){ // summary: Calculate the difference in style properties between two states // description: // calculate and normalize(?) the differences between two states // of a node (args.node) by quickly adding or removing a class, and // iterateing over the results of dojox.fx._getStyleSnapshot() // // addClass: // true to calculate what adding a class would do, // false to calculate what removing the class would do node = dom.byId(node); var cs = domStyle.getComputedStyle(node); // take our snapShots var _before = _getStyleSnapshot(cs); dojo[(addClass ? "addClass" : "removeClass")](node, cssClass); var _after = _getStyleSnapshot(cs); dojo[(addClass ? "removeClass" : "addClass")](node, cssClass); var calculated = {}, i = 0; arrayUtil.forEach(dojoxFx._allowedProperties, function(prop){ if(_before[i] != _after[i]){ // FIXME: the static units: px is not good, either. need to parse unit from computed style? calculated[prop] = parseInt(_after[i]) /* start: parseInt(_before[i]), units: 'px' */ ; } i++; }); return calculated; }; var styleFx = { // Augment dojox.fx for compat addClass: function(node, cssClass, args){ // summary: // Animate the effects of adding a class to a node // // description: // Creates an animation that will animate // the properties of a node to the properties // defined in a standard CSS .class definition. // (calculating the differences itself) // // node: String|DomNode // A String ID or DomNode referce to animate // // cssClass: String // The CSS class name to add to the node // // args: Object? // Additional optional `dojo.animateProperty` arguments, such as // duration, easing and so on. // // example: // | // | .bar { line-height: 12px; } // | .foo { line-height: 40px; } // |
// | // | // animate to line-height:40px // | dojo.fx.addClass("test", "foo").play(); // node = dom.byId(node); var pushClass = (function(n){ // summary: onEnd we want to add the class to the node // (as dojo.addClass naturally would) in case our // class parsing misses anything the browser would // otherwise interpret. this may cause some flicker, // and will only apply the class so children can inherit // after the animation is done (potentially more flicker) return function(){ domClass.add(n, cssClass); n.style.cssText = _beforeStyle; } })(node); // _getCalculatedStleChanges is the core of our style/class animations var mixedProperties = _getCalculatedStyleChanges(node, cssClass, true); var _beforeStyle = node.style.cssText; var _anim = baseFx.animateProperty(lang.mixin({ node: node, properties: mixedProperties }, args)); connectUtil.connect(_anim, "onEnd", _anim, pushClass); return _anim; // dojo.Animation }, removeClass: function(node, cssClass, args){ // summary: Animate the effects of removing a class from a node // description: // Creates an animation that will animate the properties of a // node (args.node) to the properties calculated after removing // a standard CSS className from a that node. // // calls dojo.removeClass(args.cssClass) onEnd of animation // // standard dojo.Animation object rules apply. // // example: // | // animate the removal of "foo" from a node with id="bar" // | dojox.fx.removeClass("bar", "foo").play() node = dom.byId(node); var pullClass = (function(n){ // summary: onEnd we want to remove the class from the node // (as dojo.removeClass naturally would) in case our class // parsing misses anything the browser would otherwise // interpret. this may cause some flicker, and will only // apply the class so children can inherit after the // animation is done (potentially more flicker) // return function(){ domClass.remove(n, cssClass); n.style.cssText = _beforeStyle; } })(node); var mixedProperties = _getCalculatedStyleChanges(node, cssClass); var _beforeStyle = node.style.cssText; var _anim = baseFx.animateProperty(lang.mixin({ node: node, properties: mixedProperties }, args)); connectUtil.connect(_anim, "onEnd", _anim, pullClass); return _anim; // dojo.Animation }, toggleClass: function(node, cssClass, condition, args){ // summary: // Animate the effects of Toggling a class on a Node // // description: // creates an animation that will animate the effect of // toggling a class on or off of a node. // Adds a class to node if not present, or removes if present. // Pass a boolean condition if you want to explicitly add or remove. // // node: String|DomNode // The domNode (or string of the id) to toggle // cssClass: String // String of the classname to add to the node // condition: Boolean? // If passed, true means to add the class, false means to remove. // args: Object? // Additional `dojo.Animation` args to pass along. // // example: // | // add the class "sampleClass" to a node id="theNode" // | dojox.fx.toggleClass("theNode","sampleClass",true).play(); // example: // | // toggle the class "sampleClass" on the node id="theNode" // | dojox.fx.toggleClass("theNode","sampleClass").play(); if(typeof condition == "undefined"){ condition = !domClass.contains(node, cssClass); } return dojoxFx[(condition ? "addClass" : "removeClass")](node, cssClass, args); // dojo.Animation }, _allowedProperties: [ // summary: Our pseudo map of properties we will check for. // description: // it should be much more intuitive. a way to normalize and // "predict" intent, or even something more clever ... // open to suggestions. // no-brainers: "width", "height", // only if position = absolute || relative? "left", "top", // "right", "bottom", // these need to be filtered through dojo.colors? // "background", // normalize to: /* "backgroundImage", */ // "backgroundPosition", // FIXME: to be effective, this needs "#px #px"? "backgroundColor", "color", // "border", //"borderBottomColor", "borderBottomWidth", //"borderTopColor", "borderTopWidth", //"borderLeftColor", "borderLeftWidth", //"borderRightColor", "borderRightWidth", // "padding", // normalize to: "paddingLeft", "paddingRight", "paddingTop", "paddingBottom", // "margin", // normalize to: "marginLeft", "marginTop", "marginRight", "marginBottom", // unit import/delicate?: "lineHeight", "letterSpacing", "fontSize" ] }; lang.mixin(dojoxFx,styleFx); return styleFx; });