You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by jk...@apache.org on 2006/06/10 15:59:38 UTC

svn commit: r413300 [5/16] - in /tapestry/tapestry4/trunk/framework/src/js: dojo/ dojo/src/ dojo/src/animation/ dojo/src/collections/ dojo/src/compat/ dojo/src/crypto/ dojo/src/data/ dojo/src/data/format/ dojo/src/data/provider/ dojo/src/debug/ dojo/sr...

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/event/browser.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/event/browser.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/event/browser.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/event/browser.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,272 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.event.browser");
+dojo.require("dojo.event");
+
+// FIXME: any particular reason this is in the global scope?
+dojo._ie_clobber = new function(){
+	this.clobberNodes = [];
+
+	function nukeProp(node, prop){
+		// try{ node.removeAttribute(prop); 	}catch(e){ /* squelch */ }
+		try{ node[prop] = null; 			}catch(e){ /* squelch */ }
+		try{ delete node[prop]; 			}catch(e){ /* squelch */ }
+		// FIXME: JotLive needs this, but I'm not sure if it's too slow or not
+		try{ node.removeAttribute(prop);	}catch(e){ /* squelch */ }
+	}
+
+	this.clobber = function(nodeRef){
+		var na;
+		var tna;
+		if(nodeRef){
+			tna = nodeRef.all || nodeRef.getElementsByTagName("*");
+			na = [nodeRef];
+			for(var x=0; x<tna.length; x++){
+				// if we're gonna be clobbering the thing, at least make sure
+				// we aren't trying to do it twice
+				if(tna[x]["__doClobber__"]){
+					na.push(tna[x]);
+				}
+			}
+		}else{
+			try{ window.onload = null; }catch(e){}
+			na = (this.clobberNodes.length) ? this.clobberNodes : document.all;
+		}
+		tna = null;
+		var basis = {};
+		for(var i = na.length-1; i>=0; i=i-1){
+			var el = na[i];
+			if(el["__clobberAttrs__"]){
+				for(var j=0; j<el.__clobberAttrs__.length; j++){
+					nukeProp(el, el.__clobberAttrs__[j]);
+				}
+				nukeProp(el, "__clobberAttrs__");
+				nukeProp(el, "__doClobber__");
+			}
+		}
+		na = null;
+	}
+}
+
+if(dojo.render.html.ie){
+	dojo.addOnUnload(function(){
+		dojo._ie_clobber.clobber();
+		try{
+			if((dojo["widget"])&&(dojo.widget["manager"])){
+				dojo.widget.manager.destroyAll();
+			}
+		}catch(e){}
+		try{ window.onload = null; }catch(e){}
+		try{ window.onunload = null; }catch(e){}
+		dojo._ie_clobber.clobberNodes = [];
+		// CollectGarbage();
+	});
+}
+
+dojo.event.browser = new function(){
+
+	var clobberIdx = 0;
+
+	this.clean = function(node){
+		if(dojo.render.html.ie){ 
+			dojo._ie_clobber.clobber(node);
+		}
+	}
+
+	this.addClobberNode = function(node){
+		if(!dojo.render.html.ie){ return; }
+		if(!node["__doClobber__"]){
+			node.__doClobber__ = true;
+			dojo._ie_clobber.clobberNodes.push(node);
+			// this might not be the most efficient thing to do, but it's
+			// much less error prone than other approaches which were
+			// previously tried and failed
+			node.__clobberAttrs__ = [];
+		}
+	}
+
+	this.addClobberNodeAttrs = function(node, props){
+		if(!dojo.render.html.ie){ return; }
+		this.addClobberNode(node);
+		for(var x=0; x<props.length; x++){
+			node.__clobberAttrs__.push(props[x]);
+		}
+	}
+
+	this.removeListener = function(node, evtName, fp, capture){
+		if(!capture){ var capture = false; }
+		evtName = evtName.toLowerCase();
+		if(evtName.substr(0,2)=="on"){ evtName = evtName.substr(2); }
+		// FIXME: this is mostly a punt, we aren't actually doing anything on IE
+		if(node.removeEventListener){
+			node.removeEventListener(evtName, fp, capture);
+		}
+	}
+
+	this.addListener = function(node, evtName, fp, capture, dontFix){
+		if(!node){ return; } // FIXME: log and/or bail?
+		if(!capture){ var capture = false; }
+		evtName = evtName.toLowerCase();
+		if(evtName.substr(0,2)!="on"){ evtName = "on"+evtName; }
+
+		if(!dontFix){
+			// build yet another closure around fp in order to inject fixEvent
+			// around the resulting event
+			var newfp = function(evt){
+				if(!evt){ evt = window.event; }
+				var ret = fp(dojo.event.browser.fixEvent(evt, this));
+				if(capture){
+					dojo.event.browser.stopEvent(evt);
+				}
+				return ret;
+			}
+		}else{
+			newfp = fp;
+		}
+
+		if(node.addEventListener){ 
+			node.addEventListener(evtName.substr(2), newfp, capture);
+			return newfp;
+		}else{
+			if(typeof node[evtName] == "function" ){
+				var oldEvt = node[evtName];
+				node[evtName] = function(e){
+					oldEvt(e);
+					return newfp(e);
+				}
+			}else{
+				node[evtName]=newfp;
+			}
+			if(dojo.render.html.ie){
+				this.addClobberNodeAttrs(node, [evtName]);
+			}
+			return newfp;
+		}
+	}
+
+	this.isEvent = function(obj){
+		// FIXME: event detection hack ... could test for additional attributes
+		// if necessary
+		return (typeof obj != "undefined")&&(typeof Event != "undefined")&&(obj.eventPhase);
+		// Event does not support instanceof in Opera, otherwise:
+		//return (typeof Event != "undefined")&&(obj instanceof Event);
+	}
+
+	this.currentEvent = null;
+	
+	this.callListener = function(listener, curTarget){
+		if(typeof listener != 'function'){
+			dojo.raise("listener not a function: " + listener);
+		}
+		dojo.event.browser.currentEvent.currentTarget = curTarget;
+		return listener.call(curTarget, dojo.event.browser.currentEvent);
+	}
+
+	this.stopPropagation = function(){
+		dojo.event.browser.currentEvent.cancelBubble = true;
+	}
+
+	this.preventDefault = function(){
+	  dojo.event.browser.currentEvent.returnValue = false;
+	}
+
+	this.keys = {
+		KEY_BACKSPACE: 8,
+		KEY_TAB: 9,
+		KEY_ENTER: 13,
+		KEY_SHIFT: 16,
+		KEY_CTRL: 17,
+		KEY_ALT: 18,
+		KEY_PAUSE: 19,
+		KEY_CAPS_LOCK: 20,
+		KEY_ESCAPE: 27,
+		KEY_SPACE: 32,
+		KEY_PAGE_UP: 33,
+		KEY_PAGE_DOWN: 34,
+		KEY_END: 35,
+		KEY_HOME: 36,
+		KEY_LEFT_ARROW: 37,
+		KEY_UP_ARROW: 38,
+		KEY_RIGHT_ARROW: 39,
+		KEY_DOWN_ARROW: 40,
+		KEY_INSERT: 45,
+		KEY_DELETE: 46,
+		KEY_LEFT_WINDOW: 91,
+		KEY_RIGHT_WINDOW: 92,
+		KEY_SELECT: 93,
+		KEY_F1: 112,
+		KEY_F2: 113,
+		KEY_F3: 114,
+		KEY_F4: 115,
+		KEY_F5: 116,
+		KEY_F6: 117,
+		KEY_F7: 118,
+		KEY_F8: 119,
+		KEY_F9: 120,
+		KEY_F10: 121,
+		KEY_F11: 122,
+		KEY_F12: 123,
+		KEY_NUM_LOCK: 144,
+		KEY_SCROLL_LOCK: 145
+	};
+
+	// reverse lookup
+	this.revKeys = [];
+	for(var key in this.keys){
+		this.revKeys[this.keys[key]] = key;
+	}
+
+	this.fixEvent = function(evt, sender){
+		if((!evt)&&(window["event"])){
+			var evt = window.event;
+		}
+		
+		if((evt["type"])&&(evt["type"].indexOf("key") == 0)){ // key events
+			evt.keys = this.revKeys;
+			// FIXME: how can we eliminate this iteration?
+			for(var key in this.keys) {
+				evt[key] = this.keys[key];
+			}
+			if((dojo.render.html.ie)&&(evt["type"] == "keypress")){
+				evt.charCode = evt.keyCode;
+			}
+		}
+	
+		if(dojo.render.html.ie){
+			if(!evt.target){ evt.target = evt.srcElement; }
+			if(!evt.currentTarget){ evt.currentTarget = (sender ? sender : evt.srcElement); }
+			if(!evt.layerX){ evt.layerX = evt.offsetX; }
+			if(!evt.layerY){ evt.layerY = evt.offsetY; }
+			// FIXME: scroll position query is duped from dojo.html to avoid dependency on that entire module
+			if(!evt.pageX){ evt.pageX = evt.clientX + (window.pageXOffset || document.scrollLeft || document.documentElement.scrollLeft || document.body.scrollLeft || 0) }
+			if(!evt.pageY){ evt.pageY = evt.clientY + (window.pageYOffset || document.scrollTop || document.documentElement.scrollTop || document.body.scrollTop || 0) }
+			// mouseover
+			if(evt.type == "mouseover"){ evt.relatedTarget = evt.fromElement; }
+			// mouseout
+			if(evt.type == "mouseout"){ evt.relatedTarget = evt.toElement; }
+			this.currentEvent = evt;
+			evt.callListener = this.callListener;
+			evt.stopPropagation = this.stopPropagation;
+			evt.preventDefault = this.preventDefault;
+		}
+		return evt;
+	}
+
+	this.stopEvent = function(ev) {
+		if(window.event){
+			ev.returnValue = false;
+			ev.cancelBubble = true;
+		}else{
+			ev.preventDefault();
+			ev.stopPropagation();
+		}
+	}
+}

