From e44a7e37b6c7b5961adaffc62b9042b8d442938e Mon Sep 17 00:00:00 2001 From: mensonge Date: Thu, 13 Nov 2008 09:49:11 +0000 Subject: New feature: basic Ajax suggestion for tags and implementation of Dojo toolkit git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@151 b3834d28-1941-0410-a4f8-b48e95affb8f --- includes/js/dojo/fx.js | 415 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 415 insertions(+) create mode 100644 includes/js/dojo/fx.js (limited to 'includes/js/dojo/fx.js') diff --git a/includes/js/dojo/fx.js b/includes/js/dojo/fx.js new file mode 100644 index 0000000..1473531 --- /dev/null +++ b/includes/js/dojo/fx.js @@ -0,0 +1,415 @@ +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 +} + +} -- cgit v1.2.3