if(!dojo._hasResource["dojo.fx"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. dojo._hasResource["dojo.fx"] = true; dojo.provide("dojo.fx"); dojo.provide("dojo.fx.Toggler"); /*===== dojo.fx = { // summary: Effects library on top of Base animations }; =====*/ (function(){ var _baseObj = { _fire: function(evt, args){ if(this[evt]){ this[evt].apply(this, args||[]); } return this; } }; var _chain = function(animations){ this._index = -1; this._animations = animations||[]; this._current = this._onAnimateCtx = this._onEndCtx = null; this.duration = 0; dojo.forEach(this._animations, function(a){ this.duration += a.duration; if(a.delay){ this.duration += a.delay; } }, this); }; dojo.extend(_chain, { _onAnimate: function(){ this._fire("onAnimate", arguments); }, _onEnd: function(){ dojo.disconnect(this._onAnimateCtx); dojo.disconnect(this._onEndCtx); this._onAnimateCtx = this._onEndCtx = null; if(this._index + 1 == this._animations.length){ this._fire("onEnd"); }else{ // switch animations this._current = this._animations[++this._index]; this._onAnimateCtx = dojo.connect(this._current, "onAnimate", this, "_onAnimate"); this._onEndCtx = dojo.connect(this._current, "onEnd", this, "_onEnd"); this._current.play(0, true); } }, play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){ if(!this._current){ this._current = this._animations[this._index = 0]; } if(!gotoStart && this._current.status() == "playing"){ return this; } var beforeBegin = dojo.connect(this._current, "beforeBegin", this, function(){ this._fire("beforeBegin"); }), onBegin = dojo.connect(this._current, "onBegin", this, function(arg){ this._fire("onBegin", arguments); }), onPlay = dojo.connect(this._current, "onPlay", this, function(arg){ this._fire("onPlay", arguments); dojo.disconnect(beforeBegin); dojo.disconnect(onBegin); dojo.disconnect(onPlay); }); if(this._onAnimateCtx){ dojo.disconnect(this._onAnimateCtx); } this._onAnimateCtx = dojo.connect(this._current, "onAnimate", this, "_onAnimate"); if(this._onEndCtx){ dojo.disconnect(this._onEndCtx); } this._onEndCtx = dojo.connect(this._current, "onEnd", this, "_onEnd"); this._current.play.apply(this._current, arguments); return this; }, pause: function(){ if(this._current){ var e = dojo.connect(this._current, "onPause", this, function(arg){ this._fire("onPause", arguments); dojo.disconnect(e); }); this._current.pause(); } return this; }, gotoPercent: function(/*Decimal*/percent, /*Boolean?*/ andPlay){ this.pause(); var offset = this.duration * percent; this._current = null; dojo.some(this._animations, function(a){ if(a.duration <= offset){ this._current = a; return true; } offset -= a.duration; return false; }); if(this._current){ this._current.gotoPercent(offset / _current.duration, andPlay); } return this; }, stop: function(/*boolean?*/ gotoEnd){ if(this._current){ if(gotoEnd){ for(; this._index + 1 < this._animations.length; ++this._index){ this._animations[this._index].stop(true); } this._current = this._animations[this._index]; } var e = dojo.connect(this._current, "onStop", this, function(arg){ this._fire("onStop", arguments); dojo.disconnect(e); }); this._current.stop(); } return this; }, status: function(){ return this._current ? this._current.status() : "stopped"; }, destroy: function(){ if(this._onAnimateCtx){ dojo.disconnect(this._onAnimateCtx); } if(this._onEndCtx){ dojo.disconnect(this._onEndCtx); } } }); dojo.extend(_chain, _baseObj); dojo.fx.chain = function(/*dojo._Animation[]*/ animations){ // summary: Chain a list of dojo._Animation s to run in sequence // example: // | dojo.fx.chain([ // | dojo.fadeIn({ node:node }), // | dojo.fadeOut({ node:otherNode }) // | ]).play(); // return new _chain(animations) // dojo._Animation }; var _combine = function(animations){ this._animations = animations||[]; this._connects = []; this._finished = 0; this.duration = 0; dojo.forEach(animations, function(a){ var duration = a.duration; if(a.delay){ duration += a.delay; } if(this.duration < duration){ this.duration = duration; } this._connects.push(dojo.connect(a, "onEnd", this, "_onEnd")); }, this); this._pseudoAnimation = new dojo._Animation({curve: [0, 1], duration: this.duration}); dojo.forEach(["beforeBegin", "onBegin", "onPlay", "onAnimate", "onPause", "onStop"], function(evt){ this._connects.push(dojo.connect(this._pseudoAnimation, evt, dojo.hitch(this, "_fire", evt))); }, this ); }; dojo.extend(_combine, { _doAction: function(action, args){ dojo.forEach(this._animations, function(a){ a[action].apply(a, args); }); return this; }, _onEnd: function(){ if(++this._finished == this._animations.length){ this._fire("onEnd"); } }, _call: function(action, args){ var t = this._pseudoAnimation; t[action].apply(t, args); }, play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){ this._finished = 0; this._doAction("play", arguments); this._call("play", arguments); return this; }, pause: function(){ this._doAction("pause", arguments); this._call("pause", arguments); return this; }, gotoPercent: function(/*Decimal*/percent, /*Boolean?*/ andPlay){ var ms = this.duration * percent; dojo.forEach(this._animations, function(a){ a.gotoPercent(a.duration < ms ? 1 : (ms / a.duration), andPlay); }); this._call("gotoProcent", arguments); return this; }, stop: function(/*boolean?*/ gotoEnd){ this._doAction("stop", arguments); this._call("stop", arguments); return this; }, status: function(){ return this._pseudoAnimation.status(); }, destroy: function(){ dojo.forEach(this._connects, dojo.disconnect); } }); dojo.extend(_combine, _baseObj); dojo.fx.combine = function(/*dojo._Animation[]*/ animations){ // summary: Combine a list of dojo._Animation s to run in parallel // example: // | dojo.fx.combine([ // | dojo.fadeIn({ node:node }), // | dojo.fadeOut({ node:otherNode }) // | ]).play(); return new _combine(animations); // dojo._Animation }; })(); dojo.declare("dojo.fx.Toggler", null, { // summary: // class constructor for an animation toggler. It accepts a packed // set of arguments about what type of animation to use in each // direction, duration, etc. // // example: // | var t = new dojo.fx.Toggler({ // | node: "nodeId", // | showDuration: 500, // | // hideDuration will default to "200" // | showFunc: dojo.wipeIn, // | // hideFunc will default to "fadeOut" // | }); // | t.show(100); // delay showing for 100ms // | // ...time passes... // | t.hide(); // FIXME: need a policy for where the toggler should "be" the next // time show/hide are called if we're stopped somewhere in the // middle. constructor: function(args){ var _t = this; dojo.mixin(_t, args); _t.node = args.node; _t._showArgs = dojo.mixin({}, args); _t._showArgs.node = _t.node; _t._showArgs.duration = _t.showDuration; _t.showAnim = _t.showFunc(_t._showArgs); _t._hideArgs = dojo.mixin({}, args); _t._hideArgs.node = _t.node; _t._hideArgs.duration = _t.hideDuration; _t.hideAnim = _t.hideFunc(_t._hideArgs); dojo.connect(_t.showAnim, "beforeBegin", dojo.hitch(_t.hideAnim, "stop", true)); dojo.connect(_t.hideAnim, "beforeBegin", dojo.hitch(_t.showAnim, "stop", true)); }, // node: DomNode // the node to toggle node: null, // showFunc: Function // The function that returns the dojo._Animation to show the node showFunc: dojo.fadeIn, // hideFunc: Function // The function that returns the dojo._Animation to hide the node hideFunc: dojo.fadeOut, // showDuration: // Time in milliseconds to run the show Animation showDuration: 200, // hideDuration: // Time in milliseconds to run the hide Animation hideDuration: 200, /*===== _showArgs: null, _showAnim: null, _hideArgs: null, _hideAnim: null, _isShowing: false, _isHiding: false, =====*/ show: function(delay){ // summary: Toggle the node to showing return this.showAnim.play(delay || 0); }, hide: function(delay){ // summary: Toggle the node to hidden return this.hideAnim.play(delay || 0); } }); dojo.fx.wipeIn = function(/*Object*/ args){ // summary // Returns an animation that will expand the // node defined in 'args' object from it's current height to // it's natural height (with no scrollbar). // Node must have no margin/border/padding. args.node = dojo.byId(args.node); var node = args.node, s = node.style; var anim = dojo.animateProperty(dojo.mixin({ properties: { height: { // 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.height="1px"; s.display=""; s.visibility=""; return 1; }else{ var height = dojo.style(node, "height"); return Math.max(height, 1); } }, end: function(){ return node.scrollHeight; } } } }, args)); dojo.connect(anim, "onEnd", function(){ s.height = "auto"; }); return anim; // dojo._Animation } dojo.fx.wipeOut = function(/*Object*/ args){ // summary // Returns an animation that will shrink node defined in "args" // from it's current height to 1px, and then hide it. var node = args.node = dojo.byId(args.node); var s = node.style; var anim = dojo.animateProperty(dojo.mixin({ properties: { height: { end: 1 // 0 causes IE to display the whole panel } } }, args)); dojo.connect(anim, "beforeBegin", function(){ s.overflow = "hidden"; s.display = ""; }); dojo.connect(anim, "onEnd", function(){ s.height = "auto"; s.display = "none"; }); return anim; // dojo._Animation } dojo.fx.slideTo = function(/*Object?*/ args){ // summary // Returns an animation that will slide "node" // defined in args Object from its current position to // the position defined by (args.left, args.top). // example: // | dojo.fx.slideTo({ node: node, left:"40", top:"50", unit:"px" }).play() var node = (args.node = dojo.byId(args.node)); var top = null; var left = null; var init = (function(n){ return function(){ var cs = dojo.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 = dojo.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 = dojo.animateProperty(dojo.mixin({ properties: { top: { end: args.top||0 }, left: { end: args.left||0 } } }, args)); dojo.connect(anim, "beforeBegin", anim, init); return anim; // dojo._Animation } }