Propchange: tapestry/tapestry4/trunk/framework/src/js/dojo/src/event/browser.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/event/topic.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/event/topic.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/event/topic.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/event/topic.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,99 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.require("dojo.event");
+dojo.provide("dojo.event.topic");
+
+dojo.event.topic = new function(){
+	this.topics = {};
+
+	this.getTopic = function(topicName){
+		if(!this.topics[topicName]){
+			this.topics[topicName] = new this.TopicImpl(topicName);
+		}
+		return this.topics[topicName];
+	}
+
+	this.registerPublisher = function(topic, obj, funcName){
+		var topic = this.getTopic(topic);
+		topic.registerPublisher(obj, funcName);
+	}
+
+	this.subscribe = function(topic, obj, funcName){
+		var topic = this.getTopic(topic);
+		topic.subscribe(obj, funcName);
+	}
+
+	this.unsubscribe = function(topic, obj, funcName){
+		var topic = this.getTopic(topic);
+		topic.unsubscribe(obj, funcName);
+	}
+
+	this.destroy = function(topic){
+		this.getTopic(topic).destroy();
+		delete this.topics[topic];
+	}
+
+	this.publishApply = function(topic, args){
+		var topic = this.getTopic(topic);
+		topic.sendMessage.apply(topic, args);
+	}
+
+	this.publish = function(topic, message){
+		var topic = this.getTopic(topic);
+		// if message is an array, we treat it as a set of arguments,
+		// otherwise, we just pass on the arguments passed in as-is
+		var args = [];
+		// could we use concat instead here?
+		for(var x=1; x<arguments.length; x++){
+			args.push(arguments[x]);
+		}
+		topic.sendMessage.apply(topic, args);
+	}
+}
+
+dojo.event.topic.TopicImpl = function(topicName){
+	this.topicName = topicName;
+
+	this.subscribe = function(listenerObject, listenerMethod){
+		var tf = listenerMethod||listenerObject;
+		var to = (!listenerMethod) ? dj_global : listenerObject;
+		dojo.event.kwConnect({
+			srcObj:		this, 
+			srcFunc:	"sendMessage", 
+			adviceObj:	to,
+			adviceFunc: tf
+		});
+	}
+
+	this.unsubscribe = function(listenerObject, listenerMethod){
+		var tf = (!listenerMethod) ? listenerObject : listenerMethod;
+		var to = (!listenerMethod) ? null : listenerObject;
+		dojo.event.kwDisconnect({
+			srcObj:		this, 
+			srcFunc:	"sendMessage", 
+			adviceObj:	to,
+			adviceFunc: tf
+		});
+	}
+
+	this.destroy = function(){
+		dojo.event.MethodJoinPoint.getForMethod(this, "sendMessage").disconnect();
+	}
+
+	this.registerPublisher = function(publisherObject, publisherMethod){
+		dojo.event.connect(publisherObject, publisherMethod, this, "sendMessage");
+	}
+
+	this.sendMessage = function(message){
+		// The message has been propagated
+	}
+}
+

