| /* |
| Copyright (c) 2004-2006, The Dojo Foundation |
| All Rights Reserved. |
| |
| Licensed under the Academic Free License version 2.1 or above OR the |
| modified BSD license. For more information on Dojo licensing, see: |
| |
| http://dojotoolkit.org/community/licensing.shtml |
| */ |
| |
| dojo.provide("dojo.lfx.html"); |
| |
| dojo.require("dojo.gfx.color"); |
| dojo.require("dojo.lfx.Animation"); |
| dojo.require("dojo.lang.array"); |
| dojo.require("dojo.html.display"); |
| dojo.require("dojo.html.color"); |
| dojo.require("dojo.html.layout"); |
| |
| dojo.lfx.html._byId = function(nodes){ |
| if(!nodes){ return []; } |
| if(dojo.lang.isArrayLike(nodes)){ |
| if(!nodes.alreadyChecked){ |
| var n = []; |
| dojo.lang.forEach(nodes, function(node){ |
| n.push(dojo.byId(node)); |
| }); |
| n.alreadyChecked = true; |
| return n; |
| }else{ |
| return nodes; |
| } |
| }else{ |
| var n = []; |
| n.push(dojo.byId(nodes)); |
| n.alreadyChecked = true; |
| return n; |
| } |
| } |
| |
| dojo.lfx.html.propertyAnimation = function( /*DOMNode[]*/ nodes, |
| /*Object[]*/ propertyMap, |
| /*int*/ duration, |
| /*function*/ easing, |
| /*Object*/ handlers){ |
| // summary: Returns an animation that will transition the properties of "nodes" |
| // depending how they are defined in "propertyMap". |
| // nodes: An array of DOMNodes or one DOMNode. |
| // propertyMap: { property: String, start: Decimal?, end: Decimal?, units: String? } |
| // An array of objects defining properties to change. |
| // duration: Duration of the animation in milliseconds. |
| // easing: An easing function. |
| // handlers: { handler: Function?, onstart: Function?, onstop: Function?, onanimate: Function? } |
| nodes = dojo.lfx.html._byId(nodes); |
| |
| var targs = { |
| "propertyMap": propertyMap, |
| "nodes": nodes, |
| "duration": duration, |
| "easing": easing||dojo.lfx.easeDefault |
| }; |
| |
| var setEmUp = function(args){ |
| if(args.nodes.length==1){ |
| // FIXME: we're only supporting start-value filling when one node is |
| // passed |
| |
| var pm = args.propertyMap; |
| if(!dojo.lang.isArray(args.propertyMap)){ |
| // it's stupid to have to pack an array with a set of objects |
| // when you can just pass in an object list |
| var parr = []; |
| for(var pname in pm){ |
| pm[pname].property = pname; |
| parr.push(pm[pname]); |
| } |
| pm = args.propertyMap = parr; |
| } |
| dojo.lang.forEach(pm, function(prop){ |
| if(dj_undef("start", prop)){ |
| if(prop.property != "opacity"){ |
| prop.start = parseInt(dojo.html.getComputedStyle(args.nodes[0], prop.property)); |
| }else{ |
| prop.start = dojo.html.getOpacity(args.nodes[0]); |
| } |
| } |
| }); |
| } |
| } |
| |
| var coordsAsInts = function(coords){ |
| var cints = []; |
| dojo.lang.forEach(coords, function(c){ |
| cints.push(Math.round(c)); |
| }); |
| return cints; |
| } |
| |
| var setStyle = function(n, style){ |
| n = dojo.byId(n); |
| if(!n || !n.style){ return; } |
| for(var s in style){ |
| try{ |
| if(s == "opacity"){ |
| dojo.html.setOpacity(n, style[s]); |
| }else{ |
| n.style[s] = style[s]; |
| } |
| }catch(e){ dojo.debug(e); } |
| } |
| } |
| |
| var propLine = function(properties){ |
| this._properties = properties; |
| this.diffs = new Array(properties.length); |
| dojo.lang.forEach(properties, function(prop, i){ |
| // calculate the end - start to optimize a bit |
| if(dojo.lang.isFunction(prop.start)){ |
| prop.start = prop.start(prop, i); |
| } |
| if(dojo.lang.isFunction(prop.end)){ |
| prop.end = prop.end(prop, i); |
| } |
| if(dojo.lang.isArray(prop.start)){ |
| // don't loop through the arrays |
| this.diffs[i] = null; |
| }else if(prop.start instanceof dojo.gfx.color.Color){ |
| // save these so we don't have to call toRgb() every getValue() call |
| prop.startRgb = prop.start.toRgb(); |
| prop.endRgb = prop.end.toRgb(); |
| }else{ |
| this.diffs[i] = prop.end - prop.start; |
| } |
| }, this); |
| |
| this.getValue = function(n){ |
| var ret = {}; |
| dojo.lang.forEach(this._properties, function(prop, i){ |
| var value = null; |
| if(dojo.lang.isArray(prop.start)){ |
| // FIXME: what to do here? |
| }else if(prop.start instanceof dojo.gfx.color.Color){ |
| value = (prop.units||"rgb") + "("; |
| for(var j = 0 ; j < prop.startRgb.length ; j++){ |
| value += Math.round(((prop.endRgb[j] - prop.startRgb[j]) * n) + prop.startRgb[j]) + (j < prop.startRgb.length - 1 ? "," : ""); |
| } |
| value += ")"; |
| }else{ |
| value = ((this.diffs[i]) * n) + prop.start + (prop.property != "opacity" ? prop.units||"px" : ""); |
| } |
| ret[dojo.html.toCamelCase(prop.property)] = value; |
| }, this); |
| return ret; |
| } |
| } |
| |
| var anim = new dojo.lfx.Animation({ |
| beforeBegin: function(){ |
| setEmUp(targs); |
| anim.curve = new propLine(targs.propertyMap); |
| }, |
| onAnimate: function(propValues){ |
| dojo.lang.forEach(targs.nodes, function(node){ |
| setStyle(node, propValues); |
| }); |
| } |
| }, |
| targs.duration, |
| null, |
| targs.easing |
| ); |
| if(handlers){ |
| for(var x in handlers){ |
| if(dojo.lang.isFunction(handlers[x])){ |
| anim.connect(x, anim, handlers[x]); |
| } |
| } |
| } |
| |
| return anim; // dojo.lfx.Animation |
| } |
| |
| dojo.lfx.html._makeFadeable = function(nodes){ |
| var makeFade = function(node){ |
| if(dojo.render.html.ie){ |
| // only set the zoom if the "tickle" value would be the same as the |
| // default |
| if( (node.style.zoom.length == 0) && |
| (dojo.html.getStyle(node, "zoom") == "normal") ){ |
| // make sure the node "hasLayout" |
| // NOTE: this has been tested with larger and smaller user-set text |
| // sizes and works fine |
| node.style.zoom = "1"; |
| // node.style.zoom = "normal"; |
| } |
| // don't set the width to auto if it didn't already cascade that way. |
| // We don't want to f anyones designs |
| if( (node.style.width.length == 0) && |
| (dojo.html.getStyle(node, "width") == "auto") ){ |
| node.style.width = "auto"; |
| } |
| } |
| } |
| if(dojo.lang.isArrayLike(nodes)){ |
| dojo.lang.forEach(nodes, makeFade); |
| }else{ |
| makeFade(nodes); |
| } |
| } |
| |
| dojo.lfx.html.fade = function(/*DOMNode[]*/ nodes, |
| /*Object*/values, |
| /*int?*/ duration, |
| /*Function?*/ easing, |
| /*Function?*/ callback){ |
| // summary:Returns an animation that will fade the "nodes" from the start to end values passed. |
| // nodes: An array of DOMNodes or one DOMNode. |
| // values: { start: Decimal?, end: Decimal? } |
| // duration: Duration of the animation in milliseconds. |
| // easing: An easing function. |
| // callback: Function to run at the end of the animation. |
| nodes = dojo.lfx.html._byId(nodes); |
| var props = { property: "opacity" }; |
| if(!dj_undef("start", values)){ |
| props.start = values.start; |
| }else{ |
| props.start = function(){ return dojo.html.getOpacity(nodes[0]); }; |
| } |
| |
| if(!dj_undef("end", values)){ |
| props.end = values.end; |
| }else{ |
| dojo.raise("dojo.lfx.html.fade needs an end value"); |
| } |
| |
| var anim = dojo.lfx.propertyAnimation(nodes, [ props ], duration, easing); |
| anim.connect("beforeBegin", function(){ |
| dojo.lfx.html._makeFadeable(nodes); |
| }); |
| if(callback){ |
| anim.connect("onEnd", function(){ callback(nodes, anim); }); |
| } |
| |
| return anim; // dojo.lfx.Animation |
| } |
| |
| dojo.lfx.html.fadeIn = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){ |
| // summary: Returns an animation that will fade "nodes" from its current opacity to fully opaque. |
| // nodes: An array of DOMNodes or one DOMNode. |
| // duration: Duration of the animation in milliseconds. |
| // easing: An easing function. |
| // callback: Function to run at the end of the animation. |
| return dojo.lfx.html.fade(nodes, { end: 1 }, duration, easing, callback); // dojo.lfx.Animation |
| } |
| |
| dojo.lfx.html.fadeOut = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){ |
| // summary: Returns an animation that will fade "nodes" from its current opacity to fully transparent. |
| // nodes: An array of DOMNodes or one DOMNode. |
| // duration: Duration of the animation in milliseconds. |
| // easing: An easing function. |
| // callback: Function to run at the end of the animation. |
| return dojo.lfx.html.fade(nodes, { end: 0 }, duration, easing, callback); // dojo.lfx.Animation |
| } |
| |
| dojo.lfx.html.fadeShow = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){ |
| // summary: Returns an animation that will fade "nodes" from transparent to opaque and shows |
| // "nodes" at the end if it is hidden. |
| // nodes: An array of DOMNodes or one DOMNode. |
| // duration: Duration of the animation in milliseconds. |
| // easing: An easing function. |
| // callback: Function to run at the end of the animation. |
| nodes=dojo.lfx.html._byId(nodes); |
| dojo.lang.forEach(nodes, function(node){ |
| dojo.html.setOpacity(node, 0.0); |
| }); |
| |
| var anim = dojo.lfx.html.fadeIn(nodes, duration, easing, callback); |
| anim.connect("beforeBegin", function(){ |
| if(dojo.lang.isArrayLike(nodes)){ |
| dojo.lang.forEach(nodes, dojo.html.show); |
| }else{ |
| dojo.html.show(nodes); |
| } |
| }); |
| |
| return anim; // dojo.lfx.Animation |
| } |
| |
| dojo.lfx.html.fadeHide = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){ |
| // summary: Returns an animation that will fade "nodes" from its current opacity to opaque and hides |
| // "nodes" at the end. |
| // nodes: An array of DOMNodes or one DOMNode. |
| // duration: Duration of the animation in milliseconds. |
| // easing: An easing function. |
| // callback: Function to run at the end of the animation. |
| var anim = dojo.lfx.html.fadeOut(nodes, duration, easing, function(){ |
| if(dojo.lang.isArrayLike(nodes)){ |
| dojo.lang.forEach(nodes, dojo.html.hide); |
| }else{ |
| dojo.html.hide(nodes); |
| } |
| if(callback){ callback(nodes, anim); } |
| }); |
| |
| return anim; // dojo.lfx.Animation |
| } |
| |
| dojo.lfx.html.wipeIn = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){ |
| // summary: Returns an animation that will show and wipe in "nodes". |
| // nodes: An array of DOMNodes or one DOMNode. |
| // duration: Duration of the animation in milliseconds. |
| // easing: An easing function. |
| // callback: Function to run at the end of the animation. |
| nodes = dojo.lfx.html._byId(nodes); |
| var anims = []; |
| |
| dojo.lang.forEach(nodes, function(node){ |
| var oprop = { }; // old properties of node (before we mucked w/them) |
| |
| // get node height, either it's natural height or it's height specified via style or class attributes |
| // (for FF, the node has to be (temporarily) rendered to measure height) |
| // TODO: should this offscreen code be part of dojo.html, so that getBorderBox() works on hidden nodes? |
| var origTop, origLeft, origPosition; |
| with(node.style){ |
| origTop=top; origLeft=left; origPosition=position; |
| top="-9999px"; left="-9999px"; position="absolute"; |
| display=""; |
| } |
| var height = dojo.html.getBorderBox(node).height; |
| with(node.style){ |
| top=origTop; left=origLeft; position=origPosition; |
| display="none"; |
| } |
| |
| var anim = dojo.lfx.propertyAnimation(node, |
| { "height": { |
| start: 1, // 0 causes IE to display the whole panel |
| end: function(){ return height; } |
| } |
| }, |
| duration, |
| easing); |
| |
| anim.connect("beforeBegin", function(){ |
| oprop.overflow = node.style.overflow; |
| oprop.height = node.style.height; |
| with(node.style){ |
| overflow = "hidden"; |
| height = "1px"; // 0 causes IE to display the whole panel |
| } |
| dojo.html.show(node); |
| }); |
| |
| anim.connect("onEnd", function(){ |
| with(node.style){ |
| overflow = oprop.overflow; |
| height = oprop.height; |
| } |
| if(callback){ callback(node, anim); } |
| }); |
| anims.push(anim); |
| }); |
| |
| return dojo.lfx.combine(anims); // dojo.lfx.Combine |
| } |
| |
| dojo.lfx.html.wipeOut = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){ |
| // summary: Returns an animation that will wipe out and hide "nodes". |
| // nodes: An array of DOMNodes or one DOMNode. |
| // duration: Duration of the animation in milliseconds. |
| // easing: An easing function. |
| // callback: Function to run at the end of the animation. |
| nodes = dojo.lfx.html._byId(nodes); |
| var anims = []; |
| |
| dojo.lang.forEach(nodes, function(node){ |
| var oprop = { }; // old properties of node (before we mucked w/them) |
| var anim = dojo.lfx.propertyAnimation(node, |
| { "height": { |
| start: function(){ return dojo.html.getContentBox(node).height; }, |
| end: 1 // 0 causes IE to display the whole panel |
| } |
| }, |
| duration, |
| easing, |
| { |
| "beforeBegin": function(){ |
| oprop.overflow = node.style.overflow; |
| oprop.height = node.style.height; |
| with(node.style){ |
| overflow = "hidden"; |
| } |
| dojo.html.show(node); |
| }, |
| |
| "onEnd": function(){ |
| dojo.html.hide(node); |
| with(node.style){ |
| overflow = oprop.overflow; |
| height = oprop.height; |
| } |
| if(callback){ callback(node, anim); } |
| } |
| } |
| ); |
| anims.push(anim); |
| }); |
| |
| return dojo.lfx.combine(anims); // dojo.lfx.Combine |
| } |
| |
| dojo.lfx.html.slideTo = function(/*DOMNode*/ nodes, |
| /*Object*/ coords, |
| /*int?*/ duration, |
| /*Function?*/ easing, |
| /*Function?*/ callback){ |
| // summary: Returns an animation that will slide "nodes" from its current position to |
| // the position defined in "coords". |
| // nodes: An array of DOMNodes or one DOMNode. |
| // coords: { top: Decimal?, left: Decimal? } |
| // duration: Duration of the animation in milliseconds. |
| // easing: An easing function. |
| // callback: Function to run at the end of the animation. |
| nodes = dojo.lfx.html._byId(nodes); |
| var anims = []; |
| var compute = dojo.html.getComputedStyle; |
| |
| if(dojo.lang.isArray(coords)){ |
| /* coords: Array |
| pId: a */ |
| dojo.deprecated('dojo.lfx.html.slideTo(node, array)', 'use dojo.lfx.html.slideTo(node, {top: value, left: value});', '0.5'); |
| coords = { top: coords[0], left: coords[1] }; |
| } |
| dojo.lang.forEach(nodes, function(node){ |
| var top = null; |
| var left = null; |
| |
| var init = (function(){ |
| var innerNode = node; |
| return function(){ |
| var pos = compute(innerNode, 'position'); |
| top = (pos == 'absolute' ? node.offsetTop : parseInt(compute(node, 'top')) || 0); |
| left = (pos == 'absolute' ? node.offsetLeft : parseInt(compute(node, 'left')) || 0); |
| |
| if (!dojo.lang.inArray(['absolute', 'relative'], pos)) { |
| var ret = dojo.html.abs(innerNode, true); |
| dojo.html.setStyleAttributes(innerNode, "position:absolute;top:"+ret.y+"px;left:"+ret.x+"px;"); |
| top = ret.y; |
| left = ret.x; |
| } |
| } |
| })(); |
| init(); |
| |
| var anim = dojo.lfx.propertyAnimation(node, |
| { "top": { start: top, end: (coords.top||0) }, |
| "left": { start: left, end: (coords.left||0) } |
| }, |
| duration, |
| easing, |
| { "beforeBegin": init } |
| ); |
| |
| if(callback){ |
| anim.connect("onEnd", function(){ callback(nodes, anim); }); |
| } |
| |
| anims.push(anim); |
| }); |
| |
| return dojo.lfx.combine(anims); // dojo.lfx.Combine |
| } |
| |
| dojo.lfx.html.slideBy = function(/*DOMNode*/ nodes, /*Object*/ coords, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){ |
| // summary: Returns an animation that will slide "nodes" from its current position |
| // to its current position plus the numbers defined in "coords". |
| // nodes: An array of DOMNodes or one DOMNode. |
| // coords: { top: Decimal?, left: Decimal? } |
| // duration: Duration of the animation in milliseconds. |
| // easing: An easing function. |
| // callback: Function to run at the end of the animation. |
| nodes = dojo.lfx.html._byId(nodes); |
| var anims = []; |
| var compute = dojo.html.getComputedStyle; |
| |
| if(dojo.lang.isArray(coords)){ |
| /* coords: Array |
| pId: a */ |
| dojo.deprecated('dojo.lfx.html.slideBy(node, array)', 'use dojo.lfx.html.slideBy(node, {top: value, left: value});', '0.5'); |
| coords = { top: coords[0], left: coords[1] }; |
| } |
| |
| dojo.lang.forEach(nodes, function(node){ |
| var top = null; |
| var left = null; |
| |
| var init = (function(){ |
| var innerNode = node; |
| return function(){ |
| var pos = compute(innerNode, 'position'); |
| top = (pos == 'absolute' ? node.offsetTop : parseInt(compute(node, 'top')) || 0); |
| left = (pos == 'absolute' ? node.offsetLeft : parseInt(compute(node, 'left')) || 0); |
| |
| if (!dojo.lang.inArray(['absolute', 'relative'], pos)) { |
| var ret = dojo.html.abs(innerNode, true); |
| dojo.html.setStyleAttributes(innerNode, "position:absolute;top:"+ret.y+"px;left:"+ret.x+"px;"); |
| top = ret.y; |
| left = ret.x; |
| } |
| } |
| })(); |
| init(); |
| |
| var anim = dojo.lfx.propertyAnimation(node, |
| { |
| "top": { start: top, end: top+(coords.top||0) }, |
| "left": { start: left, end: left+(coords.left||0) } |
| }, |
| duration, |
| easing).connect("beforeBegin", init); |
| |
| if(callback){ |
| anim.connect("onEnd", function(){ callback(nodes, anim); }); |
| } |
| |
| anims.push(anim); |
| }); |
| |
| return dojo.lfx.combine(anims); // dojo.lfx.Combine |
| } |
| |
| dojo.lfx.html.explode = function(/*DOMNode*/ start, |
| /*DOMNode*/ endNode, |
| /*int?*/ duration, |
| /*Function?*/ easing, |
| /*Function?*/ callback){ |
| // summary: Returns an animation that will |
| // start: |
| // endNode: |
| // duration: Duration of the animation in milliseconds. |
| // easing: An easing function. |
| // callback: Function to run at the end of the animation. |
| var h = dojo.html; |
| start = dojo.byId(start); |
| endNode = dojo.byId(endNode); |
| var startCoords = h.toCoordinateObject(start, true); |
| var outline = document.createElement("div"); |
| h.copyStyle(outline, endNode); |
| if(endNode.explodeClassName){ outline.className = endNode.explodeClassName; } |
| with(outline.style){ |
| position = "absolute"; |
| display = "none"; |
| // border = "1px solid black"; |
| var backgroundStyle = h.getStyle(start, "background-color"); |
| backgroundColor = backgroundStyle ? backgroundStyle.toLowerCase() : "transparent"; |
| backgroundColor = (backgroundColor == "transparent") ? "rgb(221, 221, 221)" : backgroundColor; |
| } |
| dojo.body().appendChild(outline); |
| |
| with(endNode.style){ |
| visibility = "hidden"; |
| display = "block"; |
| } |
| var endCoords = h.toCoordinateObject(endNode, true); |
| with(endNode.style){ |
| display = "none"; |
| visibility = "visible"; |
| } |
| |
| var props = { opacity: { start: 0.5, end: 1.0 } }; |
| dojo.lang.forEach(["height", "width", "top", "left"], function(type){ |
| props[type] = { start: startCoords[type], end: endCoords[type] } |
| }); |
| |
| var anim = new dojo.lfx.propertyAnimation(outline, |
| props, |
| duration, |
| easing, |
| { |
| "beforeBegin": function(){ |
| h.setDisplay(outline, "block"); |
| }, |
| "onEnd": function(){ |
| h.setDisplay(endNode, "block"); |
| outline.parentNode.removeChild(outline); |
| } |
| } |
| ); |
| |
| if(callback){ |
| anim.connect("onEnd", function(){ callback(endNode, anim); }); |
| } |
| return anim; // dojo.lfx.Animation |
| } |
| |
| dojo.lfx.html.implode = function(/*DOMNode*/ startNode, |
| /*DOMNode*/ end, |
| /*int?*/ duration, |
| /*Function?*/ easing, |
| /*Function?*/ callback){ |
| // summary: Returns an animation that will |
| // startNode: |
| // end: |
| // duration: Duration of the animation in milliseconds. |
| // easing: An easing function. |
| // callback: Function to run at the end of the animation. |
| var h = dojo.html; |
| startNode = dojo.byId(startNode); |
| end = dojo.byId(end); |
| var startCoords = dojo.html.toCoordinateObject(startNode, true); |
| var endCoords = dojo.html.toCoordinateObject(end, true); |
| |
| var outline = document.createElement("div"); |
| dojo.html.copyStyle(outline, startNode); |
| if (startNode.explodeClassName) { outline.className = startNode.explodeClassName; } |
| dojo.html.setOpacity(outline, 0.3); |
| with(outline.style){ |
| position = "absolute"; |
| display = "none"; |
| backgroundColor = h.getStyle(startNode, "background-color").toLowerCase(); |
| } |
| dojo.body().appendChild(outline); |
| |
| var props = { opacity: { start: 1.0, end: 0.5 } }; |
| dojo.lang.forEach(["height", "width", "top", "left"], function(type){ |
| props[type] = { start: startCoords[type], end: endCoords[type] } |
| }); |
| |
| var anim = new dojo.lfx.propertyAnimation(outline, |
| props, |
| duration, |
| easing, |
| { |
| "beforeBegin": function(){ |
| dojo.html.hide(startNode); |
| dojo.html.show(outline); |
| }, |
| "onEnd": function(){ |
| outline.parentNode.removeChild(outline); |
| } |
| } |
| ); |
| |
| if(callback){ |
| anim.connect("onEnd", function(){ callback(startNode, anim); }); |
| } |
| return anim; // dojo.lfx.Animation |
| } |
| |
| dojo.lfx.html.highlight = function(/*DOMNode[]*/ nodes, |
| /*dojo.gfx.color.Color*/ startColor, |
| /*int?*/ duration, |
| /*Function?*/ easing, |
| /*Function?*/ callback){ |
| // summary: Returns an animation that will set the background color |
| // of "nodes" to startColor and transition it to "nodes" |
| // original color. |
| // startColor: Color to transition from. |
| // duration: Duration of the animation in milliseconds. |
| // easing: An easing function. |
| // callback: Function to run at the end of the animation. |
| nodes = dojo.lfx.html._byId(nodes); |
| var anims = []; |
| |
| dojo.lang.forEach(nodes, function(node){ |
| var color = dojo.html.getBackgroundColor(node); |
| var bg = dojo.html.getStyle(node, "background-color").toLowerCase(); |
| var bgImage = dojo.html.getStyle(node, "background-image"); |
| var wasTransparent = (bg == "transparent" || bg == "rgba(0, 0, 0, 0)"); |
| while(color.length > 3) { color.pop(); } |
| |
| var rgb = new dojo.gfx.color.Color(startColor); |
| var endRgb = new dojo.gfx.color.Color(color); |
| |
| var anim = dojo.lfx.propertyAnimation(node, |
| { "background-color": { start: rgb, end: endRgb } }, |
| duration, |
| easing, |
| { |
| "beforeBegin": function(){ |
| if(bgImage){ |
| node.style.backgroundImage = "none"; |
| } |
| node.style.backgroundColor = "rgb(" + rgb.toRgb().join(",") + ")"; |
| }, |
| "onEnd": function(){ |
| if(bgImage){ |
| node.style.backgroundImage = bgImage; |
| } |
| if(wasTransparent){ |
| node.style.backgroundColor = "transparent"; |
| } |
| if(callback){ |
| callback(node, anim); |
| } |
| } |
| } |
| ); |
| |
| anims.push(anim); |
| }); |
| return dojo.lfx.combine(anims); // dojo.lfx.Combine |
| } |
| |
| dojo.lfx.html.unhighlight = function(/*DOMNode[]*/ nodes, |
| /*dojo.gfx.color.Color*/ endColor, |
| /*int?*/ duration, |
| /*Function?*/ easing, |
| /*Function?*/ callback){ |
| // summary: Returns an animation that will transition "nodes" background color |
| // from its current color to "endColor". |
| // endColor: Color to transition to. |
| // duration: Duration of the animation in milliseconds. |
| // easing: An easing function. |
| // callback: Function to run at the end of the animation. |
| nodes = dojo.lfx.html._byId(nodes); |
| var anims = []; |
| |
| dojo.lang.forEach(nodes, function(node){ |
| var color = new dojo.gfx.color.Color(dojo.html.getBackgroundColor(node)); |
| var rgb = new dojo.gfx.color.Color(endColor); |
| |
| var bgImage = dojo.html.getStyle(node, "background-image"); |
| |
| var anim = dojo.lfx.propertyAnimation(node, |
| { "background-color": { start: color, end: rgb } }, |
| duration, |
| easing, |
| { |
| "beforeBegin": function(){ |
| if(bgImage){ |
| node.style.backgroundImage = "none"; |
| } |
| node.style.backgroundColor = "rgb(" + color.toRgb().join(",") + ")"; |
| }, |
| "onEnd": function(){ |
| if(callback){ |
| callback(node, anim); |
| } |
| } |
| } |
| ); |
| anims.push(anim); |
| }); |
| return dojo.lfx.combine(anims); // dojo.lfx.Combine |
| } |
| |
| dojo.lang.mixin(dojo.lfx, dojo.lfx.html); |