diff options
Diffstat (limited to 'js/dojo/dojox/fx')
24 files changed, 3182 insertions, 0 deletions
diff --git a/js/dojo/dojox/fx/README b/js/dojo/dojox/fx/README new file mode 100644 index 0000000..edc8891 --- /dev/null +++ b/js/dojo/dojox/fx/README @@ -0,0 +1,75 @@ +------------------------------------------------------------------------------- +dojox.fx +------------------------------------------------------------------------------- +Version 1.0.0 +Release date: 10/31/2007 +------------------------------------------------------------------------------- +Project state: +experimental +------------------------------------------------------------------------------- +Credits + Peter Higgins (dante) + Jonathan Bond-Caron (jbondc@gmail.com) + Shane O'Sullivan (shaneosullivan1@gmail.com) + Bryan Forbes (bforbes) + Nicola Rizzo (nic) + +------------------------------------------------------------------------------- +Project description + + dojox.fx provides a class of animation effects to use, and + other animation and Effects additions to dojo base. + +------------------------------------------------------------------------------- +Dependencies: + + dojox.fx requires dojo (core) and the dojo.fx package + dojox.fx.easing is deprecated, and exists in dojo.fx.easing. + dojox.fx.flip requires dojo.fx + dojox.fx.scroll requires dojox.fx._core and dojo.fx + +------------------------------------------------------------------------------- +Documentation + + existing API surface: + + dojox.fx._base: + - dojox.fx.crossFade - crossfade two nodes easily + - dojox.fx.sizeTo - size a node about it's center to a new width/height + - dojox.fx.slideBy - slide a node by a t,l offset + - dojox.fx.highlight - animates the background color of a node, and returns + it to the color it was. + + (all use standard Animation properties, like duration, easing, node, etc) + + dojox.fx._core: + - dojox.fx._Line - a multi-dimensional _Line implementation, backwards compatible with + dojo._Line ... you might could safely do something akin to + dojo._Line = dojox.fx._Line; + and enable this for all dojo Animations? + + dojox.fx.style: - experimental CSS animation via class definitions + - dojox.fx.addClass - animate the effects of applying a class to a node + - dojox.fx.removeClass - " " " " removing a class from a node + - dojox.fx.toggleClass - wrapper for addClass/removeClass + + dojox.fx.ext-dojo.NodeList - extensions to dojo.NodeList-fx wrapping the + relevant dojox.fx animations into dojo.NodeList + + dojox.fx.Shadow - Class to add drop shadows to a node + + dojox.fx.flip - a Module providing pseudo-3d flip animations for nodes. + Currently experimental. + +------------------------------------------------------------------------------- +Installation instructions + +Grab the following from the Dojo SVN Repository: +http://svn.dojotoolkit.org/dojo/dojox/trunk/fx.js +http://svn.dojotoolkit.org/dojo/dojox/trunk/fx/* + +Install into the following directory structure: +/dojox/fx/ + +...which should be at the same level as your Dojo checkout. +------------------------------------------------------------------------------- diff --git a/js/dojo/dojox/fx/Shadow.js b/js/dojo/dojox/fx/Shadow.js new file mode 100644 index 0000000..ff21df2 --- /dev/null +++ b/js/dojo/dojox/fx/Shadow.js @@ -0,0 +1,147 @@ +//>>built +define("dojox/fx/Shadow", ["dojo/_base/kernel", "dojo/_base/query" ,"dojo/_base/lang", "dojo/_base/declare", "dojo/_base/sniff", + "dojo/dom-construct", "dojo/dom-class", "dojo/dom-geometry", "dojo/_base/fx", "dojo/fx", "dijit/_Widget", + "dojo/NodeList-fx"], + function(kernel, query, lang, declare, has, domConstruct, domClass, domGeom, baseFx, coreFx, Widget, NodeListFx){ +kernel.experimental("dojox.fx.Shadow"); +declare("dojox.fx.Shadow", Widget,{ + // summary: Adds a drop-shadow to a node. + // + // example: + // | // add drop shadows to all nodes with class="hasShadow" + // | dojo.query(".hasShadow").forEach(function(n){ + // | var foo = new dojox.fx.Shadow({ node: n }); + // | foo.startup(); + // | }); + // + // shadowPng: String + // Base location for drop-shadow images + shadowPng: kernel.moduleUrl("dojox.fx", "resources/shadow"), + + // shadowThickness: Integer + // How wide (in px) to make the shadow + shadowThickness: 7, + + // shadowOffset: Integer + // How deep to make the shadow appear to be + shadowOffset: 3, + + // opacity: Float + // Overall opacity of the shadow + opacity: 0.75, + + // animate: Boolean + // A toggle to disable animated transitions + animate: false, + + // node: DomNode + // The node we will be applying this shadow to + node: null, + + startup: function(){ + // summary: Initializes the shadow. + + this.inherited(arguments); + this.node.style.position = "relative"; + // make all the pieces of the shadow, and position/size them as much + // as possible (but a lot of the coordinates are set in sizeShadow + this.pieces={}; + var x1 = -1 * this.shadowThickness; + var y0 = this.shadowOffset; + var y1 = this.shadowOffset + this.shadowThickness; + this._makePiece("tl", "top", y0, "left", x1); + this._makePiece("l", "top", y1, "left", x1, "scale"); + this._makePiece("tr", "top", y0, "left", 0); + this._makePiece("r", "top", y1, "left", 0, "scale"); + this._makePiece("bl", "top", 0, "left", x1); + this._makePiece("b", "top", 0, "left", 0, "crop"); + this._makePiece("br", "top", 0, "left", 0); + + this.nodeList = query(".shadowPiece",this.node); + + this.setOpacity(this.opacity); + this.resize(); + }, + + _makePiece: function(name, vertAttach, vertCoord, horzAttach, horzCoord, sizing){ + // summary: append a shadow pieces to the node, and position it + var img; + var url = this.shadowPng + name.toUpperCase() + ".png"; + if(has("ie") < 7){ + img = domConstruct.create("div"); + img.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+url+"'"+ + (sizing?", sizingMethod='"+sizing+"'":"") + ")"; + }else{ + img = domConstruct.create("img", { src:url }); + } + + img.style.position="absolute"; + img.style[vertAttach]=vertCoord+"px"; + img.style[horzAttach]=horzCoord+"px"; + img.style.width=this.shadowThickness+"px"; + img.style.height=this.shadowThickness+"px"; + domClass.add(img,"shadowPiece"); + this.pieces[name]=img; + this.node.appendChild(img); + + }, + + setOpacity: function(/* Float */n,/* Object? */animArgs){ + // summary: set the opacity of the underlay + // note: does not work in IE? FIXME. + if(has("ie")){ return; } + if(!animArgs){ animArgs = {}; } + if(this.animate){ + var _anims = []; + this.nodeList.forEach(function(node){ + _anims.push(baseFx._fade(lang.mixin(animArgs,{ node: node, end: n }))); + }); + coreFx.combine(_anims).play(); + }else{ + this.nodeList.style("opacity",n); + } + + }, + + setDisabled: function(/* Boolean */disabled){ + // summary: enable / disable the shadow + if(disabled){ + if(this.disabled){ return; } + if(this.animate){ this.nodeList.fadeOut().play(); + }else{ this.nodeList.style("visibility","hidden"); } + this.disabled = true; + }else{ + if(!this.disabled){ return; } + if(this.animate){ this.nodeList.fadeIn().play(); + }else{ this.nodeList.style("visibility","visible"); } + this.disabled = false; + } + }, + + resize: function(/* dojox.fx._arg.ShadowResizeArgs */args){ + // summary: Resizes the shadow based on width and height. + var x; var y; + if(args){ x = args.x; y = args.y; + }else{ + var co = domGeom.position(this.node); + x = co.w; y = co.h; + } + var sideHeight = y - (this.shadowOffset+this.shadowThickness); + if (sideHeight < 0) { sideHeight = 0; } + if (y < 1) { y = 1; } + if (x < 1) { x = 1; } + with(this.pieces){ + l.style.height = sideHeight+"px"; + r.style.height = sideHeight+"px"; + b.style.width = x+"px"; + bl.style.top = y+"px"; + b.style.top = y+"px"; + br.style.top = y+"px"; + tr.style.left = x+"px"; + r.style.left = x+"px"; + br.style.left = x+"px"; + } + } + }); + return dojox.fx.Shadow; +}); diff --git a/js/dojo/dojox/fx/Timeline.js b/js/dojo/dojox/fx/Timeline.js new file mode 100644 index 0000000..f61e330 --- /dev/null +++ b/js/dojo/dojox/fx/Timeline.js @@ -0,0 +1,213 @@ +//>>built +define("dojox/fx/Timeline", ["dojo/_base/lang","dojo/fx/easing","dojo/_base/fx","dojo/dom","./_base","dojo/_base/connect", + "dojo/_base/html", "dojo/_base/array","dojo/_base/Color"], + function(lang, easingUtil, baseFx, dom, dojoxFx, connectUtil, htmlUtil, arrayUtil, Color){ + +dojoxFx.animateTimeline = function(/* Object */options, /* DomNode|String */node){ + // options: Object + // The paramters passed to the timeline animation. Includes: + // keys: Array + // An array of objects, with style properties and values. + // duration: + // Duration of the animation in milliseconds. + // Defaults to 1000. + // node: DomNode + // The DomNode or id to be animated. + // + // summary: + // An add-on to dojo.fx that provides the ability to create + // a complex property animation based on an array of "keyframes". + // description: + // The Timeline is a replacement for the default dojo._Line. + // Instead of _Line.getValue returning a float between 0-1, + // _Timeline.getValue returns an object with all properties and + // their current values. + // A property does not have to appear in every keyframe. + // As in the example below, "height" is transitioned from the first + // keyframe to the third. "width" is transitioned from the first + // to the second to the third. + // Each keyframe can accept the following custom properties: + // step: String + // The start, finish or percentage that this keyframe represents. + // Allowed parameters are: + // 0%-100% + // from (same as 0%, used to conform with the Webkit animation spec) + // to (same as 100%, used to conform with the Webkit animation spec) + // ease: String + // The string name of a dojo.fx.easing ease. Defaults to "linear". Use + // the suffix name of the ease, like: "quadIn", not: "dojo.fx.quadIn". + // + // example: + // | var keys = [ + // | { + // | step:"0px", + // | ease:"quadInOut", + // | width:"50px", + // | height:"50px", + // | },{ + // | step:"25%", + // | width:"190px" + // | },{ + // | step:"100%", + // | width:"10px", + // | height:"200px", + // | } + // | ]; + // | ani = dojox.fx.animateTimeline({keys:keys, duration:2000}, "myDiv").play(); + // + var _curve = new Timeline(options.keys); + var ani = baseFx.animateProperty({ + node:dom.byId(node || options.node), + duration:options.duration || 1000, + properties:_curve._properties, + // don't change! This easing is for the timeline, + // not individual properties + easing:easingUtil.linear, + onAnimate: function(v){ + //console.log(" ani:", v); + } + }); + connectUtil.connect(ani, "onEnd", function(node){ + // Setting the final style. Hiccups in the browser + // can cause the animation to lose track. This ensures + // that it finishes in the proper location. + var sty = ani.curve.getValue(ani.reversed ? 0 : 1); + htmlUtil.style(node, sty); + }); + connectUtil.connect(ani, "beforeBegin", function(){ + // remove default curve and replace it with Timeline + if(ani.curve){ delete ani.curve; } + ani.curve = _curve; + _curve.ani = ani; + }) + return ani; // dojo.Animation +} + +var Timeline = function(/* Array */keys){ + // summary: + // The dojox.fx._Timeline object from which an instance + // is created + // tags: + // private + this.keys = lang.isArray(keys) ? this.flatten(keys) : keys; +} + +Timeline.prototype.flatten = function(keys){ + // summary: + // An internally used function that converts the keyframes + // as used in the example above into a series of key values + // which is what is used in the animation parsing. + var getPercent = function(str, idx){ + if(str == "from"){ return 0; } + if(str == "to"){ return 1; } + if(str === undefined){ + return idx==0 ? 0 : idx / (keys.length - 1) + } + return parseInt(str, 10) * .01 + } + var p = {}, o = {}; + arrayUtil.forEach(keys, function(k, i){ + var step = getPercent(k.step, i); + var ease = easingUtil[k.ease] || easingUtil.linear; + + for(var nm in k){ + if(nm == "step" || nm == "ease" || nm == "from" || nm == "to"){ continue; } + if(!o[nm]){ + o[nm] = { + steps:[], + values:[], + eases:[], + ease:ease + }; + p[nm] = {}; + if(!/#/.test(k[nm])){ + p[nm].units = o[nm].units = /\D{1,}/.exec(k[nm]).join(""); + }else{ + p[nm].units = o[nm].units = "isColor"; + } + } + + o[nm].eases.push(easingUtil[k.ease || "linear"]); + + o[nm].steps.push(step); + if(p[nm].units == "isColor"){ + o[nm].values.push(new Color(k[nm])); + }else{ + o[nm].values.push(parseInt(/\d{1,}/.exec(k[nm]).join(""))); + } + + if(p[nm].start === undefined){ + p[nm].start = o[nm].values[o[nm].values.length-1]; + }else{ + p[nm].end = o[nm].values[o[nm].values.length-1] + } + } + }); + + + this._properties = p; + return o; // Object + +} + +Timeline.prototype.getValue = function(/*float*/ p){ + // summary: + // Replaces the native getValue in dojo.fx.Animation. + // Returns an object with all propeties used in the animation + // and the property's current value + p = this.ani._reversed ? 1-p : p; + var o = {}, self = this; + + var getProp = function(nm, i){ + return self._properties[nm].units!="isColor" ? + self.keys[nm].values[i] + self._properties[nm].units : + self.keys[nm].values[i].toCss(); + } + + for(var nm in this.keys){ + var k = this.keys[nm]; + for(var i=0; i<k.steps.length; i++){ + + var step = k.steps[i]; + var ns = k.steps[i+1]; + var next = i < k.steps.length ? true : false; + var ease = k.eases[i] || function(n){return n;}; + + if(p == step){ + // first or last + o[nm] = getProp(nm, i); + if(!next || (next && this.ani._reversed)) break; + + }else if(p > step){ + + if(next && p < k.steps[i+1]){ + // inbetween steps + var end = k.values[i+1]; + var beg = k.values[i]; + + var seg = (1 / (ns - step)) * (p - step); + seg = ease(seg); + + if(beg instanceof Color){ + o[nm] = Color.blendColors(beg, end, seg).toCss(false); + }else{ + var df = end - beg; + o[nm] = beg + seg * df + this._properties[nm].units; + } + break; + + }else{ + // completed keys before 100% + o[nm] = getProp(nm, i); + } + + }else if((next && !this.ani._reversed) || (!next && this.ani._reversed)){ + o[nm] = getProp(nm, i); + } + } + } + return o; // Object +}; +dojoxFx._Timeline = Timeline; +return dojoxFx; +}); diff --git a/js/dojo/dojox/fx/_arg.js b/js/dojo/dojox/fx/_arg.js new file mode 100644 index 0000000..3d1621d --- /dev/null +++ b/js/dojo/dojox/fx/_arg.js @@ -0,0 +1,26 @@ +//>>built +define("dojox/fx/_arg", ["dojo/_base/lang"],function(lang){ +var fxArg = lang.getObject("dojox.fx._arg",true); +fxArg.StyleArgs = function(/*Object*/ args){ + // summary: + // The node and CSS class to use for style manipulations. + // node: DOMNode + // The node to manipulate + // cssClass: String + // The class to use during the manipulation + this.node = args.node; + this.cssClass = args.cssClass; +} + +fxArg.ShadowResizeArgs = function(/*Object*/ args){ + // summary: + // The odd way to document object parameters. + // x: Integer + // the width to set + // y: Integer + // the height to set + this.x = args.x; + this.y = args.y; +} +return fxArg; +});
\ No newline at end of file diff --git a/js/dojo/dojox/fx/_base.js b/js/dojo/dojox/fx/_base.js new file mode 100644 index 0000000..335b649 --- /dev/null +++ b/js/dojo/dojox/fx/_base.js @@ -0,0 +1,320 @@ +//>>built +define("dojox/fx/_base", ["dojo/_base/array","dojo/_base/lang", "dojo/_base/fx", "dojo/fx", "dojo/dom", "dojo/dom-style", + "dojo/dom-geometry", "dojo/_base/connect", "dojo/_base/html"], + function(arrayUtil, lang, baseFx, coreFx, dom, domStyle, domGeom, connectUtil, htmlUtil){ +// summary: Experimental and extended Animations beyond Dojo Core / Base functionality. +// Provides advanced Lines, Animations, and convenience aliases. +var dojoxFx = lang.getObject("dojox.fx", true); +/* +lang.mixin(dojox.fx, { + + // anim: Function + // Alias of `dojo.anim` - the shorthand `dojo.animateProperty` with auto-play + anim: dojo.fx.anim, + + // animateProperty: Function + // Alias of `dojo.animateProperty` - animate any CSS property + animateProperty: dojox.fx.animateProperty, + + // fadeTo: Function + // Fade an element from an opacity to an opacity. + // Omit `start:` property to detect. `end:` property is required. + // Ultimately an alias to `dojo._fade` + fadeTo: dojo._fade, + + // fadeIn: Function + // Alias of `dojo.fadeIn` - Fade a node in. + fadeIn: dojo.fadeIn, + + // fadeOut: Function + // Alias of `dojo.fadeOut` - Fades a node out. + fadeOut: dojo.fadeOut, + + // combine: Function + // Alias of `dojo.fx.combine` - Run an array of animations in parallel + combine: dojo.fx.combine, + + // chain: Function + // Alias of `dojo.fx.chain` - Run an array of animations in sequence + chain: dojo.fx.chain, + + // slideTo: Function + // Alias of `dojo.fx.slideTo` - Slide a node to a defined top/left coordinate + slideTo: dojo.fx.slideTo, + + // wipeIn: Function + // Alias of `dojo.fx.wipeIn` - Wipe a node to visible + wipeIn: dojo.fx.wipeIn, + + // wipeOut: Function + // Alias of `dojo.fx.wipeOut` - Wipe a node to non-visible + wipeOut: dojo.fx.wipeOut + +}); +*/ + +dojoxFx.sizeTo = function(/* Object */args){ + // summary: + // Creates an animation that will size a node + // + // description: + // Returns an animation that will size the target node + // defined in args Object about it's center to + // a width and height defined by (args.width, args.height), + // supporting an optional method: chain||combine mixin + // (defaults to chain). + // + // - works best on absolutely or relatively positioned elements + // + // example: + // | // size #myNode to 400px x 200px over 1 second + // | dojo.fx.sizeTo({ + // | node:'myNode', + // | duration: 1000, + // | width: 400, + // | height: 200, + // | method: "combine" + // | }).play(); + // + + var node = args.node = dom.byId(args.node), + abs = "absolute"; + + var method = args.method || "chain"; + if(!args.duration){ args.duration = 500; } // default duration needed + if(method == "chain"){ args.duration = Math.floor(args.duration / 2); } + + var top, newTop, left, newLeft, width, height = null; + + var init = (function(n){ + return function(){ + var cs = domStyle.getComputedStyle(n), + pos = cs.position, + w = cs.width, + h = cs.height + ; + + top = (pos == abs ? n.offsetTop : parseInt(cs.top) || 0); + left = (pos == abs ? n.offsetLeft : parseInt(cs.left) || 0); + width = (w == "auto" ? 0 : parseInt(w)); + height = (h == "auto" ? 0 : parseInt(h)); + + newLeft = left - Math.floor((args.width - width) / 2); + newTop = top - Math.floor((args.height - height) / 2); + + if(pos != abs && pos != 'relative'){ + var ret = domStyle.coords(n, true); + top = ret.y; + left = ret.x; + n.style.position = abs; + n.style.top = top + "px"; + n.style.left = left + "px"; + } + } + })(node); + + var anim1 = baseFx.animateProperty(lang.mixin({ + properties: { + height: function(){ + init(); + return { end: args.height || 0, start: height }; + }, + top: function(){ + return { start: top, end: newTop }; + } + } + }, args)); + var anim2 = baseFx.animateProperty(lang.mixin({ + properties: { + width: function(){ + return { start: width, end: args.width || 0 } + }, + left: function(){ + return { start: left, end: newLeft } + } + } + }, args)); + + var anim = coreFx[(args.method == "combine" ? "combine" : "chain")]([anim1, anim2]); + return anim; // dojo.Animation + +}; + +dojoxFx.slideBy = function(/* Object */args){ + // summary: + // Returns an animation to slide a node by a defined offset. + // + // description: + // Returns an animation that will slide a node (args.node) from it's + // current position to it's current posision plus the numbers defined + // in args.top and args.left. standard dojo.fx mixin's apply. + // + // example: + // | // slide domNode 50px down, and 22px left + // | dojox.fx.slideBy({ + // | node: domNode, duration:400, + // | top: 50, left: -22 + // | }).play(); + + var node = args.node = dom.byId(args.node), + top, left; + + var init = (function(n){ + return function(){ + var cs = domStyle.getComputedStyle(n); + var pos = cs.position; + top = (pos == 'absolute' ? n.offsetTop : parseInt(cs.top) || 0); + left = (pos == 'absolute' ? n.offsetLeft : parseInt(cs.left) || 0); + if(pos != 'absolute' && pos != 'relative'){ + var ret = domGeom.coords(n, true); + top = ret.y; + left = ret.x; + n.style.position = "absolute"; + n.style.top = top + "px"; + n.style.left = left + "px"; + } + } + })(node); + init(); + + var _anim = baseFx.animateProperty(lang.mixin({ + properties: { + // FIXME: is there a way to update the _Line after creation? + // null start values allow chaining to work, animateProperty will + // determine them for us (except in ie6? -- ugh) + top: top + (args.top || 0), + left: left + (args.left || 0) + } + }, args)); + connectUtil.connect(_anim, "beforeBegin", _anim, init); + return _anim; // dojo.Animation +}; + +dojoxFx.crossFade = function(/* Object */args){ + // summary: + // Returns an animation cross fading two element simultaneously + // + // args: + // args.nodes: Array - two element array of domNodes, or id's + // + // all other standard animation args mixins apply. args.node ignored. + // + + // simple check for which node is visible, maybe too simple? + var node1 = args.nodes[0] = dom.byId(args.nodes[0]), + op1 = htmlUtil.style(node1,"opacity"), + node2 = args.nodes[1] = dom.byId(args.nodes[1]), + op2 = htmlUtil.style(node2, "opacity") + ; + + var _anim = coreFx.combine([ + baseFx[(op1 == 0 ? "fadeIn" : "fadeOut")](lang.mixin({ + node: node1 + },args)), + baseFx[(op1 == 0 ? "fadeOut" : "fadeIn")](lang.mixin({ + node: node2 + },args)) + ]); + return _anim; // dojo.Animation +}; + +dojoxFx.highlight = function(/*Object*/ args){ + // summary: + // Highlight a node + // + // description: + // Returns an animation that sets the node background to args.color + // then gradually fades back the original node background color + // + // example: + // | dojox.fx.highlight({ node:"foo" }).play(); + + var node = args.node = dom.byId(args.node); + + args.duration = args.duration || 400; + + // Assign default color light yellow + var startColor = args.color || '#ffff99', + endColor = htmlUtil.style(node, "backgroundColor") + ; + + // safari "fix" + // safari reports rgba(0, 0, 0, 0) (black) as transparent color, while + // other browsers return "transparent", rendered as white by default by + // dojo.Color; now dojo.Color maps "transparent" to + // djConfig.transparentColor ([r, g, b]), if present; so we can use + // the color behind the effect node + if(endColor == "rgba(0, 0, 0, 0)"){ + endColor = "transparent"; + } + + var anim = baseFx.animateProperty(lang.mixin({ + properties: { + backgroundColor: { start: startColor, end: endColor } + } + }, args)); + + if(endColor == "transparent"){ + connectUtil.connect(anim, "onEnd", anim, function(){ + node.style.backgroundColor = endColor; + }); + } + + return anim; // dojo.Animation +}; + + +dojoxFx.wipeTo = function(/*Object*/ args){ + // summary: + // Animate a node wiping to a specific width or height + // + // description: + // Returns an animation that will expand the + // node defined in 'args' object from it's current to + // the height or width value given by the args object. + // + // default to height:, so leave height null and specify width: + // to wipeTo a width. note: this may be deprecated by a + // + // Note that the final value should not include + // units and should be an integer. Thus a valid args object + // would look something like this: + // + // | dojox.fx.wipeTo({ node: "nodeId", height: 200 }).play(); + // + // Node must have no margin/border/padding, so put another + // node inside your target node for additional styling. + + args.node = dom.byId(args.node); + var node = args.node, s = node.style; + + var dir = (args.width ? "width" : "height"), + endVal = args[dir], + props = {} + ; + + props[dir] = { + // wrapped in functions so we wait till the last second to query (in case value has changed) + start: function(){ + // start at current [computed] height, but use 1px rather than 0 + // because 0 causes IE to display the whole panel + s.overflow = "hidden"; + if(s.visibility == "hidden" || s.display == "none"){ + s[dir] = "1px"; + s.display = ""; + s.visibility = ""; + return 1; + }else{ + var now = htmlUtil.style(node,dir); + return Math.max(now, 1); + } + }, + end: endVal + }; + + var anim = baseFx.animateProperty(lang.mixin({ properties: props }, args)); + return anim; // dojo.Animation +}; + +return dojoxFx; +}); diff --git a/js/dojo/dojox/fx/_core.js b/js/dojo/dojox/fx/_core.js new file mode 100644 index 0000000..5e3a4bf --- /dev/null +++ b/js/dojo/dojox/fx/_core.js @@ -0,0 +1,63 @@ +//>>built +define("dojox/fx/_core", ["dojo/_base/lang", "dojo/_base/array","./_base"], + function(lang, arrayUtil, dojoxFx){ + /*===== var dojox.fx._Line = line =====*/ + var line = function(start, end){ + // summary: a custom _Line to accomodate multi-dimensional values + // + // description: + // a normal dojo._Line is the curve, and does Line(start,end) + // for propertyAnimation. as we make more complicatied animations, we realize + // some properties can have 2, or 4 values relevant (x,y) or (t,l,r,b) for example + // + // this function provides support for those Lines, and is ported directly from 0.4 + // this is a lot of extra code for something so seldom used, so we'll put it here as + // and optional core addition. you can create a new line, and use it during onAnimate + // as you see fit. + // + // start: Integer|Array + // An Integer (or an Array of integers) to use as a starting point + // end: Integer|Array + // An Integer (or an Array of integers) to use as an ending point + // + // example: see dojox.fx.smoothScroll + // + // example: + // | // this is 10 .. 100 and 50 .. 500 + // | var curve = new dojox.fx._Line([10,50],[100,500]); + // | // dojo.Animation.onAnimate is called at every step of the animation + // | // to define current values. this _Line returns an array + // | // at each step. arguments[0] and [1] in this example. + // + this.start = start; + this.end = end; + + var isArray = lang.isArray(start), + d = (isArray ? [] : end - start); + + if(isArray){ + // multi-dimensional branch + arrayUtil.forEach(this.start, function(s, i){ + d[i] = this.end[i] - s; + }, this); + + this.getValue = function(/*float*/ n){ + var res = []; + arrayUtil.forEach(this.start, function(s, i){ + res[i] = (d[i] * n) + s; + }, this); + return res; // Array + } + }else{ + // single value branch, document here for both branches: + this.getValue = function(/*float*/ n){ + // summary: Returns the point on the line, or an array of points + // n: a floating point number greater than 0 and less than 1 + // returns: Mixed + return (d * n) + this.start; // Decimal + } + } + }; + dojoxFx._Line = line; // COMPAT + return line; +}); diff --git a/js/dojo/dojox/fx/easing.js b/js/dojo/dojox/fx/easing.js new file mode 100644 index 0000000..65c7969 --- /dev/null +++ b/js/dojo/dojox/fx/easing.js @@ -0,0 +1,14 @@ +//>>built +define("dojox/fx/easing", ["dojo/_base/lang", "dojo/_base/kernel", "dojo/fx/easing"], + function(lang,kernel,easing){ + kernel.deprecated("dojox.fx.easing","Upgraded to Core, use dojo.fx.easing instead","2.0"); + var fxExt = lang.getObject("dojox.fx",true); + fxExt.easing = easing; +/*===== + dojox.fx.easing = { + // summary: + // An Alias to `dojo.fx.easing`. Moved to Core in Dojo 1.2. + }; +=====*/ + return easing; +}); diff --git a/js/dojo/dojox/fx/ext-dojo/NodeList-style.js b/js/dojo/dojox/fx/ext-dojo/NodeList-style.js new file mode 100644 index 0000000..10f4442 --- /dev/null +++ b/js/dojo/dojox/fx/ext-dojo/NodeList-style.js @@ -0,0 +1,62 @@ +//>>built +define("dojox/fx/ext-dojo/NodeList-style", ["dojo/_base/lang", "dojo/_base/NodeList","dojo/NodeList-fx", "dojo/fx", "../style"], + function(lang, NodeList, NodeListFx, coreFx, styleX){ +// summary: +// Core extensions to `dojo.NodeList` providing additional fx to `dojo.NodeList-fx` +// from `dojox.fx.style` +// +// description: +// A Package to extend dojo base NodeList with fx provided by the `dojox.fx` project. +// These are experimental animations, in an experimental + + +lang.extend( NodeList, { + + addClassFx: function(cssClass, args){ + // summary: + // Animate the effects of adding a class to all nodes in this list. + // see `dojox.fx.addClass` + // + // tags: FX, NodeList + // + // example: + // | // fade all elements with class "bar" to to 50% opacity + // | dojo.query(".bar").addClassFx("bar").play(); + + return coreFx.combine(this.map(function(n){ // dojo.Animation + return styleX.addClass(n, cssClass, args); + })); + }, + + removeClassFx: function(cssClass, args){ + // summary: + // Animate the effect of removing a class to all nodes in this list. + // see `dojox.fx.removeClass` + // + // tags: FX, NodeList + // + // example: + // | dojo.query(".box").removeClassFx("bar").play(); + + return coreFx.combine(this.map(function(n){ // dojo.Animation + return styleX.removeClass(n, cssClass, args); + })); + }, + + toggleClassFx: function(cssClass, force, args){ + // summary: + // Animate the effect of adding or removing a class to all nodes in this list. + // see `dojox.fx.toggleClass` + // + // tags: FX, NodeList + // + // example: + // | dojo.query(".box").toggleClass("bar").play(); + + return coreFx.combine(this.map(function(n){ // dojo.Animation + return styleX.toggleClass(n, cssClass, force, args); + })); + } +}); +return NodeList; +}); diff --git a/js/dojo/dojox/fx/ext-dojo/NodeList.js b/js/dojo/dojox/fx/ext-dojo/NodeList.js new file mode 100644 index 0000000..7e4209c --- /dev/null +++ b/js/dojo/dojox/fx/ext-dojo/NodeList.js @@ -0,0 +1,63 @@ +//>>built +define("dojox/fx/ext-dojo/NodeList", ["dojo/_base/kernel", "dojo/_base/lang", "dojo/_base/fx", "dojox/fx","dojo/NodeList-fx"], + function(kernel, lang, baseFx, CoreFx, NodeList){ +kernel.experimental("dojox.fx.ext-dojo.NodeList"); +// summary: Core extensions to dojo.NodeList providing addtional fx to dojo.NodeList-fx +// description: +// A Package to extend dojo base NodeList with fx provided by the dojox.fx project. +// These are experimental animations, in an experimental + +lang.extend(NodeList, { + + sizeTo: function(args){ + // summary: + // size all elements of this NodeList. Returns an instance of dojo.Animation + // example: + // | // size all divs with class "blah" + // | dojo.query("div.blah").sizeTo({ + // | width:50, + // | height:50 + // | }).play(); + return this._anim(CoreFx, "sizeTo", args); // dojo.Animation + }, + + slideBy: function(args){ + // summary: + // slide all elements of this NodeList. Returns an instance of dojo.Animation + // + // example: + // | // slide all tables with class "blah" 10 px + // | dojo.query("table.blah").slideBy({ top:10, left:10 }).play(); + return this._anim(CoreFx, "slideBy", args); // dojo.Animation + }, + + highlight: function(args){ + // summary: + // highlight all elements of the node list. + // Returns an instance of dojo.Animation + // example: + // | // highlight all links with class "foo" + // | dojo.query("a.foo").hightlight().play(); + return this._anim(CoreFx, "highlight", args); // dojo.Animation + }, + + fadeTo: function(args){ + // summary: + // fade all elements of the node list to a specified opacity + // example: + // | // fade all elements with class "bar" to to 50% opacity + // | dojo.query(".bar").fadeTo({ end: 0.5 }).play(); + return this._anim(baseFx,"_fade",args); + }, + + wipeTo: function(args){ + // summary: + // Wipe all elements of the NodeList to a specified width: or height: + // example: + // | dojo.query(".box").wipeTo({ width: 300px }).play(); + return this._anim(CoreFx, "wipeTo", args); + } + +}); +return NodeList; +}); diff --git a/js/dojo/dojox/fx/ext-dojo/complex.js b/js/dojo/dojox/fx/ext-dojo/complex.js new file mode 100644 index 0000000..e7ab677 --- /dev/null +++ b/js/dojo/dojox/fx/ext-dojo/complex.js @@ -0,0 +1,170 @@ +//>>built +define("dojox/fx/ext-dojo/complex", ["dojo/_base/kernel", "dojo/_base/lang", "dojo/_base/array","dojo/_base/declare", "dojo/_base/connect", + "dojo/_base/Color", "dojo/_base/fx", "dojo/fx"], + function(dojo, lang, arrayUtil, declare, connectUtil, Color, baseFx, coreFx){ + lang.getObject("dojox.fx.ext-dojo.complex", true); + + var da = baseFx.animateProperty; + dojo.animateProperty = baseFx.animateProperty = function(options){ + // summary: + // An extension of dojo.animateProperty which adds functionality + // that animates a "complex property". The primary example is the + // clip style: rect(10px 30px 10px 50px). + // Note this can also be used with (and is actually intended for) + // CSS3 properties, such as transform: + // transform: rotate(10deg) translateX(0px) + // + // description: + // The standard animation doesn't know what to do with something like + // rect(...). This class identifies complex properties by they being a + // string and having parenthesis. If so, that property is made into a + // dojox.fx._Complex object and the getValue() is obtained from + // there. + // + // example: + // | var ani = dojo.animateProperty({ + // | node:dojo.byId("myDiv"), + // | duration:600, + // | properties:{ + // | clip:{start:'rect(0px 50px 50px 0px)', end:'rect(10px 30px 30px 10px)'} + // | } + // | }).play(); + // + var d = dojo; + var ani = da(options); + + connectUtil.connect(ani, "beforeBegin", function(){ + // dojo.Animate original still invokes and still + // works. We're appending this functionality to + // modify targeted properties. + ani.curve.getValue = function(r){ + // Overwriting dojo.Animate's curve.getValue + // This is mostly duplicate code, except it looks + // for an instance of dojox.fx._Complex. + var ret = {}; + for(var p in this._properties){ + var prop = this._properties[p], + start = prop.start; + if(start instanceof d.Color){ + ret[p] = d.blendColors(start, prop.end, r, prop.tempColor).toCss(); + }else if(start instanceof dojox.fx._Complex){ + ret[p] = start.getValue(r); + }else if(!d.isArray(start)){ + ret[p] = ((prop.end - start) * r) + start + (p != "opacity" ? prop.units || "px" : 0); + } + } + return ret; + }; + + // this.properties has already been set, as has this.curve._properties. + // We're fixing the props in curve which will have NaN attributes from + // our string property. + var pm = {}; + for(var p in this.properties){ + var o = this.properties[p]; + if(typeof(o.start) == "string" && /\(/.test(o.start)){ + this.curve._properties[p].start = new dojox.fx._Complex(o); + } + } + + }); + return ani; // dojo.Animation + } + + return declare("dojox.fx._Complex", null, { + // summary: + // A class that takes a complex property such as + // clip style: rect(10px 30px 10px 50px), and breaks it + // into seperate animatable units. The object has a getValue() + // that will return a string with the modified units. + // + PROP: /\([\w|,|+|\-|#|\.|\s]*\)/g, + constructor: function(options){ + var beg = options.start.match(this.PROP); + var end = options.end.match(this.PROP); + + var begProps = arrayUtil.map(beg, this.getProps, this); + var endProps = arrayUtil.map(end, this.getProps, this); + + this._properties = {}; + this.strProp = options.start; + arrayUtil.forEach(begProps, function(prop, i){ + arrayUtil.forEach(prop, function(p, j){ + this.strProp = this.strProp.replace(p, "PROP_"+i+""+j); + this._properties["PROP_"+i+""+j] = this.makePropObject(p, endProps[i][j]) + },this); + },this); + }, + + getValue: function(/*Float*/r){ + // summary: + // Returns a string with teh same integrity as the + // original star and end, but with the modified units. + var str = this.strProp, u; + for(var nm in this._properties){ + var v, o = this._properties[nm]; + if(o.units == "isColor"){ + v = Color.blendColors(o.beg, o.end, r).toCss(false); + u = ""; + }else{ + v = ((o.end - o.beg) * r) + o.beg; + u = o.units; + } + str = str.replace(nm, v + u); + } + + return str; // String + }, + + makePropObject: function(/* String */beg, /* String */end){ + // summary: + // Returns an object that stores the numeric value and + // units of the beggining and ending properties. + // + var b = this.getNumAndUnits(beg); + var e = this.getNumAndUnits(end); + return { + beg:b.num, + end:e.num, + units:b.units + }; // Object + }, + + getProps: function(/* String */str){ + // summary: + // Helper function that splits a stringified set of properties + // into individual units. + // + str = str.substring(1, str.length-1); + var s; + if(/,/.test(str)){ + str = str.replace(/\s/g, ""); + s = str.split(","); + }else{ + str = str.replace(/\s{2,}/g, " "); + s = str.split(" "); + } + return s; // String + }, + getNumAndUnits: function(prop){ + // summary: + // Helper function that returns the numeric verion of the string + // property (or dojo.Color object) and the unit in which it was + // defined. + // + if(!prop){ return {}; } + if(/#/.test(prop)){ + return { + num: new Color(prop), + units:"isColor" + }; // Object + } + var o = { + num:parseFloat(/-*[\d\.\d|\d]{1,}/.exec(prop).join("")) + }; + o.units = /[a-z]{1,}/.exec(prop);//.join(""); + o.units = o.units && o.units.length ? o.units.join("") : ""; + return o; // Object + } + }); +}); diff --git a/js/dojo/dojox/fx/ext-dojo/reverse.js b/js/dojo/dojox/fx/ext-dojo/reverse.js new file mode 100644 index 0000000..a3bb852 --- /dev/null +++ b/js/dojo/dojox/fx/ext-dojo/reverse.js @@ -0,0 +1,104 @@ +//>>built +define("dojox/fx/ext-dojo/reverse", ["dojo/_base/fx", + "dojo/fx", + "dojo/_base/lang", + "dojo/fx/easing", + "dojox/fx"], + function(baseFx, coreFx, lang, easingUtil, dojoxFx){ // +/*===== var dojox.fx.ext-dojo.=====*/ +var reverseApi = { + // summary: + // A dojo.Animation extension that enables an easy reversal. + // description: + // To use, simply require dojox.fx.ext-dojo.reverse and a reverse() + // method will be added to all dojo.Animations. + // It can be used at any time during the animation. It does not + // need to be called when it ends. It also reverses the easing - + // if dojo.fx.easing.quadIn is used, dojo.fx.easing.quadOut will + // be used when animating backwards. + // + _reversed: false, + reverse: function(/*Boolean*/keepPaused, /*Function ? */reverseEase){ + // summary: + // The key method added to an animation to enable reversal. + // keepPaused: Boolean + // By default, calling reverse() will play the animation if + // it was paused. Pass in true to keep it paused (will have + // no effect if reverse is called while animation is playing). + // reverseEase: Function + // A function to use for the reverse easing. This allows for + // the possibility of custom eases that are not in the dojo.fx + // library. + // + var playing = this.status() == "playing"; + this.pause(); + this._reversed = !this._reversed; + var d = this.duration, + sofar = d * this._percent, + togo = d - sofar, + curr = new Date().valueOf(), + cp = this.curve._properties, + p = this.properties, + nm + ; + this._endTime = curr + sofar; + this._startTime = curr - togo; + + if(playing){ + this.gotoPercent(togo / d) + } + for(nm in p){ + var tmp = p[nm].start; + p[nm].start = cp[nm].start = p[nm].end; + p[nm].end = cp[nm].end = tmp; + } + + if(this._reversed){ + if(!this.rEase){ + this.fEase = this.easing; + if(reverseEase){ + this.rEase = reverseEase; + }else{ + // loop through dojo.fx.easing to find the matching ease + var de = easingUtil, found, eName; + for(nm in de){ + if(this.easing == de[nm]){ + // get ease's name + found = nm; break; + } + } + + if(found){ + // find ease's opposite + if(/InOut/.test(nm) || !/In|Out/i.test(nm)){ + this.rEase = this.easing; + }else if(/In/.test(nm)){ + eName = nm.replace("In", "Out"); + }else{ + eName = nm.replace("Out", "In"); + } + if(eName){ + this.rEase = easingUtil[eName]; + } + }else{ + // default ease, and other's like linear do not have an opposite + console.info("ease function to reverse not found"); + this.rEase = this.easing; + } + } + + } + this.easing = this.rEase; + }else{ + this.easing = this.fEase; + } + if(!keepPaused && this.status() != "playing"){ + this.play(); + } + + return this; + } +}; +lang.extend( baseFx.Animation, reverseApi); +return baseFx.Animation; +});
\ No newline at end of file diff --git a/js/dojo/dojox/fx/flip.js b/js/dojo/dojox/fx/flip.js new file mode 100644 index 0000000..501fdab --- /dev/null +++ b/js/dojo/dojox/fx/flip.js @@ -0,0 +1,518 @@ +//>>built +define("dojox/fx/flip", [ + "dojo/_base/kernel", + "dojo/_base/html", + "dojo/dom", + "dojo/dom-construct", + "dojo/dom-geometry", + "dojo/_base/connect", + "dojo/_base/Color", + "dojo/_base/sniff", + "dojo/_base/lang", + "dojo/_base/window", + "dojo/_base/fx", + "dojo/fx", + "./_base" +], function(kernel, htmlUtil, dom, domConstruct, domGeom, connectUtil, Color, has, lang, winUtil, baseFx, coreFx, fxExt) { +//kernel,lang->(sniff,array,has),sniff,unload,window + + kernel.experimental("dojox.fx.flip"); + // because ShrinkSafe will eat this up: + var borderConst = "border", + widthConst = "Width", + heightConst = "Height", + topConst = "Top", + rightConst = "Right", + leftConst = "Left", + bottomConst = "Bottom" + ; + + fxExt.flip = function(/*Object*/ args){ + // summary: Animate a node flipping following a specific direction + // + // description: + // Returns an animation that will flip the + // node around a central axis: + // if args.dir is "left" or "right" --> y axis + // if args.dir is "top" or "bottom" --> x axis + // + // This effect is obtained using a border distorsion applied to a helper node. + // + // The user can specify three background colors for the helper node: + // darkColor: the darkest color reached during the animation + // lightColor: the brightest color + // endColor: the final backgroundColor for the node + // + // depth: Float + // 0 <= depth <= 1 overrides the computed "depth" + // (0: min distorsion, 1: max distorsion) + // + // whichAnim: String + // "first" : the first half animation + // "last" : the second one + // "both" (default) : both + // + // axis: String + // "center" (default) : the node is flipped around his center + // "shortside" : the node is flipped around his "short" (in perspective) side + // "longside" : the node is flipped around his "long" (in perspective) side + // "cube" : the node flips around the central axis of the cube + // + // shift: Integer + // node translation, perpendicular to the rotation axis + // + // example: + // | var anim = dojox.fx.flip({ + // | node: dojo.byId("nodeId"), + // | dir: "top", + // | darkColor: "#555555", + // | lightColor: "#dddddd", + // | endColor: "#666666", + // | depth: .5, + // | shift: 50, + // | duration:300 + // | }); + + var helperNode = domConstruct.create("div"), + node = args.node = dom.byId(args.node), + s = node.style, + dims = null, + hs = null, + pn = null, + lightColor = args.lightColor || "#dddddd", + darkColor = args.darkColor || "#555555", + bgColor = htmlUtil.style(node, "backgroundColor"), + endColor = args.endColor || bgColor, + staticProps = {}, + anims = [], + duration = args.duration ? args.duration / 2 : 250, + dir = args.dir || "left", + pConst = .9, + transparentColor = "transparent", + whichAnim = args.whichAnim, + axis = args.axis || "center", + depth = args.depth + ; + // IE6 workaround: IE6 doesn't support transparent borders + var convertColor = function(color){ + return ((new Color(color)).toHex() === "#000000") ? "#000001" : color; + }; + + if(has("ie") < 7){ + endColor = convertColor(endColor); + lightColor = convertColor(lightColor); + darkColor = convertColor(darkColor); + bgColor = convertColor(bgColor); + transparentColor = "black"; + helperNode.style.filter = "chroma(color='#000000')"; + } + + var init = (function(n){ + return function(){ + var ret = htmlUtil.coords(n, true); + dims = { + top: ret.y, + left: ret.x, + width: ret.w, + height: ret.h + }; + } + })(node); + init(); + // helperNode initialization + hs = { + position: "absolute", + top: dims["top"] + "px", + left: dims["left"] + "px", + height: "0", + width: "0", + zIndex: args.zIndex || (s.zIndex || 0), + border: "0 solid " + transparentColor, + fontSize: "0", + visibility: "hidden" + }; + var props = [ {}, + { + top: dims["top"], + left: dims["left"] + } + ]; + var dynProperties = { + left: [leftConst, rightConst, topConst, bottomConst, widthConst, heightConst, "end" + heightConst + "Min", leftConst, "end" + heightConst + "Max"], + right: [rightConst, leftConst, topConst, bottomConst, widthConst, heightConst, "end" + heightConst + "Min", leftConst, "end" + heightConst + "Max"], + top: [topConst, bottomConst, leftConst, rightConst, heightConst, widthConst, "end" + widthConst + "Min", topConst, "end" + widthConst + "Max"], + bottom: [bottomConst, topConst, leftConst, rightConst, heightConst, widthConst, "end" + widthConst + "Min", topConst, "end" + widthConst + "Max"] + }; + // property names + pn = dynProperties[dir]; + + // .4 <= pConst <= .9 + if(typeof depth != "undefined"){ + depth = Math.max(0, Math.min(1, depth)) / 2; + pConst = .4 + (.5 - depth); + }else{ + pConst = Math.min(.9, Math.max(.4, dims[pn[5].toLowerCase()] / dims[pn[4].toLowerCase()])); + } + var p0 = props[0]; + for(var i = 4; i < 6; i++){ + if(axis == "center" || axis == "cube"){ // find a better name for "cube" + dims["end" + pn[i] + "Min"] = dims[pn[i].toLowerCase()] * pConst; + dims["end" + pn[i] + "Max"] = dims[pn[i].toLowerCase()] / pConst; + }else if(axis == "shortside"){ + dims["end" + pn[i] + "Min"] = dims[pn[i].toLowerCase()]; + dims["end" + pn[i] + "Max"] = dims[pn[i].toLowerCase()] / pConst; + }else if(axis == "longside"){ + dims["end" + pn[i] + "Min"] = dims[pn[i].toLowerCase()] * pConst; + dims["end" + pn[i] + "Max"] = dims[pn[i].toLowerCase()]; + } + } + if(axis == "center"){ + p0[pn[2].toLowerCase()] = dims[pn[2].toLowerCase()] - (dims[pn[8]] - dims[pn[6]]) / 4; + }else if(axis == "shortside"){ + p0[pn[2].toLowerCase()] = dims[pn[2].toLowerCase()] - (dims[pn[8]] - dims[pn[6]]) / 2; + } + + staticProps[pn[5].toLowerCase()] = dims[pn[5].toLowerCase()] + "px"; + staticProps[pn[4].toLowerCase()] = "0"; + staticProps[borderConst + pn[1] + widthConst] = dims[pn[4].toLowerCase()] + "px"; + staticProps[borderConst + pn[1] + "Color"] = bgColor; + + p0[borderConst + pn[1] + widthConst] = 0; + p0[borderConst + pn[1] + "Color"] = darkColor; + p0[borderConst + pn[2] + widthConst] = p0[borderConst + pn[3] + widthConst] = axis != "cube" + ? (dims["end" + pn[5] + "Max"] - dims["end" + pn[5] + "Min"]) / 2 + : dims[pn[6]] / 2 + ; + p0[pn[7].toLowerCase()] = dims[pn[7].toLowerCase()] + dims[pn[4].toLowerCase()] / 2 + (args.shift || 0); + p0[pn[5].toLowerCase()] = dims[pn[6]]; + + var p1 = props[1]; + p1[borderConst + pn[0] + "Color"] = { start: lightColor, end: endColor }; + p1[borderConst + pn[0] + widthConst] = dims[pn[4].toLowerCase()]; + p1[borderConst + pn[2] + widthConst] = 0; + p1[borderConst + pn[3] + widthConst] = 0; + p1[pn[5].toLowerCase()] = { start: dims[pn[6]], end: dims[pn[5].toLowerCase()] }; + + lang.mixin(hs, staticProps); + htmlUtil.style(helperNode, hs); + winUtil.body().appendChild(helperNode); + + var finalize = function(){ +// helperNode.parentNode.removeChild(helperNode); + domConstruct.destroy(helperNode); + // fixes a flicker when the animation ends + s.backgroundColor = endColor; + s.visibility = "visible"; + }; + if(whichAnim == "last"){ + for(i in p0){ + p0[i] = { start: p0[i] }; + } + p0[borderConst + pn[1] + "Color"] = { start: darkColor, end: endColor }; + p1 = p0; + } + if(!whichAnim || whichAnim == "first"){ + anims.push(baseFx.animateProperty({ + node: helperNode, + duration: duration, + properties: p0 + })); + } + if(!whichAnim || whichAnim == "last"){ + anims.push(baseFx.animateProperty({ + node: helperNode, + duration: duration, + properties: p1, + onEnd: finalize + })); + } + + // hide the original node + connectUtil.connect(anims[0], "play", function(){ + helperNode.style.visibility = "visible"; + s.visibility = "hidden"; + }); + + return coreFx.chain(anims); // dojo.Animation + + } + + fxExt.flipCube = function(/*Object*/ args){ + // summary: An extension to `dojox.fx.flip` providing a more 3d-like rotation + // + // description: + // An extension to `dojox.fx.flip` providing a more 3d-like rotation. + // Behaves the same as `dojox.fx.flip`, using the same attributes and + // other standard `dojo.Animation` properties. + // + // example: + // See `dojox.fx.flip` + var anims = [], + mb = domGeom.getMarginBox(args.node), + shiftX = mb.w / 2, + shiftY = mb.h / 2, + dims = { + top: { + pName: "height", + args:[ + { + whichAnim: "first", + dir: "top", + shift: -shiftY + }, + { + whichAnim: "last", + dir: "bottom", + shift: shiftY + } + ] + }, + right: { + pName: "width", + args:[ + { + whichAnim: "first", + dir: "right", + shift: shiftX + }, + { + whichAnim: "last", + dir: "left", + shift: -shiftX + } + ] + }, + bottom: { + pName: "height", + args:[ + { + whichAnim: "first", + dir: "bottom", + shift: shiftY + }, + { + whichAnim: "last", + dir: "top", + shift: -shiftY + } + ] + }, + left: { + pName: "width", + args:[ + { + whichAnim: "first", + dir: "left", + shift: -shiftX + }, + { + whichAnim: "last", + dir: "right", + shift: shiftX + } + ] + } + } + ; + var d = dims[args.dir || "left"], + p = d.args + ; + args.duration = args.duration ? args.duration * 2 : 500; + args.depth = .8; + args.axis = "cube"; + for(var i = p.length - 1; i >= 0; i--){ + lang.mixin(args, p[i]); + anims.push(fxExt.flip(args)); + } + return coreFx.combine(anims); + }; + + fxExt.flipPage = function(/*Object*/ args){ + // summary: An extension to `dojox.fx.flip` providing a page flip like animation. + // + // description: + // An extension to `dojox.fx.flip` providing a page flip effect. + // Behaves the same as `dojox.fx.flip`, using the same attributes and + // other standard `dojo.Animation` properties. + // + // example: + // See `dojox.fx.flip` + var n = args.node, + coords = htmlUtil.coords(n, true), + x = coords.x, + y = coords.y, + w = coords.w, + h = coords.h, + bgColor = htmlUtil.style(n, "backgroundColor"), + lightColor = args.lightColor || "#dddddd", + darkColor = args.darkColor, + helperNode = domConstruct.create("div"), + anims = [], + hn = [], + dir = args.dir || "right", + pn = { + left: ["left", "right", "x", "w"], + top: ["top", "bottom", "y", "h"], + right: ["left", "left", "x", "w"], + bottom: ["top", "top", "y", "h"] + }, + shiftMultiplier = { + right: [1, -1], + left: [-1, 1], + top: [-1, 1], + bottom: [1, -1] + } + ; + htmlUtil.style(helperNode, { + position: "absolute", + width : w + "px", + height : h + "px", + top : y + "px", + left : x + "px", + visibility: "hidden" + }); + var hs = []; + for(var i = 0; i < 2; i++){ + var r = i % 2, + d = r ? pn[dir][1] : dir, + wa = r ? "last" : "first", + endColor = r ? bgColor : lightColor, + startColor = r ? endColor : args.startColor || n.style.backgroundColor + ; + hn[i] = lang.clone(helperNode); + var finalize = function(x){ + return function(){ + domConstruct.destroy(hn[x]); + } + }(i) + ; + winUtil.body().appendChild(hn[i]); + hs[i] = { + backgroundColor: r ? startColor : bgColor + }; + + hs[i][pn[dir][0]] = coords[pn[dir][2]] + shiftMultiplier[dir][0] * i * coords[pn[dir][3]] + "px"; + htmlUtil.style(hn[i], hs[i]); + anims.push(dojox.fx.flip({ + node: hn[i], + dir: d, + axis: "shortside", + depth: args.depth, + duration: args.duration / 2, + shift: shiftMultiplier[dir][i] * coords[pn[dir][3]] / 2, + darkColor: darkColor, + lightColor: lightColor, + whichAnim: wa, + endColor: endColor + })); + connectUtil.connect(anims[i], "onEnd", finalize); + } + return coreFx.chain(anims); + }; + + + fxExt.flipGrid = function(/*Object*/ args){ + // summary: An extension to `dojox.fx.flip` providing a decomposition in rows * cols flipping elements + // + // description: + // An extension to `dojox.fx.flip` providing a page flip effect. + // Behaves the same as `dojox.fx.flip`, using the same attributes and + // other standard `dojo.Animation` properties and + // + // cols: Integer columns + // rows: Integer rows + // + // duration: the single flip duration + // + // example: + // See `dojox.fx.flip` + var rows = args.rows || 4, + cols = args.cols || 4, + anims = [], + helperNode = domConstruct.create("div"), + n = args.node, + coords = htmlUtil.coords(n, true), + x = coords.x, + y = coords.y, + nw = coords.w, + nh = coords.h, + w = coords.w / cols, + h = coords.h / rows, + cAnims = [] + ; + htmlUtil.style(helperNode, { + position: "absolute", + width: w + "px", + height: h + "px", + backgroundColor: htmlUtil.style(n, "backgroundColor") + }); + for(var i = 0; i < rows; i++){ + var r = i % 2, + d = r ? "right" : "left", + signum = r ? 1 : -1 + ; + // cloning + var cn = lang.clone(n); + htmlUtil.style(cn, { + position: "absolute", + width: nw + "px", + height: nh + "px", + top: y + "px", + left: x + "px", + clip: "rect(" + i * h + "px," + nw + "px," + nh + "px,0)" + }); + winUtil.body().appendChild(cn); + anims[i] = []; + for(var j = 0; j < cols; j++){ + var hn = lang.clone(helperNode), + l = r ? j : cols - (j + 1) + ; + var adjustClip = function(xn, yCounter, xCounter){ + return function(){ + if(!(yCounter % 2)){ + htmlUtil.style(xn, { + clip: "rect(" + yCounter * h + "px," + (nw - (xCounter + 1) * w ) + "px," + ((yCounter + 1) * h) + "px,0px)" + }); + }else{ + htmlUtil.style(xn, { + clip: "rect(" + yCounter * h + "px," + nw + "px," + ((yCounter + 1) * h) + "px," + ((xCounter + 1) * w) + "px)" + }); + } + } + }(cn, i, j); + winUtil.body().appendChild(hn); + htmlUtil.style(hn, { + left: x + l * w + "px", + top: y + i * h + "px", + visibility: "hidden" + }); + var a = dojox.fx.flipPage({ + node: hn, + dir: d, + duration: args.duration || 900, + shift: signum * w/2, + depth: .2, + darkColor: args.darkColor, + lightColor: args.lightColor, + startColor: args.startColor || args.node.style.backgroundColor + }), + removeHelper = function(xn){ + return function(){ + domConstruct.destroy(xn); + } + }(hn) + ; + connectUtil.connect(a, "play", this, adjustClip); + connectUtil.connect(a, "play", this, removeHelper); + anims[i].push(a); + } + cAnims.push(coreFx.chain(anims[i])); + + } + connectUtil.connect(cAnims[0], "play", function(){ + htmlUtil.style(n, {visibility: "hidden"}); + }); + return coreFx.combine(cAnims); + }; + return fxExt; +}); diff --git a/js/dojo/dojox/fx/resources/shadowB.png b/js/dojo/dojox/fx/resources/shadowB.png Binary files differnew file mode 100644 index 0000000..0da8a2a --- /dev/null +++ b/js/dojo/dojox/fx/resources/shadowB.png diff --git a/js/dojo/dojox/fx/resources/shadowBL.png b/js/dojo/dojox/fx/resources/shadowBL.png Binary files differnew file mode 100644 index 0000000..4926283 --- /dev/null +++ b/js/dojo/dojox/fx/resources/shadowBL.png diff --git a/js/dojo/dojox/fx/resources/shadowBR.png b/js/dojo/dojox/fx/resources/shadowBR.png Binary files differnew file mode 100644 index 0000000..ee704df --- /dev/null +++ b/js/dojo/dojox/fx/resources/shadowBR.png diff --git a/js/dojo/dojox/fx/resources/shadowL.png b/js/dojo/dojox/fx/resources/shadowL.png Binary files differnew file mode 100644 index 0000000..67ebc2e --- /dev/null +++ b/js/dojo/dojox/fx/resources/shadowL.png diff --git a/js/dojo/dojox/fx/resources/shadowR.png b/js/dojo/dojox/fx/resources/shadowR.png Binary files differnew file mode 100644 index 0000000..8d0c99d --- /dev/null +++ b/js/dojo/dojox/fx/resources/shadowR.png diff --git a/js/dojo/dojox/fx/resources/shadowT.png b/js/dojo/dojox/fx/resources/shadowT.png Binary files differnew file mode 100644 index 0000000..ea99436 --- /dev/null +++ b/js/dojo/dojox/fx/resources/shadowT.png diff --git a/js/dojo/dojox/fx/resources/shadowTL.png b/js/dojo/dojox/fx/resources/shadowTL.png Binary files differnew file mode 100644 index 0000000..388742a --- /dev/null +++ b/js/dojo/dojox/fx/resources/shadowTL.png diff --git a/js/dojo/dojox/fx/resources/shadowTR.png b/js/dojo/dojox/fx/resources/shadowTR.png Binary files differnew file mode 100644 index 0000000..c9d4f04 --- /dev/null +++ b/js/dojo/dojox/fx/resources/shadowTR.png diff --git a/js/dojo/dojox/fx/scroll.js b/js/dojo/dojox/fx/scroll.js new file mode 100644 index 0000000..913cf36 --- /dev/null +++ b/js/dojo/dojox/fx/scroll.js @@ -0,0 +1,44 @@ +//>>built +define("dojox/fx/scroll", ["dojo/_base/kernel","dojo/_base/lang", "dojo/_base/fx", "dojox/fx/_base","dojox/fx/_core","dojo/dom-geometry","dojo/_base/sniff"], + function (kernel, lang, baseFx, fxExt, Line, domGeom, has){ + kernel.experimental("dojox.fx.scroll"); + var fx = lang.getObject("dojox.fx",true); + fxExt.smoothScroll = function(/* Object */args){ + // summary: Returns an animation that will smooth-scroll to a node + // description: This implementation support either horizontal or vertical scroll, as well as + // both. In addition, element in iframe can be scrolled to correctly. + // offset: {x: int, y: int} this will be added to the target position + // duration: Duration of the animation in milliseconds. + // win: a node or window object to scroll + + if(!args.target){ args.target = domGeom.position(args.node); } + + var isWindow = lang[(has("ie") ? "isObject" : "isFunction")](args["win"].scrollTo), + delta = { x: args.target.x, y: args.target.y } + ; + if(!isWindow){ + var winPos = domGeom.position(args.win); + delta.x -= winPos.x; + delta.y -= winPos.y; + } + var _anim = (isWindow) ? + (function(val){ + args.win.scrollTo(val[0],val[1]); + }) : + (function(val){ + args.win.scrollLeft = val[0]; + args.win.scrollTop = val[1]; + }); + var anim = new baseFx.Animation(lang.mixin({ + beforeBegin: function(){ + if(this.curve){ delete this.curve; } + var current = isWindow ? dojo._docScroll() : {x: args.win.scrollLeft, y: args.win.scrollTop}; + anim.curve = new Line([current.x,current.y],[current.x + delta.x, current.y + delta.y]); + }, + onAnimate: _anim + },args)); + return anim; // dojo.Animation + }; + fx.smoothScroll = fxExt.smoothScroll; + return fxExt.smoothScroll; +});
\ No newline at end of file diff --git a/js/dojo/dojox/fx/split.js b/js/dojo/dojox/fx/split.js new file mode 100644 index 0000000..777383b --- /dev/null +++ b/js/dojo/dojox/fx/split.js @@ -0,0 +1,663 @@ +//>>built +define("dojox/fx/split", ["dojo/_base/lang", "dojo/dom", "dojo/_base/window", "dojo/_base/html", "dojo/dom-geometry", + "dojo/dom-construct", "dojo/dom-attr", "dojo/_base/fx", "dojo/fx", "./_base", "dojo/fx/easing", "dojo/_base/connect"], + function(lang, dom, winUtil, htmlUtil, domGeom, domConstruct, domAttr, baseFx, coreFx, fxExt, easingUtil, connectUtil){ +var dojoxFx = lang.getObject("dojox.fx"); +lang.mixin(dojoxFx,{ + _split: function(/*Object*/ args){ + // summary: Split a node into rectangular pieces and animate them. + // + // description: + // Returns an animation that will split the node into a grid + // of pieces that move independently. + // + // args: + // args.crop: Boolean - If true, pieces will only be visible inside node's boundries + // args.rows: Integer - The number of horizontal pieces (default is 3) + // args.columns: Integer - The number of vertical pieces (default is 3) + // args.pieceAnimation: Function(piece, x, y, coords) - Returns either the dojo.Animation + // or an array of dojo.Animation objects for the piece at location (x, y) in the node's grid; + // coords is the result of dojo.coords(args.node, true); + + args.rows = args.rows || 3; + args.columns = args.columns || 3; + args.duration = args.duration || 1000; + + var node = args.node = dom.byId(args.node), + parentNode = node.parentNode, + pNode = parentNode, + body = winUtil.body(), + _pos = "position" + ; + + while(pNode && pNode != body && htmlUtil.style(pNode, _pos) == "static"){ + pNode = pNode.parentNode; + } + + var pCoords = pNode != body ? domGeom.position(pNode, true) : { x: 0, y: 0 }, + coords = domGeom.position(node, true), + nodeHeight = htmlUtil.style(node, "height"), + nodeWidth = htmlUtil.style(node, "width"), + hBorder = htmlUtil.style(node, "borderLeftWidth") + htmlUtil.style(node, "borderRightWidth"), + vBorder = htmlUtil.style(node, "borderTopWidth") + htmlUtil.style(node, "borderBottomWidth"), + pieceHeight = Math.ceil(nodeHeight / args.rows), + pieceWidth = Math.ceil(nodeWidth / args.columns), + container = domConstruct.create(node.tagName, { + style: { + position: "absolute", + padding: 0, + margin: 0, + border:"none", + top: coords.y - pCoords.y + "px", + left: coords.x - pCoords.x + "px", + height: nodeHeight + vBorder + "px", + width: nodeWidth + hBorder + "px", + background: "none", + overflow: args.crop ? "hidden" : "visible", + zIndex: htmlUtil.style(node, "zIndex") + } + }, node, "after"), + animations = [], + pieceHelper = domConstruct.create(node.tagName, { + style: { + position: "absolute", + border: "none", + padding: 0, + margin: 0, + height: pieceHeight + hBorder + "px", + width: pieceWidth + vBorder + "px", + overflow: "hidden" + } + }); + + // Create the pieces and their animations + for(var y = 0, ly = args.rows; y < ly; y++){ + for(var x = 0, lx = args.columns; x < lx; x++){ + // Create the piece + var piece = lang.clone(pieceHelper), + pieceContents = lang.clone(node), + pTop = y * pieceHeight, + pLeft = x * pieceWidth + ; + + // IE hack + pieceContents.style.filter = ""; + + // removing the id attribute from the cloned nodes + domAttr.remove(pieceContents, "id"); + + htmlUtil.style(piece, { + border: "none", + overflow: "hidden", + top: pTop + "px", + left: pLeft + "px" + }); + htmlUtil.style(pieceContents, { + position: "static", + opacity: "1", + marginTop: -pTop + "px", + marginLeft: -pLeft + "px" + }); + piece.appendChild(pieceContents); + container.appendChild(piece); + + var pieceAnimation = args.pieceAnimation(piece, x, y, coords); + if(lang.isArray(pieceAnimation)){ + // if pieceAnimation is an array, append its elements + animations = animations.concat(pieceAnimation); + }else{ + // otherwise, append it + animations.push(pieceAnimation); + } + } + } + var anim = coreFx.combine(animations); + connectUtil.connect(anim, "onEnd", anim, function(){ + container.parentNode.removeChild(container); + }); + if(args.onPlay){ + connectUtil.connect(anim, "onPlay", anim, args.onPlay); + } + if(args.onEnd){ + connectUtil.connect(anim, "onEnd", anim, args.onEnd); + } + return anim; // dojo.Animation + }, + + explode: function(/*Object*/ args){ + // summary: Explode a node into rectangular pieces + // + // description: + // Returns an animation that will split the node into a grid + // of pieces that fly away from the center. + // + // args: + // args.rows: Integer - The number of horizontal pieces (default is 3) + // args.columns: Integer - The number of vertical pieces (default is 3) + // args.random: Float - If set, pieces fly to random distances, for random durations, + // and in slightly random directions. The value defines how much + // randomness is introduced. + // args.distance: Float - Multiplier for the distance the pieces fly (even when random) + // args.fade: Boolean - If true, pieces fade out while in motion (default is true) + // args.fadeEasing: Function - If args.fade is true, the fade animations use this easing function + // args.unhide: Boolean - If true, the animation is reversed + // args.sync: Boolean - If args.unhide is true, all the pieces converge at the same time + // (default is true) + + var node = args.node = dom.byId(args.node); + args.rows = args.rows || 3; + args.columns = args.columns || 3; + args.distance = args.distance || 1; + args.duration = args.duration || 1000; + args.random = args.random || 0; + if(!args.fade){ + args.fade = true; + } + if(typeof args.sync == "undefined"){ + args.sync = true; + } + args.random = Math.abs(args.random); + + // Returns the animation object for each piece + args.pieceAnimation = function(piece, x, y, coords){ + var pieceHeight = coords.h / args.rows, + pieceWidth = coords.w / args.columns, + distance = args.distance * 2, + duration = args.duration, + ps = piece.style, + startTop = parseInt(ps.top), + startLeft = parseInt(ps.left), + delay = 0, + randomX = 0, + randomY = 0; + + if(args.random){ + var seed = (Math.random() * args.random) + Math.max(1 - args.random, 0); + distance *= seed; + duration *= seed; + // To syncronize, give each piece an appropriate delay so they end together + delay = ((args.unhide && args.sync) || (!args.unhide && !args.sync)) ? (args.duration - duration) : 0; + // Slightly randomize the direction of each piece + randomX = Math.random() - 0.5; + randomY = Math.random() - 0.5; + } + + var distanceY = ((coords.h - pieceHeight) / 2 - pieceHeight * y), + distanceX = ((coords.w - pieceWidth) / 2 - pieceWidth * x), + distanceXY = Math.sqrt(Math.pow(distanceX, 2) + Math.pow(distanceY, 2)), + endTop = parseInt(startTop - distanceY * distance + distanceXY * randomY), + endLeft = parseInt(startLeft - distanceX * distance + distanceXY * randomX) + ; + + // Create the animation objects for the piece + // These are separate anim objects so they can have different curves + var pieceSlide = baseFx.animateProperty({ + node: piece, + duration: duration, + delay: delay, + easing: (args.easing || (args.unhide ? easingUtil.sinOut : easingUtil.circOut)), + beforeBegin: (args.unhide ? function(){ + if(args.fade){ + htmlUtil.style(piece, { opacity: "0"}); + } + ps.top = endTop + "px"; + ps.left = endLeft + "px"; + } : undefined), + properties: { + top: (args.unhide ? { start: endTop, end: startTop } : { start: startTop, end: endTop }), + left: (args.unhide ? { start: endLeft, end: startLeft } : { start: startLeft, end: endLeft }) + } + }); + if(args.fade){ + var pieceFade = baseFx.animateProperty({ + node: piece, + duration: duration, + delay: delay, + easing: (args.fadeEasing || easingUtil.quadOut), + properties: { + opacity: (args.unhide ? { start: "0", end: "1" } : { start: "1", end: "0" }) + } + }); + + // return both animations as an array + return (args.unhide ? [pieceFade, pieceSlide] : [pieceSlide, pieceFade]); + }else{ + // Otherwise return only the slide animation + return pieceSlide; + } + }; + + var anim = dojoxFx._split(args); + if(args.unhide){ + connectUtil.connect(anim, "onEnd", null, function(){ + htmlUtil.style(node, {opacity: "1" }); + }); + }else{ + connectUtil.connect(anim, "onPlay", null, function(){ + htmlUtil.style(node, { opacity: "0" }); + }); + } + return anim; // dojo.Animation + }, + + converge: function(/*Object*/ args){ + args.unhide = true; + return dojoxFx.explode(args); + }, + + disintegrate: function(/*Object*/ args){ + // summary: Split a node into rectangular pieces and let them fall + // + // description: + // Returns an animation that will split the node into a grid + // of pieces that drop. + // + // args: + // args.rows: Integer - The number of horizontal pieces (default is 5) + // args.columns: Integer - The number of vertical pieces (default is 5) + // args.interval: Float - The number of milliseconds between each piece's animation + // args.distance: Float - The number of the node's heights to drop (default is 1.5) + // args.fade: Boolean - If true, pieces fade out while in motion (default is true) + // args.random: Float - If set, pieces fall in random order. The value defines how much + // randomness is introduced. + // args.reverseOrder: Boolean - If true, pieces animate in reversed order + // args.unhide: Boolean - If true, the peices fall from above and land in place + var node = args.node = dom.byId(args.node); + + args.rows = args.rows || 5; + args.columns = args.columns || 5; + args.duration = args.duration || 1500; + args.interval = args.interval || args.duration / (args.rows + args.columns * 2); + args.distance = args.distance || 1.5; + args.random = args.random || 0; + if(typeof args.fade == "undefined"){ + args.fade = true; + } + + var random = Math.abs(args.random), + duration = args.duration - (args.rows + args.columns) * args.interval; + + // Returns the animation object for each piece + args.pieceAnimation = function(piece, x, y, coords){ + + var randomDelay = Math.random() * (args.rows + args.columns) * args.interval, + ps = piece.style, + + // If distance is negative, start from the top right instead of bottom left + uniformDelay = (args.reverseOrder || args.distance < 0) ? + ((x + y) * args.interval) : + (((args.rows + args.columns) - (x + y)) * args.interval), + delay = randomDelay * random + Math.max(1 - random, 0) * uniformDelay, + // Create the animation object for the piece + properties = {} + ; + if(args.unhide){ + properties.top = { + start: (parseInt(ps.top) - coords.h * args.distance), + end: parseInt(ps.top) + }; + if(args.fade){ + properties.opacity = {start: "0", end: "1"}; + } + }else{ + properties.top = {end: (parseInt(ps.top) + coords.h * args.distance)}; + if(args.fade){ + properties.opacity = {end: "0"}; + } + } + var pieceAnimation = baseFx.animateProperty({ + node: piece, + duration: duration, + delay: delay, + easing: (args.easing || (args.unhide ? easingUtil.sinIn : easingUtil.circIn)), + properties: properties, + beforeBegin: (args.unhide ? function(){ + if(args.fade){ + htmlUtil.style(piece, { opacity: "0" }); + } + ps.top = properties.top.start + "px"; + } : undefined) + }); + + return pieceAnimation; + }; + + var anim = dojoxFx._split(args); + if(args.unhide){ + connectUtil.connect(anim, "onEnd", anim, function(){ + htmlUtil.style(node, { opacity: "1" }); + }); + }else{ + connectUtil.connect(anim, "onPlay", anim, function(){ + htmlUtil.style(node, { opacity: "0" }); + }); + } + return anim; // dojo.Animation + }, + + build: function(/*Object*/ args){ + args.unhide = true; + return dojoxFx.disintegrate(args); + }, + + shear: function(/*Object*/ args){ + // summary: Split a node into rectangular pieces and slide them in alternating directions + // + // description: + // Returns an animation that will split the node into a grid + // of pieces that slide in alternating directions. + // + // args: + // args.rows: Integer - The number of horizontal pieces (default is 6) + // args.columns: Integer - The number of vertical pieces (default is 6) + // args.interval: Float - The number of milliseconds between each piece's animation (default is 0) + // args.distance: Float - The multiple of the node's dimensions to slide (default is 1) + // args.fade: Boolean - If true, pieces fade out while in motion (default is true) + // args.random: Float - If true, pieces have a random delay. The value defines how much + // randomness is introduced + // args.reverseOrder: Boolean - If true, pieces animate in reversed order + // args.unhide: Boolean - If true, the animation is reversed + + var node = args.node = dom.byId(args.node); + + args.rows = args.rows || 6; + args.columns = args.columns || 6; + args.duration = args.duration || 1000; + args.interval = args.interval || 0; + args.distance = args.distance || 1; + args.random = args.random || 0; + if(typeof(args.fade) == "undefined"){ + args.fade = true; + } + var random = Math.abs(args.random), + duration = (args.duration - (args.rows + args.columns) * Math.abs(args.interval)) + ; + + // Returns the animation object for each piece + args.pieceAnimation = function(piece, x, y, coords){ + + // Since x an y start at 0, the opposite is true... + var colIsOdd = !(x % 2), + rowIsOdd = !(y % 2), + randomDelay = Math.random() * duration, + uniformDelay = (args.reverseOrder) ? + (((args.rows + args.columns) - (x + y)) * args.interval) : + ((x + y) * args.interval), + delay = randomDelay * random + Math.max(1 - random, 0) * uniformDelay, + properties = {}, + ps = piece.style + ; + + if(args.fade){ + properties.opacity = (args.unhide ? { start: "0", end: "1" } : { end: "0" }); + } + + // If we have only rows or columns, ignore the other dimension + if(args.columns == 1){ + colIsOdd = rowIsOdd; + }else if(args.rows == 1){ + rowIsOdd = !colIsOdd; + } + + // Determine the piece's direction + var left = parseInt(ps.left), + top = parseInt(ps.top), + distanceX = args.distance*coords.w, + distanceY = args.distance*coords.h + ; + if(args.unhide){ + if(colIsOdd == rowIsOdd){ + properties.left = colIsOdd ? {start: (left - distanceX), end: left} : {start: (left + distanceX), end: left}; + }else{ + properties.top = colIsOdd ? {start: (top + distanceY), end: top} : {start: (top - distanceY), end: top}; + } + }else{ + if(colIsOdd == rowIsOdd){ + properties.left = colIsOdd ? {end: (left - distanceX)} : {end: (left + distanceX)}; + }else{ + properties.top = colIsOdd ? {end: (top + distanceY)} : {end: (top - distanceY)}; + } + } + + // Create the animation object for the piece + var pieceAnimation = baseFx.animateProperty({ + node: piece, + duration: duration, + delay: delay, + easing: (args.easing || easingUtil.sinInOut), + properties: properties, + beforeBegin: (args.unhide ? function(){ + if(args.fade){ + ps.opacity = "0"; + } + if(colIsOdd == rowIsOdd){ + ps.left = properties.left.start + "px"; + }else{ + ps.top = properties.top.start + "px"; + } + } : undefined) + }); + + return pieceAnimation; + }; + + var anim = dojoxFx._split(args); + if(args.unhide){ + connectUtil.connect(anim, "onEnd", anim, function(){ + htmlUtil.style(node, { opacity: "1" }); + }); + }else{ + connectUtil.connect(anim, "onPlay", anim, function(){ + htmlUtil.style(node, { opacity: "0" }); + }); + } + return anim; // dojo.Animation + }, + + unShear: function(/*Object*/ args){ + args.unhide = true; + return dojoxFx.shear(args); + }, + + pinwheel: function(/*Object*/ args){ + // summary: Split a node into rectangular pieces and wipe them in alternating directions + // + // description: + // Returns an animation that will split the node into a grid + // of pieces that wipe in alternating directions. + // + // args: + // args.rows: Integer - The number of horizontal pieces (default is 4) + // args.columns: Integer - The number of vertical pieces (default is 4) + // args.interval: Float - The number of milliseconds between each piece's animation (default is 0) + // args.distance: Float - The percentage of the piece's dimensions the piece should wipe + // args.fade: Boolean - If true, pieces fade out while in motion (default is true) + // args.random: Float - If true, pieces have a random delay. The value defines how much + // randomness is introduced. + // args.unhide: Boolean - If true, the animation is reversed + + var node = args.node = dom.byId(args.node); + + args.rows = args.rows || 4; + args.columns = args.columns || 4; + args.duration = args.duration || 1000; + args.interval = args.interval || 0; + args.distance = args.distance || 1; + args.random = args.random || 0; + if(typeof args.fade == "undefined"){ + args.fade = true; + } + var duration = (args.duration - (args.rows + args.columns) * Math.abs(args.interval)); + + // Returns the animation object for each piece + args.pieceAnimation = function(piece, x, y, coords){ + var pieceHeight = coords.h / args.rows, + pieceWidth = coords.w / args.columns, + + // because x an y start at 0, the opposite is true... + colIsOdd = !(x % 2), + rowIsOdd = !(y % 2), + + randomDelay = Math.random() * duration, + uniformDelay = (args.interval < 0) ? + (((args.rows + args.columns) - (x + y)) * args.interval * -1) : + ((x + y) * args.interval), + delay = randomDelay * args.random + Math.max(1 - args.random, 0) * uniformDelay, + properties = {}, + ps = piece.style + ; + + if(args.fade){ + properties.opacity = (args.unhide ? {start: 0, end: 1} : {end:0}); + } + + // If we have only rows or columns, ignore the other dimension + if(args.columns == 1){ + colIsOdd = !rowIsOdd; + }else if(args.rows == 1){ + rowIsOdd = colIsOdd; + } + + // Determine the piece's direction + var left = parseInt(ps.left), + top = parseInt(ps.top) + ; + if(colIsOdd){ + if(rowIsOdd){ + properties.top = args.unhide ? + { start: top + pieceHeight * args.distance, end: top} : + { start: top, end: top + pieceHeight * args.distance} ; + }else{ + properties.left = args.unhide ? + { start: left + pieceWidth * args.distance, end: left } : + { start: left, end: left + pieceWidth * args.distance } ; + } + } + if(colIsOdd != rowIsOdd){ + properties.width = args.unhide ? + { start: pieceWidth * (1 - args.distance), end: pieceWidth } : + { start: pieceWidth, end: pieceWidth * (1 - args.distance) } ; + }else{ + properties.height = args.unhide ? + { start: pieceHeight * (1 - args.distance), end: pieceHeight } : + { start: pieceHeight, end: pieceHeight * (1 - args.distance) } ; + } + + // Create the animation object for the piece + var pieceAnimation = baseFx.animateProperty({ + node: piece, + duration: duration, + delay: delay, + easing: (args.easing || easingUtil.sinInOut), + properties: properties, + beforeBegin: (args.unhide ? function(){ + if(args.fade){ + htmlUtil.style(piece, "opacity", 0); + } + if(colIsOdd){ + if(rowIsOdd){ + ps.top = (top + pieceHeight * (1 - args.distance)) + "px"; + }else{ + ps.left = (left + pieceWidth * (1 - args.distance)) + "px"; + } + }else{ + ps.left = left + "px"; + ps.top = top + "px"; + } + if(colIsOdd != rowIsOdd){ + ps.width = (pieceWidth * (1 - args.distance)) + "px"; + }else{ + ps.height = (pieceHeight * (1 - args.distance)) + "px"; + } + } : undefined) + }); + + return pieceAnimation; + }; + + var anim = dojoxFx._split(args); + if(args.unhide){ + connectUtil.connect(anim, "onEnd", anim, function(){ + htmlUtil.style(node, { opacity: "1" }); + }); + }else{ + connectUtil.connect(anim, "play", anim, function(){ + htmlUtil.style(node, { opacity: "0" }); + }); + } + return anim; // dojo.Animation + }, + + unPinwheel: function(/*Object*/ args){ + args.unhide = true; + return dojoxFx.pinwheel(args); // dojo.Animation + }, + + blockFadeOut: function(/*Object*/ args){ + // summary: Split a node into rectangular pieces and fade them + // + // description: + // Returns an animation that will split the node into a grid + // of pieces that fade in or out. + // + // args: + // args.rows: Integer - The number of horizontal pieces (default is 5) + // args.columns: Integer - The number of vertical pieces (default is 5) + // args.interval: Float - The number of milliseconds between each piece's animation (default is 0) + // args.random: Float - If true, pieces have a random delay. The value defines how much + // randomness is introduced + // args.reverseOrder: Boolean - If true, pieces animate in reversed order + // args.unhide: Boolean - If true, the animation is reversed + + var node = args.node = dom.byId(args.node); + + args.rows = args.rows || 5; + args.columns = args.columns || 5; + args.duration = args.duration || 1000; + args.interval = args.interval || args.duration / (args.rows + args.columns * 2); + args.random = args.random || 0; + var random = Math.abs(args.random), + duration = args.duration - (args.rows + args.columns) * args.interval + ; + + // Returns the animation object for each piece + args.pieceAnimation = function(piece, x, y, coords){ + var randomDelay = Math.random() * args.duration, + uniformDelay = (args.reverseOrder) ? + (((args.rows + args.columns) - (x + y)) * Math.abs(args.interval)) : + ((x + y) * args.interval), + delay = randomDelay * random + Math.max(1 - random, 0) * uniformDelay, + // Create the animation object for the piece + pieceAnimation = baseFx.animateProperty({ + node: piece, + duration: duration, + delay: delay, + easing: (args.easing || easingUtil.sinInOut), + properties: { + opacity: (args.unhide ? {start: "0", end: "1"} : {start: "1", end: "0"}) + }, + beforeBegin: (args.unhide ? function(){ htmlUtil.style(piece, { opacity: "0" });} : function(){ piece.style.filter = ""; }) + }); + + return pieceAnimation; + }; + var anim = dojoxFx._split(args); + if(args.unhide){ + connectUtil.connect(anim, "onEnd", anim, function(){ + htmlUtil.style(node, { opacity: "1" }); + }); + }else{ + connectUtil.connect(anim, "onPlay", anim, function(){ + htmlUtil.style(node, { opacity: "0" }); + }); + } + return anim; // dojo.Animation + }, + + blockFadeIn: function(/*Object*/ args){ + args.unhide = true; + return dojoxFx.blockFadeOut(args); // dojo.Animation + } +}); +return fxExt; +});
\ No newline at end of file diff --git a/js/dojo/dojox/fx/style.js b/js/dojo/dojox/fx/style.js new file mode 100644 index 0000000..02eba12 --- /dev/null +++ b/js/dojo/dojox/fx/style.js @@ -0,0 +1,237 @@ +//>>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; } + // | <div class="bar" id="test"> + // | Multi<br>line<br>text + // | </div> + // | + // | // 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; +}); diff --git a/js/dojo/dojox/fx/text.js b/js/dojo/dojox/fx/text.js new file mode 100644 index 0000000..faf069f --- /dev/null +++ b/js/dojo/dojox/fx/text.js @@ -0,0 +1,463 @@ +//>>built +define("dojox/fx/text", ["dojo/_base/lang", "./_base", "dojo/_base/fx", "dojo/fx","dojo/fx/easing", "dojo/dom", "dojo/dom-style", "dojo/_base/html", "dojo/_base/connect"], +function(lang, dojoxFx, baseFx, coreFx, easingLib, dom, domStyle, htmlLib, connectUtil ){ +var textFx = lang.getObject("dojox.fx.text", true); +textFx._split = function(/*Object*/ args){ + // summary: Split a block of text into words or letters + // + // description: + // Returns an animation that will split the node into a grid + // of pieces that move independently. + // + // NOTE: + // In some rendering engines, the text will appear to "jump" from its initial position + // when the animation begins. To work around this bug, enclose the node's text in a <p> or <div>. + // + // args: + // args.crop: Boolean - If true, pieces will be positioned relatively rather than absolutely + // args.text: String - Text to place inside the node (otherwise node.innerHTML is used) + // args.words: Boolean - If true, the text will be split into words rather than characters + // args.pieceAnimation: Function(piece, pieceCoords, nodeCoords, number, numPieces) + // - Returns either the dojo.Animation or an array of dojo.Animation objects for the piece; + // pieceCoords is the result of dojo.coords(piece, true); + // nodeCoords is the result of dojo.coords(args.node, true); + // number is the piece's position in the array of pieces, and numPieces is the array.length + + var node = args.node = dom.byId(args.node), + s = node.style, + cs = domStyle.getComputedStyle(node), + nodeCoords = htmlLib.coords(node, true); + + args.duration = args.duration || 1000; + args.words = args.words || false; + + var originalHTML = (args.text && typeof(args.text) == "string") ? args.text : node.innerHTML, + originalHeight = s.height, + originalWidth = s.width, + animations = []; + + domStyle.set(node, { + height: cs.height, + width: cs.width + }); + + // The following regular expression courtesy of Phil Haack + // http://haacked.com/archive/2004/10/25/usingregularexpressionstomatchhtml.aspx + var tagReg = /(<\/?\w+((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)\/?>)/g; + + // Translation: /(HTML tag plus spaces)|(word/letter without '<' plus spaces)/g + var reg = (args.words ? + /(<\/?\w+((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)\/?>)\s*|([^\s<]+\s*)/g : + /(<\/?\w+((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)\/?>)\s*|([^\s<]\s*)/g + ); + + // Split the text into pieces + var pieces = (typeof args.text == "string") ? args.text.match(reg) : node.innerHTML.match(reg); + var html = ""; + var numPieces = 0; + var number = 0; + for(var i = 0; i < pieces.length; i++){ + var piece = pieces[i]; + if(!piece.match(tagReg)){ + html += "<span>" + piece + "</span>"; + numPieces++; + }else{ + html += piece; + } + } + node.innerHTML = html; + + // Find the newly-created spans and create their animations + function animatePieces(piece){ + var next = piece.nextSibling; + if(piece.tagName == "SPAN" && piece.childNodes.length == 1 && piece.firstChild.nodeType == 3){ + var pieceCoords = htmlLib.coords(piece, true); + number++; + domStyle.set(piece, { + padding: 0, + margin: 0, + top: (args.crop ? "0px" : pieceCoords.t + "px"), + left: (args.crop ? "0px" : pieceCoords.l + "px"), + display: "inline" + }); + var pieceAnimation = args.pieceAnimation(piece, pieceCoords, nodeCoords, number, numPieces); + if(lang.isArray(pieceAnimation)){ + // if pieceAnimation is an array, append its elements + animations = animations.concat(pieceAnimation); + }else{ + // otherwise, append it + animations[animations.length] = pieceAnimation; + } + }else if(piece.firstChild){ + animatePieces(piece.firstChild); + } + + if(next){ + animatePieces(next); + } + } + + animatePieces(node.firstChild); + var anim = coreFx.combine(animations); + connectUtil.connect(anim, "onEnd", anim, function(){ + node.innerHTML = originalHTML; + domStyle.set(node, { + height: originalHeight, + width: originalWidth + }); + }); + if(args.onPlay){ + connectUtil.connect(anim, "onPlay", anim, args.onPlay); + } + if(args.onEnd){ + connectUtil.connect(anim, "onEnd", anim, args.onEnd); + } + return anim; // dojo.Animation +}; + +textFx.explode = function(/*Object*/ args){ + // summary: Explode a block of text into words or letters + // + // description: + // Returns an animation that will split the text into a spans + // of words or characters that fly away from the center. + // + // args: + // args.crop: Boolean - If true, pieces will be positioned relatively rather than absolutely + // args.words: Boolean - If true, text will be split into words rather than characters + // args.random: Float - If set, pieces fly to random distances, for random durations, + // and in slightly random directions. The value defines how much + // randomness is introduced. + // args.distance: Float - Multiplier for the distance the pieces fly (even when random) + // args.fade: Boolean - If true, pieces fade out while in motion (default is true) + // args.fadeEasing: Function - If args.fade is true, the fade animations use this easing function + // args.unhide: Boolean - If true, the animation is reversed + // args.sync: Boolean - If args.unhide is true, all the pieces converge at the same time + // (default is true) + + var node = args.node = dom.byId(args.node); + var s = node.style; + + args.distance = args.distance || 1; + args.duration = args.duration || 1000; + args.random = args.random || 0; + if(typeof(args.fade) == "undefined"){ + args.fade = true; + } + if(typeof(args.sync) == "undefined"){ + args.sync = true; + } + args.random = Math.abs(args.random); + + // Returns the animation object for each piece + args.pieceAnimation = function(piece, pieceCoords, coords, number, numPieces){ + var pieceHeight = pieceCoords.h; + var pieceWidth = pieceCoords.w; + var distance = args.distance * 2; + var duration = args.duration; + var startTop = parseFloat(piece.style.top); + var startLeft = parseFloat(piece.style.left); + var delay = 0; + var randomX = 0; + var randomY = 0; + if(args.random){ + var seed = (Math.random() * args.random) + Math.max(1 - args.random, 0); + distance *= seed; + duration *= seed; + // To syncronize, give each piece an appropriate delay so they end together + delay = ((args.unhide && args.sync) || (!args.unhide && !args.sync)) ? (args.duration - duration) : 0; + + // Slightly randomize the direction of each piece + randomX = Math.random() - 0.5; + randomY = Math.random() - 0.5; + } + var distanceY = ((coords.h - pieceHeight) / 2 - (pieceCoords.y - coords.y)); + var distanceX = ((coords.w - pieceWidth) / 2 - (pieceCoords.x - coords.x)); + var distanceXY = Math.sqrt(Math.pow(distanceX, 2) + Math.pow(distanceY, 2)); + var endTop = startTop - distanceY * distance + distanceXY * randomY; + var endLeft = startLeft - distanceX * distance + distanceXY * randomX; + + // Create the animation objects for the piece + // These are separate anim objects so they can have different curves + var pieceSlide = baseFx.animateProperty({ + node: piece, + duration: duration, + delay: delay, + easing: (args.easing || (args.unhide ? easingLib.sinOut : easingLib.circOut)), + beforeBegin: (args.unhide ? function(){ + if(args.fade){ + //piece.style.opacity = 0; + domStyle.set(piece,"opacity", 0); + } + piece.style.position = args.crop ? "relative" : "absolute"; + piece.style.top = endTop + "px"; + piece.style.left = endLeft + "px"; + } : function(){piece.style.position = args.crop ? "relative" : "absolute";}), + properties: { + top: (args.unhide ? { start: endTop, end: startTop } : { start: startTop, end: endTop }), + left: (args.unhide ? { start: endLeft, end: startLeft } : { start: startLeft, end: endLeft }) + } + }); + + if(args.fade){ + var pieceFade = baseFx.animateProperty({ + node: piece, + duration: duration, + delay: delay, + easing: (args.fadeEasing || easingLib.quadOut), + properties: { + opacity: (args.unhide ? {start: 0, end: 1} : {end: 0}) + } + }); + + // return both animations as an array + return (args.unhide ? [pieceFade, pieceSlide] : [pieceSlide, pieceFade]); + }else{ + // Otherwise return only the slide animation + return pieceSlide; + } + }; + + var anim = textFx._split(args); + return anim; // dojo.Animation +}; + +textFx.converge = function(/*Object*/ args){ + args.unhide = true; + return textFx.explode(args); +}; + +textFx.disintegrate = function(/*Object*/ args){ + // summary: Split a block of text into words or letters and let them fall + // + // description: + // Returns an animation that will split the text into spans of words + // or characters that drop. + // + // args: + // args.crop: Boolean - If true, pieces will be positioned relatively rather than absolutely + // args.words: Boolean - If true, text will be split into words rather than characters + // args.interval: Float - The number of milliseconds between each piece's animation + // args.distance: Float - The number of the node's heights to drop (default is 1.5) + // args.fade: Boolean - If true, pieces fade out while in motion (default is true) + // args.random: Float - If set, pieces fall in random order. The value defines how much + // randomness is introduced + // args.reverseOrder: Boolean - If true, pieces animate in reversed order + // args.unhide: Boolean - If true, the peices fall from above and land in place + + var node = args.node = dom.byId(args.node); + var s = node.style; + + args.duration = args.duration || 1500; + args.distance = args.distance || 1.5; + args.random = args.random || 0; + if(!args.fade){ + args.fade = true; + } + var random = Math.abs(args.random); + + // Returns the animation object for each piece + args.pieceAnimation = function(piece, pieceCoords, coords, number, numPieces){ + var pieceHeight = pieceCoords.h; + var pieceWidth = pieceCoords.w; + + var interval = args.interval || (args.duration / (1.5 * numPieces)); + var duration = (args.duration - numPieces * interval); + + var randomDelay = Math.random() * numPieces * interval; + // If distance is negative, start from the top right instead of bottom left + var uniformDelay = (args.reverseOrder || args.distance < 0) ? + (number * interval) : ((numPieces - number) * interval); + var delay = randomDelay * random + Math.max(1 - random, 0) * uniformDelay; + + // Create the animation object for the piece + var properties = {}; + if(args.unhide){ + properties.top = { + start: (parseFloat(piece.style.top) - coords.h * args.distance), + end: parseFloat(piece.style.top) + }; + if(args.fade){ + properties.opacity = {start: 0, end: 1}; + } + }else{ + properties.top = {end: (parseFloat(piece.style.top) + coords.h * args.distance)}; + if(args.fade){ + properties.opacity = {end: 0}; + } + } + var pieceAnimation = baseFx.animateProperty({ + node: piece, + duration: duration, + delay: delay, + easing: (args.easing || (args.unhide ? easingLib.sinIn : easingLib.circIn)), + properties: properties, + beforeBegin: (args.unhide ? function(){ + if(args.fade){ + // piece.style.opacity = 0; + domStyle.set(piece, "opacity", 0); + } + piece.style.position = args.crop ? "relative" : "absolute"; + piece.style.top = properties.top.start + "px"; + } : function(){ piece.style.position = args.crop ? "relative" : "absolute";}) + }); + + return pieceAnimation; + }; + + var anim = textFx._split(args); + return anim; // dojo.Animation +}; + +textFx.build = function(/*Object*/ args){ + args.unhide = true; + return textFx.disintegrate(args); +}; + +textFx.blockFadeOut = function(/*Object*/ args){ + // summary: Split a block of text into words or letters and fade them + // + // description: + // Returns an animation that will split the text into spans of words + // or characters that fade in or out. + // + // args: + // args.words: Boolean - If true, text will be split into words rather than characters + // args.interval: Float - The number of milliseconds between each piece's animation (default is 0) + // args.random: Float - If true, pieces have a random delay. The value defines how much + // randomness is introduced + // args.reverseOrder: Boolean - If true, pieces animate in reversed order + // args.unhide: Boolean - If true, the animation is reversed + + var node = args.node = dom.byId(args.node);; + var s = node.style; + + args.duration = args.duration || 1000; + args.random = args.random || 0; + var random = Math.abs(args.random); + + // Returns the animation object for each piece + args.pieceAnimation = function(piece, pieceCoords, coords, number, numPieces){ + var interval = args.interval || (args.duration / (1.5 * numPieces)); + var duration = (args.duration - numPieces * interval); + + var randomDelay = Math.random() * numPieces * interval; + // If interval or random is negative, start from the bottom instead of top + var uniformDelay = (args.reverseOrder) ? + ((numPieces - number) * interval) : (number * interval); + var delay = randomDelay * random + Math.max(1 - random, 0) * uniformDelay; + + // Create the animation object for the piece + var pieceAnimation = baseFx.animateProperty({ + node: piece, + duration: duration, + delay: delay, + easing: (args.easing || easingLib.sinInOut), + properties: { + opacity: (args.unhide ? {start: 0, end: 1} : {end:0}) + }, + beforeBegin: (args.unhide ? function(){ domStyle.set(piece,"opacity",0); } : undefined) + }); + + return pieceAnimation; + }; + + var anim = textFx._split(args); + return anim; // dojo.Animation +}; + +textFx.blockFadeIn = function(/*Object*/ args){ + args.unhide = true; + return textFx.blockFadeOut(args); +}; + +textFx.backspace = function(/*Object*/ args){ + // summary: Split a block of text into words or letters and backspace them in sequence + // + // description: + // Returns an animation that will split the text into spans of words + // or characters that appear as if they were being backspaced (or typed) in real-time. + // + // args: + // args.interval: Float - The number of milliseconds between each piece's animation + // (default is determined by text length and args.duration); + // args.wordDelay: Integer - The number of milliseconds between each word + // (only effective when args.unhide = true) + // args.fixed: Boolean - If true, only style.opacity changes; otherwise, style.display + // changes between none and inline, adding realism (default = false) + // args.random: Float - If true, pieces have a random delay. The value defines how much + // randomness is introduced (only effective when args.unhide = true) + // args.unhide: Boolean - If true, the animation is reversed + + var node = args.node = dom.byId(args.node); + var s = node.style; + + args.words = false; + args.duration = args.duration || 2000; + args.random = args.random || 0; + var random = Math.abs(args.random); + var delay = 10; + + // Returns the animation object for each piece + args.pieceAnimation = function(piece, pieceCoords, coords, number, numPieces){ + var interval = args.interval || (args.duration / (1.5 * numPieces)), + text = ("textContent" in piece) ? piece.textContent : piece.innerText, + whitespace = text.match(/\s/g); + + if(typeof(args.wordDelay) == "undefined"){ + args.wordDelay = interval * 2; + } + + if(!args.unhide){ + delay = (numPieces - number - 1) * interval; + } + + var beforeBegin, onEnd; + + if(args.fixed){ + if(args.unhide){ + var beforeBegin = function(){ domStyle.set(piece,"opacity",0); }; + } + }else{ + if(args.unhide){ + var beforeBegin = function(){piece.style.display = "none";}; + var onEnd = function(){piece.style.display = "inline";}; + }else{ + var onEnd = function(){piece.style.display = "none";}; + } + } + + // Create the animation object for the piece + var pieceAnimation = baseFx.animateProperty({ + node: piece, + duration: 1, + delay: delay, + easing: (args.easing || easingLib.sinInOut), + properties: { + opacity: (args.unhide ? {start: 0, end: 1} : {end:0}) + }, + beforeBegin: beforeBegin, + onEnd: onEnd + }); + + if(args.unhide){ + var randomDelay = Math.random() * text.length * interval; + var wordDelay = randomDelay * random / 2 + Math.max(1 - random / 2, 0) * args.wordDelay; + + delay += randomDelay * random + Math.max(1 - random, 0) * interval * text.length + + (wordDelay * (whitespace && text.lastIndexOf(whitespace[whitespace.length-1]) == text.length - 1)); + } + + return pieceAnimation; + }; + + var anim = textFx._split(args); + return anim; // dojo.Animation +}; + +textFx.type = function(/*Object*/ args){ + args.unhide = true; + return textFx.backspace(args); +}; +return textFx; +});
\ No newline at end of file |