Propchange: tapestry/tapestry4/trunk/framework/src/js/dojo/src/event/topic.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/flash.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/flash.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/flash.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/flash.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,1242 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.flash");
+
+dojo.require("dojo.string.*");
+dojo.require("dojo.uri.*");
+
+
+/** 
+		The goal of dojo.flash is to make it easy to extend Flash's capabilities
+		into an AJAX/DHTML environment. Robust, performant, reliable 
+		JavaScript/Flash communication is harder than most realize when they
+		delve into the topic, especially if you want it
+		to work on Internet Explorer, Firefox, and Safari, and to be able to
+		push around hundreds of K of information quickly. Dojo.flash makes it
+		possible to support these platforms; you have to jump through a few
+		hoops to get its capabilites, but if you are a library writer 
+		who wants to bring Flash's storage or streaming sockets ability into
+		DHTML, for example, then dojo.flash is perfect for you.
+  
+		Dojo.flash provides an easy object for interacting with the Flash plugin. 
+		This object provides methods to determine the current version of the Flash
+		plugin (dojo.flash.info); execute Flash instance methods 
+		independent of the Flash version
+		being used (dojo.flash.comm); write out the necessary markup to 
+		dynamically insert a Flash object into the page (dojo.flash.Embed; and 
+		do dynamic installation and upgrading of the current Flash plugin in 
+		use (dojo.flash.Install).
+		
+		To use dojo.flash, you must first wait until Flash is finished loading 
+		and initializing before you attempt communication or interaction. 
+		To know when Flash is finished use dojo.event.connect:
+		
+		dojo.event.connect(dojo.flash, "loaded", myInstance, "myCallback");
+		
+		Then, while the page is still loading provide the file name
+		and the major version of Flash that will be used for Flash/JavaScript
+		communication (see "Flash Communication" below for information on the 
+		different kinds of Flash/JavaScript communication supported and how they 
+		depend on the version of Flash installed):
+		
+		dojo.flash.setSwf({flash6: "src/storage/storage_flash6.swf",
+											 flash8: "src/storage/storage_flash8.swf"});
+		
+		This will cause dojo.flash to pick the best way of communicating
+		between Flash and JavaScript based on the platform.
+		
+		If no SWF files are specified, then Flash is not initialized.
+		
+		Your Flash must use DojoExternalInterface to expose Flash methods and
+		to call JavaScript; see "Flash Communication" below for details.
+		
+		setSwf can take an optional 'visible' attribute to control whether
+		the Flash object is visible or not on the page; the default is visible:
+		
+		dojo.flash.setSwf({flash6: "src/storage/storage_flash6.swf",
+											 flash8: "src/storage/storage_flash8.swf",
+											 visible: false});
+		
+		Once finished, you can query Flash version information:
+		
+		dojo.flash.info.version
+		
+		Or can communicate with Flash methods that were exposed:
+		
+		var results = dojo.flash.comm.sayHello("Some Message");
+		
+		Only string values are currently supported for both arguments and
+		for return results. Everything will be cast to a string on both
+		the JavaScript and Flash sides.
+		
+		-------------------
+		Flash Communication
+		-------------------
+		
+		dojo.flash allows Flash/JavaScript communication in 
+		a way that can pass large amounts of data back and forth reliably and
+		very fast. The dojo.flash
+		framework encapsulates the specific way in which this communication occurs,
+		presenting a common interface to JavaScript irrespective of the underlying
+		Flash version.
+		
+		There are currently three major ways to do Flash/JavaScript communication
+		in the Flash community:
+		
+		1) Flash 6+ - Uses Flash methods, such as SetVariable and TCallLabel,
+		and the fscommand handler to do communication. Strengths: Very fast,
+		mature, and can send extremely large amounts of data; can do
+		synchronous method calls. Problems: Does not work on Safari; works on 
+		Firefox/Mac OS X only if Flash 8 plugin is installed; cryptic to work with.
+		
+		2) Flash 8+ - Uses ExternalInterface, which provides a way for Flash
+		methods to register themselves for callbacks from JavaScript, and a way
+		for Flash to call JavaScript. Strengths: Works on Safari; elegant to
+		work with; can do synchronous method calls. Problems: Extremely buggy 
+		(fails if there are new lines in the data, for example); performance
+		degrades drastically in O(n^2) time as data grows; locks up the browser while
+		it is communicating; does not work in Internet Explorer if Flash
+		object is dynamically added to page with document.writeln, DOM methods,
+		or innerHTML.
+		
+		3) Flash 6+ - Uses two seperate Flash applets, one that we 
+		create over and over, passing input data into it using the PARAM tag, 
+		which then uses a Flash LocalConnection to pass the data to the main Flash
+		applet; communication back to Flash is accomplished using a getURL
+		call with a javascript protocol handler, such as "javascript:myMethod()".
+		Strengths: the most cross browser, cross platform pre-Flash 8 method
+		of Flash communication known; works on Safari. Problems: Timing issues;
+		clunky and complicated; slow; can only send very small amounts of
+		data (several K); all method calls are asynchronous.
+		
+		dojo.flash.comm uses only the first two methods. This framework
+		was created primarily for dojo.storage, which needs to pass very large
+		amounts of data synchronously and reliably across the Flash/JavaScript
+		boundary. We use the first method, the Flash 6 method, on all platforms
+		that support it, while using the Flash 8 ExternalInterface method
+		only on Safari with some special code to help correct ExternalInterface's
+		bugs.
+		
+		Since dojo.flash needs to have two versions of the Flash
+		file it wants to generate, a Flash 6 and a Flash 8 version to gain
+		true cross-browser compatibility, several tools are provided to ease
+		development on the Flash side.
+		
+		In your Flash file, if you want to expose Flash methods that can be
+		called, use the DojoExternalInterface class to register methods. This
+		class is an exact API clone of the standard ExternalInterface class, but
+		can work in Flash 6+ browsers. Under the covers it uses the best
+		mechanism to do communication:
+		
+		class HelloWorld{
+			function HelloWorld(){
+				// Initialize the DojoExternalInterface class
+				DojoExternalInterface.initialize();
+				
+				// Expose your methods
+				DojoExternalInterface.addCallback("sayHello", this, this.sayHello);
+				
+				// Tell JavaScript that you are ready to have method calls
+				DojoExternalInterface.loaded();
+				
+				// Call some JavaScript
+				var resultsReady = function(results){
+					trace("Received the following results from JavaScript: " + results);
+				}
+				DojoExternalInterface.call("someJavaScriptMethod", resultsReady, 
+																	 someParameter);
+			}
+			
+			function sayHello(){ ... }
+			
+			static main(){ ... }
+		}
+		
+		DojoExternalInterface adds two new functions to the ExternalInterface
+		API: initialize() and loaded(). initialize() must be called before
+		any addCallback() or call() methods are run, and loaded() must be
+		called after you are finished adding your callbacks. Calling loaded()
+		will fire the dojo.flash.loaded() event, so that JavaScript can know that
+		Flash has finished loading and adding its callbacks, and can begin to
+		interact with the Flash file.
+		
+		To generate your SWF files, use the ant task
+		"buildFlash". You must have the open source Motion Twin ActionScript 
+		compiler (mtasc) installed and in your path to use the "buildFlash"
+		ant task; download and install mtasc from http://www.mtasc.org/.
+		
+		
+		
+		buildFlash usage:
+		
+		ant buildFlash -Ddojo.flash.file=../tests/flash/HelloWorld.as
+		
+		where "dojo.flash.file" is the relative path to your Flash 
+		ActionScript file.
+		
+		This will generate two SWF files, one ending in _flash6.swf and the other
+		ending in _flash8.swf in the same directory as your ActionScript method:
+		
+		HelloWorld_flash6.swf
+		HelloWorld_flash8.swf
+		
+		Initialize dojo.flash with the filename and Flash communication version to
+		use during page load; see the documentation for dojo.flash for details:
+		
+		dojo.flash.setSwf({flash6: "tests/flash/HelloWorld_flash6.swf",
+											 flash8: "tests/flash/HelloWorld_flash8.swf"});
+		
+		Now, your Flash methods can be called from JavaScript as if they are native
+		Flash methods, mirrored exactly on the JavaScript side:
+		
+		dojo.flash.comm.sayHello();
+		
+		Only Strings are supported being passed back and forth currently.
+		
+		JavaScript to Flash communication is synchronous; i.e., results are returned
+		directly from the method call:
+		
+		var results = dojo.flash.comm.sayHello();
+		
+		Flash to JavaScript communication is asynchronous due to limitations in
+		the underlying technologies; you must use a results callback to handle
+		results returned by JavaScript in your Flash AS files:
+		
+		var resultsReady = function(results){
+			trace("Received the following results from JavaScript: " + results);
+		}
+		DojoExternalInterface.call("someJavaScriptMethod", resultsReady);
+		
+		
+		
+		-------------------
+		Notes
+		-------------------
+		
+		If you have both Flash 6 and Flash 8 versions of your file:
+		
+		dojo.flash.setSwf({flash6: "tests/flash/HelloWorld_flash6.swf",
+											 flash8: "tests/flash/HelloWorld_flash8.swf"});
+											 
+		but want to force the browser to use a certain version of Flash for
+		all platforms (for testing, for example), use the djConfig
+		variable 'forceFlashComm' with the version number to force:
+		
+		var djConfig = { forceFlashComm: 6 };
+		
+		Two values are currently supported, 6 and 8, for the two styles of
+		communication described above. Just because you force dojo.flash
+		to use a particular communication style is no guarantee that it will
+		work; for example, Flash 8 communication doesn't work in Internet
+		Explorer due to bugs in Flash, and Flash 6 communication does not work
+		in Safari. It is best to let dojo.flash determine the best communication
+		mechanism, and to use the value above only for debugging the dojo.flash
+		framework itself.
+		
+		Also note that dojo.flash can currently only work with one Flash object
+		on the page; it and the API do not yet support multiple Flash objects on
+		the same page.
+		
+		We use some special tricks to get decent, linear performance
+		out of Flash 8's ExternalInterface on Safari; see the blog
+		post 
+		http://codinginparadise.org/weblog/2006/02/how-to-speed-up-flash-8s.html
+		for details.
+		
+		Your code can detect whether the Flash player is installing or having
+		its version revved in two ways. First, if dojo.flash detects that
+		Flash installation needs to occur, it sets dojo.flash.info.installing
+		to true. Second, you can detect if installation is necessary with the
+		following callback:
+		
+		dojo.event.connect(dojo.flash, "installing", myInstance, "myCallback");
+		
+		You can use this callback to delay further actions that might need Flash;
+		when installation is finished the full page will be refreshed and the
+		user will be placed back on your page with Flash installed.
+		
+		Two utility methods exist if you want to add loading and installing
+		listeners without creating dependencies on dojo.event; these are
+		'addLoadingListener' and 'addInstallingListener'.
+		
+		-------------------
+		Todo/Known Issues
+		-------------------
+
+		There are several tasks I was not able to do, or did not need to fix
+		to get dojo.storage out:		
+		
+		* When using Flash 8 communication, Flash method calls to JavaScript
+		are not working properly; serialization might also be broken for certain
+		invalid characters when it is Flash invoking JavaScript methods.
+		The Flash side needs to have more sophisticated serialization/
+		deserialization mechanisms like JavaScript currently has. The
+		test_flash2.html unit tests should also be updated to have much more
+		sophisticated Flash to JavaScript unit tests, including large
+		amounts of data.
+		
+		* On Internet Explorer, after doing a basic install, the page is
+		not refreshed or does not detect that Flash is now available. The way
+		to fix this is to create a custom small Flash file that is pointed to
+		during installation; when it is finished loading, it does a callback
+		that says that Flash installation is complete on IE, and we can proceed
+		to initialize the dojo.flash subsystem.
+		
+		@author Brad Neuberg, bkn3@columbia.edu
+*/
+
+dojo.flash = {
+	flash6_version: null,
+	flash8_version: null,
+	ready: false,
+	_visible: true,
+	_loadedListeners: new Array(),
+	_installingListeners: new Array(),
+	
+	/** Sets the SWF files and versions we are using. */
+	setSwf: function(fileInfo){
+		//dojo.debug("setSwf");
+		if(fileInfo == null || dojo.lang.isUndefined(fileInfo)){
+			return;
+		}
+		
+		if(fileInfo.flash6 != null && !dojo.lang.isUndefined(fileInfo.flash6)){
+			this.flash6_version = fileInfo.flash6;
+		}
+		
+		if(fileInfo.flash8 != null && !dojo.lang.isUndefined(fileInfo.flash8)){
+			this.flash8_version = fileInfo.flash8;
+		}
+		
+		if(!dojo.lang.isUndefined(fileInfo.visible)){
+			this._visible = fileInfo.visible;
+		}
+		
+		// initialize ourselves		
+		this._initialize();
+	},
+	
+	/** Returns whether we are using Flash 6 for communication on this platform. */
+	useFlash6: function(){
+		if(this.flash6_version == null){
+			return false;
+		}else if (this.flash6_version != null && dojo.flash.info.commVersion == 6){
+			// if we have a flash 6 version of this SWF, and this browser supports 
+			// communicating using Flash 6 features...
+			return true;
+		}else{
+			return false;
+		}
+	},
+	
+	/** Returns whether we are using Flash 8 for communication on this platform. */
+	useFlash8: function(){
+		if(this.flash8_version == null){
+			return false;
+		}else if (this.flash8_version != null && dojo.flash.info.commVersion == 8){
+			// if we have a flash 8 version of this SWF, and this browser supports
+			// communicating using Flash 8 features...
+			return true;
+		}else{
+			return false;
+		}
+	},
+	
+	/** Adds a listener to know when Flash is finished loading. 
+			Useful if you don't want a dependency on dojo.event. */
+	addLoadedListener: function(listener){
+		this._loadedListeners.push(listener);
+	},
+
+	/** Adds a listener to know if Flash is being installed. 
+			Useful if you don't want a dependency on dojo.event. */
+	addInstallingListener: function(listener){
+		this._installingListeners.push(listener);
+	},	
+	
+	/** 
+			A callback when the Flash subsystem is finished loading and can be
+			worked with. To be notified when Flash is finished loading, connect
+			your callback to this method using the following:
+			
+			dojo.event.connect(dojo.flash, "loaded", myInstance, "myCallback");
+	*/
+	loaded: function(){
+		//dojo.debug("dojo.flash.loaded");
+		dojo.flash.ready = true;
+		if(dojo.flash._loadedListeners.length > 0){
+			for(var i = 0;i < dojo.flash._loadedListeners.length; i++){
+				dojo.flash._loadedListeners[i].call(null);
+			}
+		}
+	},
+	
+	/** 
+			A callback to know if Flash is currently being installed or
+			having its version revved. To be notified if Flash is installing, connect
+			your callback to this method using the following:
+			
+			dojo.event.connect(dojo.flash, "installing", myInstance, "myCallback");
+	*/
+	installing: function(){
+	 //dojo.debug("installing");
+	 if(dojo.flash._installingListeners.length > 0){
+			for(var i = 0; i < dojo.flash._installingListeners.length; i++){
+				dojo.flash._installingListeners[i].call(null);
+			}
+		}
+	},
+	
+	/** Initializes dojo.flash. */
+	_initialize: function(){
+		//dojo.debug("dojo.flash._initialize");
+		// see if we need to rev or install Flash on this platform
+		var installer = new dojo.flash.Install();
+		dojo.flash.installer = installer;
+
+		if(installer.needed() == true){		
+			installer.install();
+		}else{
+			//dojo.debug("Writing object out");
+			// write the flash object into the page
+			dojo.flash.obj = new dojo.flash.Embed(this._visible);
+			dojo.flash.obj.write(dojo.flash.info.commVersion);
+			
+			// initialize the way we do Flash/JavaScript communication
+			dojo.flash.comm = new dojo.flash.Communicator();
+		}
+	}
+};
+
+
+/** 
+		A class that helps us determine whether Flash is available,
+		it's major and minor versions, and what Flash version features should
+		be used for Flash/JavaScript communication. Parts of this code
+		are adapted from the automatic Flash plugin detection code autogenerated 
+		by the Macromedia Flash 8 authoring environment. 
+		
+		An instance of this class can be accessed on dojo.flash.info after
+		the page is finished loading.
+		
+		This constructor must be called before the page is finished loading. 
+*/
+dojo.flash.Info = function(){
+	// Visual basic helper required to detect Flash Player ActiveX control 
+	// version information on Internet Explorer
+	if(dojo.render.html.ie){
+		document.writeln('<script language="VBScript" type="text/vbscript"\>');
+		document.writeln('Function VBGetSwfVer(i)');
+		document.writeln('  on error resume next');
+		document.writeln('  Dim swControl, swVersion');
+		document.writeln('  swVersion = 0');
+		document.writeln('  set swControl = CreateObject("ShockwaveFlash.ShockwaveFlash." + CStr(i))');
+		document.writeln('  if (IsObject(swControl)) then');
+		document.writeln('    swVersion = swControl.GetVariable("$version")');
+		document.writeln('  end if');
+		document.writeln('  VBGetSwfVer = swVersion');
+		document.writeln('End Function');
+		document.writeln('</script\>');
+	}
+	
+	this._detectVersion();
+	this._detectCommunicationVersion();
+}
+
+dojo.flash.Info.prototype = {
+	/** The full version string, such as "8r22". */
+	version: -1,
+	
+	/** 
+			The major, minor, and revisions of the plugin. For example, if the
+			plugin is 8r22, then the major version is 8, the minor version is 0,
+			and the revision is 22. 
+	*/
+	versionMajor: -1,
+	versionMinor: -1,
+	versionRevision: -1,
+	
+	/** Whether this platform has Flash already installed. */
+	capable: false,
+	
+	/** 
+			The major version number for how our Flash and JavaScript communicate.
+			This can currently be the following values:
+			6 - We use a combination of the Flash plugin methods, such as SetVariable
+			and TCallLabel, along with fscommands, to do communication.
+			8 - We use the ExternalInterface API. 
+			-1 - For some reason neither method is supported, and no communication
+			is possible. 
+	*/
+	commVersion: 6,
+	
+	/** Set if we are in the middle of a Flash installation session. */
+	installing: false,
+	
+	/** 
+			Asserts that this environment has the given major, minor, and revision
+			numbers for the Flash player. Returns true if the player is equal
+			or above the given version, false otherwise.
+			
+			Example: To test for Flash Player 7r14:
+			
+			dojo.flash.info.isVersionOrAbove(7, 0, 14)
+	*/
+	isVersionOrAbove: function(reqMajorVer, reqMinorVer, reqVer){
+		// make the revision a decimal (i.e. transform revision 14 into
+		// 0.14
+		reqVer = parseFloat("." + reqVer);
+		
+		if(this.versionMajor >= reqMajorVer && this.versionMinor >= reqMinorVer
+			 && this.versionRevision >= reqVer){
+			return true;
+		}else{
+			return false;
+		}
+	},
+	
+	_detectVersion: function(){
+		var versionStr;
+		
+		// loop backwards through the versions until we find the newest version	
+		for(var testVersion = 25; testVersion > 0; testVersion--){
+			if(dojo.render.html.ie){
+				versionStr = VBGetSwfVer(testVersion);
+			}else{
+				versionStr = this._JSFlashInfo(testVersion);		
+			}
+				
+			if(versionStr == -1 ){
+				this.capable = false; 
+				return;
+			}else if(versionStr != 0){
+				var versionArray;
+				if(dojo.render.html.ie){
+					var tempArray = versionStr.split(" ");
+					var tempString = tempArray[1];
+					versionArray = tempString.split(",");
+				}else{
+					versionArray = versionStr.split(".");
+				}
+					
+				this.versionMajor = versionArray[0];
+				this.versionMinor = versionArray[1];
+				this.versionRevision = versionArray[2];
+				
+				// 7.0r24 == 7.24
+				var versionString = this.versionMajor + "." + this.versionRevision;
+				this.version = parseFloat(versionString);
+				
+				this.capable = true;
+				
+				break;
+			}
+		}
+	},
+	
+	/** 
+			JavaScript helper required to detect Flash Player PlugIn version 
+			information. Internet Explorer uses a corresponding Visual Basic
+			version to interact with the Flash ActiveX control. 
+	*/
+	_JSFlashInfo: function(testVersion){
+		// NS/Opera version >= 3 check for Flash plugin in plugin array
+		if(navigator.plugins != null && navigator.plugins.length > 0){
+			if(navigator.plugins["Shockwave Flash 2.0"] || 
+				 navigator.plugins["Shockwave Flash"]){
+				var swVer2 = navigator.plugins["Shockwave Flash 2.0"] ? " 2.0" : "";
+				var flashDescription = navigator.plugins["Shockwave Flash" + swVer2].description;
+				var descArray = flashDescription.split(" ");
+				var tempArrayMajor = descArray[2].split(".");
+				var versionMajor = tempArrayMajor[0];
+				var versionMinor = tempArrayMajor[1];
+				if(descArray[3] != ""){
+					var tempArrayMinor = descArray[3].split("r");
+				}else{
+					var tempArrayMinor = descArray[4].split("r");
+				}
+				var versionRevision = tempArrayMinor[1] > 0 ? tempArrayMinor[1] : 0;
+				var version = versionMajor + "." + versionMinor + "." 
+											+ versionRevision;
+											
+				return version;
+			}
+		}
+		
+		return -1;
+	},
+	
+	/** 
+			Detects the mechanisms that should be used for Flash/JavaScript 
+			communication, setting 'commVersion' to either 6 or 8. If the value is
+			6, we use Flash Plugin 6+ features, such as GetVariable, TCallLabel,
+			and fscommand, to do Flash/JavaScript communication; if the value is
+			8, we use the ExternalInterface API for communication. 
+	*/
+	_detectCommunicationVersion: function(){
+		if(this.capable == false){
+			this.commVersion = null;
+			return;
+		}
+		
+		// detect if the user has over-ridden the default flash version
+		if (typeof djConfig["forceFlashComm"] != "undefined" &&
+				typeof djConfig["forceFlashComm"] != null){
+			this.commVersion = djConfig["forceFlashComm"];
+			return;
+		}
+		
+		// we prefer Flash 6 features over Flash 8, because they are much faster
+		// and much less buggy
+		
+		// at this point, we don't have a flash file to detect features on,
+		// so we need to instead look at the browser environment we are in
+		if(dojo.render.html.safari == true || dojo.render.html.opera == true){
+			this.commVersion = 8;
+		}else{
+			this.commVersion = 6;
+		}
+	}
+};
+
+/** A class that is used to write out the Flash object into the page. */
+dojo.flash.Embed = function(visible){
+	this._visible = visible;
+}
+
+dojo.flash.Embed.prototype = {
+	/** 
+			The width of this Flash applet. The default is the minimal width
+			necessary to show the Flash settings dialog. 
+	*/
+	width: 215,
+	
+	/** 
+			The height of this Flash applet. The default is the minimal height
+			necessary to show the Flash settings dialog. 
+	*/
+	height: 138,
+	
+	/** The id of the Flash object. */
+	id: "flashObject",
+	
+	/** Controls whether this is a visible Flash applet or not. */
+	_visible: true,
+			
+	/** 
+			Writes the Flash into the page. This must be called before the page
+			is finished loading. 
+			@param flashVer The Flash version to write.
+			@param doExpressInstall Whether to write out Express Install
+			information. Optional value; defaults to false.
+	*/
+	write: function(flashVer, doExpressInstall){
+		//dojo.debug("write");
+		if(dojo.lang.isUndefined(doExpressInstall)){
+			doExpressInstall = false;
+		}
+		
+		// determine our container div's styling
+		var containerStyle = new dojo.string.Builder();
+		containerStyle.append("width: " + this.width + "px; ");
+		containerStyle.append("height: " + this.height + "px; ");
+		if(this._visible == false){
+			containerStyle.append("position: absolute; ");
+			containerStyle.append("z-index: 10000; ");
+			containerStyle.append("top: -1000px; ");
+			containerStyle.append("left: -1000px; ");
+		}
+		containerStyle = containerStyle.toString();
+
+		// figure out the SWF file to get and how to write out the correct HTML
+		// for this Flash version
+		var objectHTML;
+		var swfloc;
+		// Flash 6
+		if(flashVer == 6){
+			swfloc = dojo.flash.flash6_version;
+			var dojoPath = djConfig.baseRelativePath;
+			swfloc = swfloc + "?baseRelativePath=" + escape(dojoPath);
+			
+			objectHTML = 
+						  '<embed id="' + this.id + '" src="' + swfloc + '" '
+						+ '    quality="high" bgcolor="#ffffff" '
+						+ '    width="' + this.width + '" height="' + this.height + '" '
+						+ '    name="' + this.id + '" '
+						+ '    align="middle" allowScriptAccess="sameDomain" '
+						+ '    type="application/x-shockwave-flash" swLiveConnect="true" '
+						+ '    pluginspage="http://www.macromedia.com/go/getflashplayer">';
+		}else{ // Flash 8
+			swfloc = dojo.flash.flash8_version;
+			var swflocObject = swfloc;
+			var swflocEmbed = swfloc;
+			var dojoPath = djConfig.baseRelativePath;
+			if(doExpressInstall){
+				// the location to redirect to after installing
+				var redirectURL = escape(window.location);
+				document.title = document.title.slice(0, 47) + " - Flash Player Installation";
+				var docTitle = escape(document.title);
+				swflocObject += "?MMredirectURL=" + redirectURL
+				                + "&MMplayerType=ActiveX"
+				                + "&MMdoctitle=" + docTitle
+								+ "&baseRelativePath=" + escape(dojoPath);
+				swflocEmbed += "?MMredirectURL=" + redirectURL 
+								+ "&MMplayerType=PlugIn"
+								+ "&baseRelativePath=" + escape(dojoPath);
+			}
+			
+			objectHTML =
+				'<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" '
+				  + 'codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" '
+				  + 'width="' + this.width + '" '
+				  + 'height="' + this.height + '" '
+				  + 'id="' + this.id + '" '
+				  + 'align="middle"> '
+				  + '<param name="allowScriptAccess" value="sameDomain" /> '
+				  + '<param name="movie" value="' + swflocObject + '" /> '
+				  + '<param name="quality" value="high" /> '
+				  + '<param name="bgcolor" value="#ffffff" /> '
+				  + '<embed src="' + swflocEmbed + '" '
+				  + 'quality="high" '
+				  + 'bgcolor="#ffffff" '
+				  + 'width="' + this.width + '" '
+				  + 'height="' + this.height + '" '
+				  + 'id="' + this.id + '" '
+				  + 'name="' + this.id + '" '
+				  + 'swLiveConnect="true" '
+				  + 'align="middle" '
+				  + 'allowScriptAccess="sameDomain" '
+				  + 'type="application/x-shockwave-flash" '+ "&baseRelativePath=" + escape(dojoPath);
+				  + 'pluginspage="http://www.macromedia.com/go/getflashplayer" />'
+				+ '</object>';
+		}
+
+		// now write everything out
+		objectHTML = '<div id="' + this.id + 'Container" style="' + containerStyle + '"> '
+						+ objectHTML
+					 + '</div>';
+		document.writeln(objectHTML);
+	},  
+	
+	/** Gets the Flash object DOM node. */
+	get: function(){
+		//return (dojo.render.html.ie) ? window[this.id] : document[this.id];
+		
+		// more robust way to get Flash object; version above can break
+		// communication on IE sometimes
+		return document.getElementById(this.id);
+	},
+	
+	/** Sets the visibility of this Flash object. */
+	setVisible: function(visible){
+		var container = dojo.byId(this.id + "Container");
+		if(visible == true){
+			container.style.visibility = "visible";
+		}else{
+			container.style.position = "absolute";
+			container.style.x = "-1000px";
+			container.style.y = "-1000px";
+			container.style.visibility = "hidden";
+		}
+	},
+	
+	/** Centers the flash applet on the page. */
+	center: function(){
+		// FIXME: replace this with Dojo's centering code rather than our own
+		// We want to center the Flash applet vertically and horizontally
+		var elementWidth = this.width;
+		var elementHeight = this.height;
+    
+		// get the browser width and height; the code below
+		// works in IE and Firefox in compatibility, non-strict
+		// mode
+		var browserWidth = document.body.clientWidth;
+		var browserHeight = document.body.clientHeight;
+    
+		// in Firefox if we are in standards compliant mode
+		// (with a strict doctype), then the browser width
+		// and height have to be computed from the root level
+		// HTML element not the BODY element
+		if(!dojo.render.html.ie && document.compatMode == "CSS1Compat"){
+			browserWidth = document.body.parentNode.clientWidth;
+			browserHeight = document.body.parentNode.clientHeight;
+		}else if(dojo.render.html.ie && document.compatMode == "CSS1Compat"){
+			// IE 6 in standards compliant mode has to be calculated
+			// differently
+			browserWidth = document.documentElement.clientWidth;
+			browserHeight = document.documentElement.clientHeight;
+		}else if(dojo.render.html.safari){ // Safari works different
+			browserHeight = self.innerHeight;
+		}
+    
+		// get where we are scrolled to in the document
+		// the code below works in FireFox
+		var scrolledByWidth = window.scrollX;
+		var scrolledByHeight = window.scrollY;
+		// compute these values differently for IE;
+		// IE has two possibilities; it is either in standards
+		// compatibility mode or it is not
+		if(typeof scrolledByWidth == "undefined"){
+			if(document.compatMode == "CSS1Compat"){ // standards mode
+				scrolledByWidth = document.documentElement.scrollLeft;
+				scrolledByHeight = document.documentElement.scrollTop;
+			}else{ // Pre IE6 non-standards mode
+				scrolledByWidth = document.body.scrollLeft;
+				scrolledByHeight = document.body.scrollTop;
+			}
+		}
+
+		// compute the centered position    
+		var x = scrolledByWidth + (browserWidth - elementWidth) / 2;
+		var y = scrolledByHeight + (browserHeight - elementHeight) / 2; 
+
+		// set the centered position
+		var container = dojo.byId(this.id + "Container");
+		container.style.top = y + "px";
+		container.style.left = x + "px";
+	}
+};
+
+
+/** 
+		A class that is used to communicate between Flash and JavaScript in 
+		a way that can pass large amounts of data back and forth reliably,
+		very fast, and with synchronous method calls. This class encapsulates the 
+		specific way in which this communication occurs,
+		presenting a common interface to JavaScript irrespective of the underlying
+		Flash version.
+*/
+dojo.flash.Communicator = function(){
+	if(dojo.flash.useFlash6()){
+		this._writeFlash6();
+	}else if (dojo.flash.useFlash8()){
+		this._writeFlash8();
+	}
+}
+
+dojo.flash.Communicator.prototype = {
+	_writeFlash6: function(){
+		var id = dojo.flash.obj.id;
+		
+		// global function needed for Flash 6 callback;
+		// we write it out as a script tag because the VBScript hook for IE
+		// callbacks does not work properly if this function is evalled() from
+		// within the Dojo system
+		document.writeln('<script language="JavaScript">');
+		document.writeln('  function ' + id + '_DoFSCommand(command, args){ ');
+		document.writeln('    dojo.flash.comm._handleFSCommand(command, args); ');
+		document.writeln('}');
+		document.writeln('</script>');
+		
+		// hook for Internet Explorer to receive FSCommands from Flash
+		if(dojo.render.html.ie){
+			document.writeln('<SCRIPT LANGUAGE=VBScript\> ');
+			document.writeln('on error resume next ');
+			document.writeln('Sub ' + id + '_FSCommand(ByVal command, ByVal args)');
+			document.writeln(' call ' + id + '_DoFSCommand(command, args)');
+			document.writeln('end sub');
+			document.writeln('</SCRIPT\> ');
+		}
+	},
+	
+	_writeFlash8: function(){
+		// nothing needs to be written out for Flash 8 communication; 
+		// happens automatically
+	},
+	
+	/** Flash 6 communication. */
+	
+	/** Handles fscommand's from Flash to JavaScript. Flash 6 communication. */
+	_handleFSCommand: function(command, args){
+		//dojo.debug("fscommand, command="+command+", args="+args);
+		// Flash 8 on Mac/Firefox precedes all commands with the string "FSCommand:";
+		// strip it off if it is present
+		if(command != null && !dojo.lang.isUndefined(command)
+			&& /^FSCommand:(.*)/.test(command) == true){
+			command = command.match(/^FSCommand:(.*)/)[1];
+		}
+		 
+		if(command == "addCallback"){ // add Flash method for JavaScript callback
+			this._fscommandAddCallback(command, args);
+		}else if(command == "call"){ // Flash to JavaScript method call
+			this._fscommandCall(command, args);
+		}else if(command == "fscommandReady"){ // see if fscommands are ready
+			this._fscommandReady();
+		}
+	},
+	
+	/** Handles registering a callable Flash function. Flash 6 communication. */
+	_fscommandAddCallback: function(command, args){
+		var functionName = args;
+			
+		// do a trick, where we link this function name to our wrapper
+		// function, _call, that does the actual JavaScript to Flash call
+		var callFunc = function(){
+			return dojo.flash.comm._call(functionName, arguments);
+		};			
+		dojo.flash.comm[functionName] = callFunc;
+		
+		// indicate that the call was successful
+		dojo.flash.obj.get().SetVariable("_succeeded", true);
+	},
+	
+	/** Handles Flash calling a JavaScript function. Flash 6 communication. */
+	_fscommandCall: function(command, args){
+		var plugin = dojo.flash.obj.get();
+		var functionName = args;
+		
+		// get the number of arguments to this method call and build them up
+		var numArgs = parseInt(plugin.GetVariable("_numArgs"));
+		var flashArgs = new Array();
+		for(var i = 0; i < numArgs; i++){
+			var currentArg = plugin.GetVariable("_" + i);
+			flashArgs.push(currentArg);
+		}
+		
+		// get the function instance; we technically support more capabilities
+		// than ExternalInterface, which can only call global functions; if
+		// the method name has a dot in it, such as "dojo.flash.loaded", we
+		// eval it so that the method gets run against an instance
+		var runMe;
+		if(functionName.indexOf(".") == -1){ // global function
+			runMe = window[functionName];
+		}else{
+			// instance function
+			runMe = eval(functionName);
+		}
+		
+		// make the call and get the results
+		var results = null;
+		if(!dojo.lang.isUndefined(runMe) && runMe != null){
+			results = runMe.apply(null, flashArgs);
+		}
+		
+		// return the results to flash
+		plugin.SetVariable("_returnResult", results);
+	},
+	
+	/** Reports that fscommands are ready to run if executed from Flash. */
+	_fscommandReady: function(){
+		var plugin = dojo.flash.obj.get();
+		plugin.SetVariable("fscommandReady", "true");
+	},
+	
+	/** 
+			The actual function that will execute a JavaScript to Flash call; used
+			by the Flash 6 communication method. 
+	*/
+	_call: function(functionName, args){
+		// we do JavaScript to Flash method calls by setting a Flash variable
+		// "_functionName" with the function name; "_numArgs" with the number
+		// of arguments; and "_0", "_1", etc for each numbered argument. Flash
+		// reads these, executes the function call, and returns the result
+		// in "_returnResult"
+		var plugin = dojo.flash.obj.get();
+		plugin.SetVariable("_functionName", functionName);
+		plugin.SetVariable("_numArgs", args.length);
+		for(var i = 0; i < args.length; i++){
+			// unlike Flash 8's ExternalInterface, Flash 6 has no problem with
+			// any special characters _except_ for the null character \0; double
+			// encode this so the Flash side never sees it, but we can get it 
+			// back if the value comes back to JavaScript
+			var value = args[i];
+			value = value.replace(/\0/g, "\\0");
+			
+			plugin.SetVariable("_" + i, value);
+		}
+		
+		// now tell Flash to execute this method using the Flash Runner
+		plugin.TCallLabel("/_flashRunner", "execute");
+		
+		// get the results
+		var results = plugin.GetVariable("_returnResult");
+		
+		// we double encoded all null characters as //0 because Flash breaks
+		// if they are present; turn the //0 back into /0
+		results = results.replace(/\\0/g, "\0");
+		
+		return results;
+	},
+	
+	/** Flash 8 communication. */
+	
+	/** 
+			Registers the existence of a Flash method that we can call with
+			JavaScript, using Flash 8's ExternalInterface. 
+	*/
+	_addExternalInterfaceCallback: function(methodName){
+		var wrapperCall = function(){
+			// some browsers don't like us changing values in the 'arguments' array, so
+			// make a fresh copy of it
+			var methodArgs = new Array(arguments.length);
+			for(var i = 0; i < arguments.length; i++){
+				methodArgs[i] = arguments[i];
+			}
+			return dojo.flash.comm._execFlash(methodName, methodArgs);
+		};
+		
+		dojo.flash.comm[methodName] = wrapperCall;
+	},
+	
+	/** 
+			Encodes our data to get around ExternalInterface bugs.
+			Flash 8 communication.
+	*/
+	_encodeData: function(data){
+		// double encode all entity values, or they will be mis-decoded
+		// by Flash when returned
+		var entityRE = /\&([^;]*)\;/g;
+		data = data.replace(entityRE, "&amp;$1;");
+		
+		// entity encode XML-ish characters, or Flash's broken XML serializer
+		// breaks
+		data = data.replace(/</g, "&lt;");
+		data = data.replace(/>/g, "&gt;");
+		
+		// transforming \ into \\ doesn't work; just use a custom encoding
+		data = data.replace("\\", "&custom_backslash;&custom_backslash;");
+		
+		data = data.replace(/\n/g, "\\n");
+		data = data.replace(/\r/g, "\\r");
+		data = data.replace(/\f/g, "\\f");
+		data = data.replace(/\0/g, "\\0"); // null character
+		data = data.replace(/\'/g, "\\\'");
+		data = data.replace(/\"/g, '\\\"');
+		
+		return data;
+	},
+	
+	/** 
+			Decodes our data to get around ExternalInterface bugs.
+			Flash 8 communication.
+	*/
+	_decodeData: function(data){
+		if(data == null || typeof data == "undefined"){
+			return data;
+		}
+		
+		// certain XMLish characters break Flash's wire serialization for
+		// ExternalInterface; these are encoded on the 
+		// DojoExternalInterface side into a custom encoding, rather than
+		// the standard entity encoding, because otherwise we won't be able to
+		// differentiate between our own encoding and any entity characters
+		// that are being used in the string itself
+		data = data.replace(/\&custom_lt\;/g, "<");
+		data = data.replace(/\&custom_gt\;/g, ">");
+		
+		// Unfortunately, Flash returns us our String with special characters
+		// like newlines broken into seperate characters. So if \n represents
+		// a new line, Flash returns it as "\" and "n". This means the character
+		// is _not_ a newline. This forces us to eval() the string to cause
+		// escaped characters to turn into their real special character values.
+		data = eval('"' + data + '"');
+		
+		return data;
+	},
+	
+	/** 
+			Sends our method arguments over to Flash in chunks in order to
+			have ExternalInterface's performance not be O(n^2).
+			Flash 8 communication.
+	*/
+	_chunkArgumentData: function(value, argIndex){
+		var plugin = dojo.flash.obj.get();
+		
+		// cut up the string into pieces, and push over each piece one
+		// at a time
+		var numSegments = Math.ceil(value.length / 1024);
+		for(var i = 0; i < numSegments; i++){
+			var startCut = i * 1024;
+			var endCut = i * 1024 + 1024;
+			if(i == (numSegments - 1)){
+				endCut = i * 1024 + value.length;
+			}
+			
+			var piece = value.substring(startCut, endCut);
+			
+			// encode each piece seperately, rather than the entire
+			// argument data, because ocassionally a special 
+			// character, such as an entity like &foobar;, will fall between
+			// piece boundaries, and we _don't_ want to encode that value if
+			// it falls between boundaries, or else we will end up with incorrect
+			// data when we patch the pieces back together on the other side
+			piece = this._encodeData(piece);
+			
+			// directly use the underlying CallFunction method used by
+			// ExternalInterface, which is vastly faster for large strings
+			// and lets us bypass some Flash serialization bugs
+			plugin.CallFunction('<invoke name="chunkArgumentData" '
+														+ 'returntype="javascript">'
+														+ '<arguments>'
+														+ '<string>' + piece + '</string>'
+														+ '<number>' + argIndex + '</number>'
+														+ '</arguments>'
+														+ '</invoke>');
+		}
+	},
+	
+	/** 
+			Gets our method return data in chunks for better performance.
+			Flash 8 communication.
+	*/
+	_chunkReturnData: function(){
+		var plugin = dojo.flash.obj.get();
+		
+		var numSegments = plugin.getReturnLength();
+		var resultsArray = new Array();
+		for(var i = 0; i < numSegments; i++){
+			// directly use the underlying CallFunction method used by
+			// ExternalInterface, which is vastly faster for large strings
+			var piece = 
+					plugin.CallFunction('<invoke name="chunkReturnData" '
+															+ 'returntype="javascript">'
+															+ '<arguments>'
+															+ '<number>' + i + '</number>'
+															+ '</arguments>'
+															+ '</invoke>');
+															
+			// remove any leading or trailing JavaScript delimiters, which surround
+			// our String when it comes back from Flash since we bypass Flash's
+			// deserialization routines by directly calling CallFunction on the
+			// plugin
+			if(piece == '""' || piece == "''"){
+				piece = "";
+			}else{
+				piece = piece.substring(1, piece.length-1);
+			}
+		
+			resultsArray.push(piece);
+		}
+		var results = resultsArray.join("");
+		
+		return results;
+	},
+	
+	/** 
+			Executes a Flash method; called from the JavaScript wrapper proxy we
+			create on dojo.flash.comm.
+			Flash 8 communication.
+	*/
+	_execFlash: function(methodName, methodArgs){
+		var plugin = dojo.flash.obj.get();
+				
+		// begin Flash method execution
+		plugin.startExec();
+		
+		// set the number of arguments
+		plugin.setNumberArguments(methodArgs.length);
+		
+		// chunk and send over each argument
+		for(var i = 0; i < methodArgs.length; i++){
+			this._chunkArgumentData(methodArgs[i], i);
+		}
+		
+		// execute the method
+		plugin.exec(methodName);
+														
+		// get the return result
+		var results = this._chunkReturnData();
+		
+		// decode the results
+		results = this._decodeData(results);
+		
+		// reset everything
+		plugin.endExec();
+		
+		return results;
+
+	}
+}
+
+/** 
+		Figures out the best way to automatically install the Flash plugin
+		for this browser and platform. Also determines if installation or
+		revving of the current plugin is needed on this platform.
+*/
+dojo.flash.Install = function(){
+}
+
+dojo.flash.Install.prototype = {
+	/** 
+			Determines if installation or revving of the current plugin is 
+			needed. 
+	*/
+	needed: function(){
+		// do we even have flash?
+		if(dojo.flash.info.capable == false){
+			return true;
+		}
+
+		// are we on the Mac? Safari needs Flash version 8 to do Flash 8
+		// communication, while Firefox/Mac needs Flash 8 to fix bugs it has
+		// with Flash 6 communication
+		if(dojo.render.os.mac == true && !dojo.flash.info.isVersionOrAbove(8, 0, 0)){
+			return true;
+		}
+
+		// other platforms need at least Flash 6 or above
+		if(!dojo.flash.info.isVersionOrAbove(6, 0, 0)){
+			return true;
+		}
+
+		// otherwise we don't need installation
+		return false;
+	},
+
+	/** Performs installation or revving of the Flash plugin. */
+	install: function(){
+		//dojo.debug("install");
+		// indicate that we are installing
+		dojo.flash.info.installing = true;
+		dojo.flash.installing();
+		
+		if(dojo.flash.info.capable == false){ // we have no Flash at all
+			//dojo.debug("Completely new install");
+			// write out a simple Flash object to force the browser to prompt
+			// the user to install things
+			var installObj = new dojo.flash.Embed(false);
+			installObj.write(8); // write out HTML for Flash 8 version+
+		}else if(dojo.flash.info.isVersionOrAbove(6, 0, 65)){ // Express Install
+			//dojo.debug("Express install");
+			var installObj = new dojo.flash.Embed(false);
+			installObj.write(8, true); // write out HTML for Flash 8 version+
+			installObj.setVisible(true);
+			installObj.center();
+		}else{ // older Flash install than version 6r65
+			alert("This content requires a more recent version of the Macromedia "
+						+" Flash Player.");
+			window.location.href = "http://www.macromedia.com/go/getflashplayer";
+		}
+	},
+	
+	/** 
+			Called when the Express Install is either finished, failed, or was
+			rejected by the user.
+	*/
+	_onInstallStatus: function(msg){
+		if (msg == "Download.Complete"){
+			// Installation is complete.
+			dojo.flash._initialize();
+		}else if(msg == "Download.Cancelled"){
+			alert("This content requires a more recent version of the Macromedia "
+						+" Flash Player.");
+			window.location.href = "http://www.macromedia.com/go/getflashplayer";
+		}else if (msg == "Download.Failed"){
+			// The end user failed to download the installer due to a network failure
+			alert("There was an error downloading the Flash Player update. "
+						+ "Please try again later, or visit macromedia.com to download "
+						+ "the latest version of the Flash plugin.");
+		}	
+	}
+}
+
+// find out if Flash is installed
+dojo.flash.info = new dojo.flash.Info();

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/flash/flash6/DojoExternalInterface.as
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/flash/flash6/DojoExternalInterface.as?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/flash/flash6/DojoExternalInterface.as (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/flash/flash6/DojoExternalInterface.as Sat Jun 10 06:59:28 2006
@@ -0,0 +1,214 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+/** 
+		An implementation of Flash 8's ExternalInterface that works with Flash 6
+		and which is source-compatible with Flash 8. 
+		
+		@author Brad Neuberg, bkn3@columbia.edu 
+*/
+
+class DojoExternalInterface{
+	public static var available:Boolean;
+	public static var dojoPath = "";
+	
+	public static var _fscommandReady = false;
+	public static var _callbacks = new Array();
+
+	public static function initialize(){ 
+		//getURL("javascript:dojo.debug('FLASH:DojoExternalInterface initialize')");
+		// FIXME: Set available variable by testing for capabilities
+		DojoExternalInterface.available = true;
+		
+		// extract the dojo base path
+		DojoExternalInterface.dojoPath = DojoExternalInterface.getDojoPath();
+		//getURL("javascript:dojo.debug('FLASH:dojoPath="+DojoExternalInterface.dojoPath+"')");
+		
+		// Sometimes, on IE, the fscommand infrastructure can take a few hundred
+		// milliseconds the first time a page loads. Set a timer to keep checking
+		// to make sure we can issue fscommands; otherwise, our calls to fscommand
+		// for setCallback() and loaded() will just "disappear"
+		_root.fscommandReady = false;
+		var fsChecker = function(){
+			// issue a test fscommand
+			fscommand("fscommandReady");
+			
+			// JavaScript should set _root.fscommandReady if it got the call
+			if(_root.fscommandReady == "true"){
+				DojoExternalInterface._fscommandReady = true;
+				clearInterval(_root.fsTimer);
+			}
+		};
+		_root.fsTimer = setInterval(fsChecker, 100);
+	}
+	
+	public static function addCallback(methodName:String, instance:Object, 
+											method:Function) : Boolean{
+		// A variable that indicates whether the call below succeeded
+		_root._succeeded = null;
+		
+		// Callbacks are registered with the JavaScript side as follows.
+		// On the Flash side, we maintain a lookup table that associates
+		// the methodName with the actual instance and method that are
+		// associated with this method.
+		// Using fscommand, we send over the action "addCallback", with the
+		// argument being the methodName to add, such as "foobar".
+		// The JavaScript takes these values and registers the existence of
+		// this callback point.
+		
+		// precede the method name with a _ character in case it starts
+		// with a number
+		_callbacks["_" + methodName] = {_instance: instance, _method: method};
+		_callbacks[_callbacks.length] = methodName;
+		
+		// The API for ExternalInterface says we have to make sure the call
+		// succeeded; check to see if there is a value 
+		// for _succeeded, which is set by the JavaScript side
+		if(_root._succeeded == null){
+			return false;
+		}else{
+			return true;
+		}
+	}
+	
+	public static function call(methodName:String, 
+								resultsCallback:Function) : Void{
+		// FIXME: support full JSON serialization
+		
+		// First, we pack up all of the arguments to this call and set them
+		// as Flash variables, which the JavaScript side will unpack using
+		// plugin.GetVariable(). We set the number of arguments as "_numArgs",
+		// and add each argument as a variable, such as "_1", "_2", etc., starting
+		// from 0.
+		// We then execute an fscommand with the action "call" and the
+		// argument being the method name. JavaScript takes the method name,
+		// retrieves the arguments using GetVariable, executes the method,
+		// and then places the return result in a Flash variable
+		// named "_returnResult".
+		_root._numArgs = arguments.length - 2;
+		for(var i = 2; i < arguments.length; i++){
+			var argIndex = i - 2;
+			_root["_" + argIndex] = arguments[i];
+		}
+		
+		_root._returnResult = undefined;
+		fscommand("call", methodName);
+		
+		// immediately return if the caller is not waiting for return results
+		if(resultsCallback == undefined || resultsCallback == null){
+			return;
+		}
+		
+		// check at regular intervals for return results	
+		var resultsChecker = function(){
+			if(_root._returnResult != undefined){
+				clearInterval(_root._callbackID);
+				resultsCallback.call(null, _root._returnResult);
+			}
+		};	
+		_root._callbackID = setInterval(resultsChecker, 100);
+	}
+	
+	/** 
+			Called by Flash to indicate to JavaScript that we are ready to have
+			our Flash functions called. Calling loaded()
+			will fire the dojo.flash.loaded() event, so that JavaScript can know that
+			Flash has finished loading and adding its callbacks, and can begin to
+			interact with the Flash file.
+	*/
+	public static function loaded(){
+		//getURL("javascript:dojo.debug('FLASH:loaded')");
+		
+		// one more step: see if fscommands are ready to be executed; if not,
+		// set an interval that will keep running until fscommands are ready;
+		// make sure the gateway is loaded as well
+		var execLoaded = function(){
+			if(DojoExternalInterface._fscommandReady == true){
+				clearInterval(_root.loadedInterval);
+				
+				// initialize the small Flash file that helps gateway JS to Flash
+				// calls
+				DojoExternalInterface._initializeFlashRunner();
+			}	
+		};
+		
+		if(_fscommandReady == true){
+			execLoaded();
+		}else{
+			_root.loadedInterval = setInterval(execLoaded, 50);
+		}
+	}
+	
+	/** 
+			Handles and executes a JavaScript to Flash method call. Used by
+			initializeFlashRunner. 
+	*/
+	public static function _handleJSCall(){
+		// get our parameters
+		var numArgs = parseInt(_root._numArgs);
+		var jsArgs = new Array();
+		for(var i = 0; i < numArgs; i++){
+			var currentValue = _root["_" + i];
+			jsArgs.push(currentValue);
+		}
+		
+		// get our function name
+		var functionName = _root._functionName;
+		
+		// now get the actual instance and method object to execute on,
+		// using our lookup table that was constructed by calls to
+		// addCallback on initialization
+		var instance = _callbacks["_" + functionName]._instance;
+		var method = _callbacks["_" + functionName]._method;
+		
+		// execute it
+		var results = method.apply(instance, jsArgs);
+		
+		// return the results
+		_root._returnResult = results;
+	}
+	
+	/** Called by the flash6_gateway.swf to indicate that it is loaded. */
+	public static function _gatewayReady(){
+		for(var i = 0; i < _callbacks.length; i++){
+			fscommand("addCallback", _callbacks[i]);
+		}
+		call("dojo.flash.loaded");
+	}
+	
+	/** 
+			When JavaScript wants to communicate with Flash it simply sets
+			the Flash variable "_execute" to true; this method creates the
+			internal Movie Clip, called the Flash Runner, that makes this
+			magic happen.
+	*/
+	public static function _initializeFlashRunner(){
+		// figure out where our Flash movie is
+		var swfLoc = DojoExternalInterface.dojoPath + "flash6_gateway.swf";
+		
+		// load our gateway helper file
+		_root.createEmptyMovieClip("_flashRunner", 5000);
+		_root._flashRunner._lockroot = true;
+		_root._flashRunner.loadMovie(swfLoc);
+	}
+	
+	private static function getDojoPath(){
+		var url = _root._url;
+		var start = url.indexOf("baseRelativePath=") + "baseRelativePath=".length;
+		var path = url.substring(start);
+		var end = path.indexOf("&");
+		if(end != -1){
+			path = path.substring(0, end);
+		}
+		return path;
+	}
+}
+
+// vim:ts=4:noet:tw=0:

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/flash/flash8/ExpressInstall.as
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/flash/flash8/ExpressInstall.as?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/flash/flash8/ExpressInstall.as (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/flash/flash8/ExpressInstall.as Sat Jun 10 06:59:28 2006
@@ -0,0 +1,81 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+/**
+ * Based on the expressinstall.as class created by Geoff Stearns as part
+ * of the FlashObject library.
+ *
+ * Use this file to invoke the Macromedia Flash Player Express Install functionality
+ * This file is intended for use with the FlashObject embed script. You can download FlashObject 
+ * and this file at the following URL: http://blog.deconcept.com/flashobject/
+ *
+ * Usage: 
+ *          var ExpressInstall = new ExpressInstall();
+ *          
+ *          // test to see if install is needed:
+ *          if (ExpressInstall.needsUpdate) { // returns true if update is needed
+ *              ExpressInstall.init(); // starts the update
+ *          }
+ *
+ *	NOTE: Your Flash movie must be at least 214px by 137px in order to use ExpressInstall.
+ *
+ */
+
+class ExpressInstall {
+	public var needsUpdate:Boolean;
+	private var updater:MovieClip;
+	private var hold:MovieClip;
+	
+	public function ExpressInstall(){
+		// does the user need to update?
+		this.needsUpdate = (_root.MMplayerType == undefined) ? false : true;	
+	}
+
+	public function init():Void{
+		this.loadUpdater();
+	}
+
+	public function loadUpdater():Void {
+		System.security.allowDomain("fpdownload.macromedia.com");
+
+		// hope that nothing is at a depth of 10000000, you can change this depth if needed, but you want
+		// it to be on top of your content if you have any stuff on the first frame
+		this.updater = _root.createEmptyMovieClip("expressInstallHolder", 10000000);
+
+		// register the callback so we know if they cancel or there is an error
+		var _self = this;
+		this.updater.installStatus = _self.onInstallStatus;
+		this.hold = this.updater.createEmptyMovieClip("hold", 1);
+
+		// can't use movieClipLoader because it has to work in 6.0.65
+		this.updater.onEnterFrame = function():Void {
+			if(typeof this.hold.startUpdate == 'function'){
+				_self.initUpdater();
+				this.onEnterFrame = null;
+			}
+		}
+
+		var cacheBuster:Number = Math.random();
+
+		this.hold.loadMovie("http://fpdownload.macromedia.com/pub/flashplayer/"
+												+"update/current/swf/autoUpdater.swf?"+ cacheBuster);
+	}
+
+	private function initUpdater():Void{
+		this.hold.redirectURL = _root.MMredirectURL;
+		this.hold.MMplayerType = _root.MMplayerType;
+		this.hold.MMdoctitle = _root.MMdoctitle;
+		this.hold.startUpdate();
+	}
+
+	public function onInstallStatus(msg):Void{
+		getURL("javascript:dojo.flash.install._onInstallStatus('"+msg+"')");
+	}
+}

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/fx/__package__.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/fx/__package__.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/fx/__package__.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/fx/__package__.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,15 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.kwCompoundRequire({
+	browser: ["dojo.fx.html"],
+	dashboard: ["dojo.fx.html"]
+});
+dojo.provide("dojo.fx.*");

Propchange: tapestry/tapestry4/trunk/framework/src/js/dojo/src/fx/__package__.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/fx/svg.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/fx/svg.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/fx/svg.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/fx/svg.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,99 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.fx.svg");
+
+dojo.require("dojo.svg");
+dojo.require("dojo.animation.*");
+dojo.require("dojo.event.*");
+
+dojo.fx.svg.fadeOut = function(node, duration, callback){
+	return dojo.fx.svg.fade(node, duration, dojo.svg.getOpacity(node), 0, callback);
+};
+dojo.fx.svg.fadeIn = function(node, duration, callback){
+	return dojo.fx.svg.fade(node, duration, dojo.svg.getOpacity(node), 1, callback);
+};
+dojo.fx.svg.fadeHide = function(node, duration, callback){
+	if(!duration) { duration = 150; } // why not have a default?
+	return dojo.fx.svg.fadeOut(node, duration, function(node) {
+		if(typeof callback == "function") { callback(node); }
+	});
+};
+dojo.fx.svg.fadeShow = function(node, duration, callback){
+	if(!duration) { duration = 150; } // why not have a default?
+	return dojo.fx.svg.fade(node, duration, 0, 1, callback);
+};
+dojo.fx.svg.fade = function(node, duration, startOpac, endOpac, callback){
+	var anim = new dojo.animation.Animation(
+		new dojo.math.curves.Line([startOpac],[endOpac]),
+		duration,
+		0
+	);
+	dojo.event.connect(anim, "onAnimate", function(e){
+		dojo.svg.setOpacity(node, e.x);
+	});
+	if (callback) {
+		dojo.event.connect(anim, "onEnd", function(e){
+			callback(node, anim);
+		});
+	};
+	anim.play(true);
+	return anim;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+//	TODO
+/////////////////////////////////////////////////////////////////////////////////////////
+
+//	SLIDES
+dojo.fx.svg.slideTo = function(node, endCoords, duration, callback) { };
+dojo.fx.svg.slideBy = function(node, coords, duration, callback) { };
+dojo.fx.svg.slide = function(node, startCoords, endCoords, duration, callback) { 
+	var anim = new dojo.animation.Animation(
+		new dojo.math.curves.Line([startCoords],[endCoords]),
+		duration,
+		0
+	);
+	dojo.event.connect(anim, "onAnimate", function(e){
+		dojo.svg.setCoords(node, {x: e.x, y: e.y });
+	});
+	if (callback) {
+		dojo.event.connect(anim, "onEnd", function(e){
+			callback(node, anim);
+		});
+	};
+	anim.play(true);
+	return anim;
+};
+
+//	COLORS
+dojo.fx.svg.colorFadeIn = function(node, startRGB, duration, delay, callback) { };
+dojo.fx.svg.highlight = dojo.fx.svg.colorFadeIn;
+dojo.fx.svg.colorFadeFrom = dojo.fx.svg.colorFadeIn;
+
+dojo.fx.svg.colorFadeOut = function(node, endRGB, duration, delay, callback) { };
+dojo.fx.svg.unhighlight = dojo.fx.svg.colorFadeOut;
+dojo.fx.svg.colorFadeTo = dojo.fx.svg.colorFadeOut;
+
+dojo.fx.svg.colorFade = function(node, startRGB, endRGB, duration, callback, dontPlay) { };
+
+//	WIPES
+dojo.fx.svg.wipeIn = function(node, duration, callback, dontPlay) { };
+dojo.fx.svg.wipeInToHeight = function(node, duration, height, callback, dontPlay) { }
+dojo.fx.svg.wipeOut = function(node, duration, callback, dontPlay) { };
+
+//	Explode and Implode
+dojo.fx.svg.explode = function(startNode, endNode, duration, callback) { };
+dojo.fx.svg.explodeFromBox = function(startCoords, endNode, duration, callback) { };
+dojo.fx.svg.implode = function(startNode, endNode, duration, callback) { };
+dojo.fx.svg.implodeToBox = function(startNode, endCoords, duration, callback) { };
+dojo.fx.svg.Exploder = function(triggerNode, boxNode) { };
+
+//	html mixes in, we want SVG to remain separate

Propchange: tapestry/tapestry4/trunk/framework/src/js/dojo/src/fx/svg.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/graphics/color.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/graphics/color.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/graphics/color.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/graphics/color.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,166 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.graphics.color");
+dojo.require("dojo.lang.array");
+
+// TODO: rewrite the "x2y" methods to take advantage of the parsing
+//       abilities of the Color object. Also, beef up the Color
+//       object (as possible) to parse most common formats
+
+// takes an r, g, b, a(lpha) value, [r, g, b, a] array, "rgb(...)" string, hex string (#aaa, #aaaaaa, aaaaaaa)
+dojo.graphics.color.Color = function(r, g, b, a) {
+	// dojo.debug("r:", r[0], "g:", r[1], "b:", r[2]);
+	if(dojo.lang.isArray(r)) {
+		this.r = r[0];
+		this.g = r[1];
+		this.b = r[2];
+		this.a = r[3]||1.0;
+	} else if(dojo.lang.isString(r)) {
+		var rgb = dojo.graphics.color.extractRGB(r);
+		this.r = rgb[0];
+		this.g = rgb[1];
+		this.b = rgb[2];
+		this.a = g||1.0;
+	} else if(r instanceof dojo.graphics.color.Color) {
+		this.r = r.r;
+		this.b = r.b;
+		this.g = r.g;
+		this.a = r.a;
+	} else {
+		this.r = r;
+		this.g = g;
+		this.b = b;
+		this.a = a;
+	}
+}
+
+dojo.graphics.color.Color.fromArray = function(arr) {
+	return new dojo.graphics.color.Color(arr[0], arr[1], arr[2], arr[3]);
+}
+
+dojo.lang.extend(dojo.graphics.color.Color, {
+	toRgb: function(includeAlpha) {
+		if(includeAlpha) {
+			return this.toRgba();
+		} else {
+			return [this.r, this.g, this.b];
+		}
+	},
+
+	toRgba: function() {
+		return [this.r, this.g, this.b, this.a];
+	},
+
+	toHex: function() {
+		return dojo.graphics.color.rgb2hex(this.toRgb());
+	},
+
+	toCss: function() {
+		return "rgb(" + this.toRgb().join() + ")";
+	},
+
+	toString: function() {
+		return this.toHex(); // decent default?
+	},
+
+	blend: function(color, weight) {
+		return dojo.graphics.color.blend(this.toRgb(), new dojo.graphics.color.Color(color).toRgb(), weight);
+	}
+});
+
+dojo.graphics.color.named = {
+	white:      [255,255,255],
+	black:      [0,0,0],
+	red:        [255,0,0],
+	green:	    [0,255,0],
+	blue:       [0,0,255],
+	navy:       [0,0,128],
+	gray:       [128,128,128],
+	silver:     [192,192,192]
+};
+
+// blend colors a and b (both as RGB array or hex strings) with weight from -1 to +1, 0 being a 50/50 blend
+dojo.graphics.color.blend = function(a, b, weight) {
+	if(typeof a == "string") { return dojo.graphics.color.blendHex(a, b, weight); }
+	if(!weight) { weight = 0; }
+	else if(weight > 1) { weight = 1; }
+	else if(weight < -1) { weight = -1; }
+	var c = new Array(3);
+	for(var i = 0; i < 3; i++) {
+		var half = Math.abs(a[i] - b[i])/2;
+		c[i] = Math.floor(Math.min(a[i], b[i]) + half + (half * weight));
+	}
+	return c;
+}
+
+// very convenient blend that takes and returns hex values
+// (will get called automatically by blend when blend gets strings)
+dojo.graphics.color.blendHex = function(a, b, weight) {
+	return dojo.graphics.color.rgb2hex(dojo.graphics.color.blend(dojo.graphics.color.hex2rgb(a), dojo.graphics.color.hex2rgb(b), weight));
+}
+
+// get RGB array from css-style color declarations
+dojo.graphics.color.extractRGB = function(color) {
+	var hex = "0123456789abcdef";
+	color = color.toLowerCase();
+	if( color.indexOf("rgb") == 0 ) {
+		var matches = color.match(/rgba*\((\d+), *(\d+), *(\d+)/i);
+		var ret = matches.splice(1, 3);
+		return ret;
+	} else {
+		var colors = dojo.graphics.color.hex2rgb(color);
+		if(colors) {
+			return colors;
+		} else {
+			// named color (how many do we support?)
+			return dojo.graphics.color.named[color] || [255, 255, 255];
+		}
+	}
+}
+
+dojo.graphics.color.hex2rgb = function(hex) {
+	var hexNum = "0123456789ABCDEF";
+	var rgb = new Array(3);
+	if( hex.indexOf("#") == 0 ) { hex = hex.substring(1); }
+	hex = hex.toUpperCase();
+	if(hex.replace(new RegExp("["+hexNum+"]", "g"), "") != "") {
+		return null;
+	}
+	if( hex.length == 3 ) {
+		rgb[0] = hex.charAt(0) + hex.charAt(0)
+		rgb[1] = hex.charAt(1) + hex.charAt(1)
+		rgb[2] = hex.charAt(2) + hex.charAt(2);
+	} else {
+		rgb[0] = hex.substring(0, 2);
+		rgb[1] = hex.substring(2, 4);
+		rgb[2] = hex.substring(4);
+	}
+	for(var i = 0; i < rgb.length; i++) {
+		rgb[i] = hexNum.indexOf(rgb[i].charAt(0)) * 16 + hexNum.indexOf(rgb[i].charAt(1));
+	}
+	return rgb;
+}
+
+dojo.graphics.color.rgb2hex = function(r, g, b) {
+	if(dojo.lang.isArray(r)) {
+		g = r[1] || 0;
+		b = r[2] || 0;
+		r = r[0] || 0;
+	}
+	var ret = dojo.lang.map([r, g, b], function(x) {
+		x = new Number(x);
+		var s = x.toString(16);
+		while(s.length < 2) { s = "0" + s; }
+		return s;
+	});
+	ret.unshift("#");
+	return ret.join("");
+}

Propchange: tapestry/tapestry4/trunk/framework/src/js/dojo/src/graphics/color.js
------------------------------------------------------------------------------
    svn:eol-style = native