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/09/23 01:22:51 UTC

svn commit: r449122 [21/40] - in /tapestry/tapestry4/trunk/tapestry-framework/src: java/org/apache/tapestry/ java/org/apache/tapestry/dojo/ java/org/apache/tapestry/dojo/form/ java/org/apache/tapestry/dojo/html/ java/org/apache/tapestry/form/ java/org/...

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/storage.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/storage.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/storage.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/storage.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,361 @@
+/*
+	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
+*/
+
+/** 
+		FIXME: Write better docs.
+
+		@author Brad Neuberg, bkn3@columbia.edu 
+*/
+dojo.provide("dojo.storage");
+dojo.provide("dojo.storage.StorageProvider");
+
+dojo.require("dojo.lang.*");
+dojo.require("dojo.event.*");
+
+
+/** The base class for all storage providers. */
+
+/** 
+	 The constructor for a storage provider. You should avoid initialization
+	 in the constructor; instead, define initialization in your initialize()
+	 method. 
+*/
+dojo.declare("dojo.storage", null, {
+	/** A put() call to a storage provider was succesful. */
+	SUCCESS: "success",
+	
+	/** A put() call to a storage provider failed. */
+	FAILED: "failed",
+	
+	/** A put() call to a storage provider is pending user approval. */
+	PENDING: "pending",
+	
+	/** 
+	  Returned by getMaximumSize() if this storage provider can not determine
+	  the maximum amount of data it can support. 
+	*/
+	SIZE_NOT_AVAILABLE: "Size not available",
+	
+	/**
+	  Returned by getMaximumSize() if this storage provider has no theoretical
+	  limit on the amount of data it can store. 
+	*/
+	SIZE_NO_LIMIT: "No size limit",
+	
+	/** 
+		The namespace for all storage operations. This is useful if several
+		applications want access to the storage system from the same domain but
+		want different storage silos. 
+	*/
+	"namespace": "dojoStorage",
+	
+	/**  
+		If a function is assigned to this property, then when the settings
+		provider's UI is closed this function is called. Useful, for example,
+		if the user has just cleared out all storage for this provider using
+		the settings UI, and you want to update your UI.
+	*/
+	onHideSettingsUI: null,
+
+	initialize: function(){
+		// summary: 
+		//		Allows this storage provider to initialize itself. This is
+		//		called after the page has finished loading, so you can not do
+		//		document.writes(). 
+		dojo.unimplemented("dojo.storage.initialize");
+	},
+	
+	isAvailable: function(){ /*Boolean*/
+		// summary: 
+		//		Returns whether this storage provider is available on this
+		//		platform. 
+		dojo.unimplemented("dojo.storage.isAvailable");
+	},
+	
+	/**
+
+	*/
+	put: function(	/*string*/ key,
+					/*object*/ value, 
+					/*function*/ resultsHandler){
+		// summary:
+		//		Puts a key and value into this storage system.
+		// key:
+		//		A string key to use when retrieving this value in the future.
+		// value:
+		//		A value to store; this can be any JavaScript type.
+		// resultsHandler:
+		//		A callback function that will receive three arguments. The
+		//		first argument is one of three values: dojo.storage.SUCCESS,
+		//		dojo.storage.FAILED, or dojo.storage.PENDING; these values
+		//		determine how the put request went. In some storage systems
+		//		users can deny a storage request, resulting in a
+		//		dojo.storage.FAILED, while in other storage systems a storage
+		//		request must wait for user approval, resulting in a
+		//		dojo.storage.PENDING status until the request is either
+		//		approved or denied, resulting in another call back with
+		//		dojo.storage.SUCCESS. 
+		//		The second argument in the call back is the key name that was being stored.
+		//		The third argument in the call back is an optional message that
+		//		details possible error messages that might have occurred during
+		//		the storage process.
+
+//	  Example:
+//		var resultsHandler = function(status, key, message){
+//		  alert("status="+status+", key="+key+", message="+message);
+//		};
+//		dojo.storage.put("test", "hello world", resultsHandler);
+		dojo.unimplemented("dojo.storage.put");
+	},
+
+	get: function(/*string*/ key){ /*Object*/
+		// summary:
+		//		Gets the value with the given key. Returns null if this key is
+		//		not in the storage system.
+		// key:
+		//		A string key to get the value of.
+		// return: Returns any JavaScript object type; null if the key is not present
+		dojo.unimplemented("dojo.storage.get");
+	},
+
+	hasKey: function(/*string*/ key){ /*Boolean*/
+		// summary: Determines whether the storage has the given key. 
+		return (this.get(key) != null);
+	},
+
+	/**
+	
+	getKeys: function(){ //Array
+		// summary: Enumerates all of the available keys in this storage system.
+		dojo.unimplemented("dojo.storage.getKeys");
+	},
+
+	*/
+	clear: function(){
+		// summary: 
+		//		Completely clears this storage system of all of it's values and
+		//		keys. 
+		dojo.unimplemented("dojo.storage.clear");
+	},
+  
+	/** Removes the given key from the storage system. */
+	remove: function(key){
+		dojo.unimplemented("dojo.storage.remove");
+	},
+
+	isPermanent: function(){ /*Boolean*/
+		// summary:
+		//		Returns whether this storage provider's values are persisted
+		//		when this platform is shutdown. 
+		dojo.unimplemented("dojo.storage.isPermanent");
+	},
+
+	/**
+	  The maximum storage allowed by this provider.
+	
+	  @returns Returns the maximum storage size 
+	           supported by this provider, in 
+	           thousands of bytes (i.e., if it 
+	           returns 60 then this means that 60K 
+	           of storage is supported).
+	    
+	           If this provider can not determine 
+	           it's maximum size, then 
+	           dojo.storage.SIZE_NOT_AVAILABLE is 
+	           returned; if there is no theoretical
+	           limit on the amount of storage 
+	           this provider can return, then
+	           dojo.storage.SIZE_NO_LIMIT is 
+	           returned
+	*/
+	getMaximumSize: function(){
+		dojo.unimplemented("dojo.storage.getMaximumSize");
+	},
+
+	hasSettingsUI: function(){ /*Boolean*/
+		// summary: Determines whether this provider has a settings UI.
+		return false;
+	},
+
+	showSettingsUI: function(){
+		// summary: If this provider has a settings UI, it is shown. 
+		dojo.unimplemented("dojo.storage.showSettingsUI");
+	},
+
+	hideSettingsUI: function(){
+		// summary: If this provider has a settings UI, hides it.
+		dojo.unimplemented("dojo.storage.hideSettingsUI");
+	},
+	
+	getType: function(){ /*String*/
+		// summary:
+		//		The provider name as a string, such as
+		//		"dojo.storage.FlashStorageProvider". 
+		dojo.unimplemented("dojo.storage.getType");
+	},
+	
+	isValidKey: function(/*string*/ keyName){ /*Boolean*/
+		// summary:
+		//		Subclasses can call this to ensure that the key given is valid
+		//		in a consistent way across different storage providers. We use
+		//		the lowest common denominator for key values allowed: only
+		//		letters, numbers, and underscores are allowed. No spaces. 
+		if((keyName == null)||(typeof keyName == "undefined")){
+			return false;
+		}
+			
+		return /^[0-9A-Za-z_]*$/.test(keyName);
+	}
+});
+
+
+
+
+/**
+	Initializes the storage systems and figures out the best available 
+	storage options on this platform.
+*/
+dojo.storage.manager = new function(){
+	this.currentProvider = null;
+	this.available = false;
+	this.initialized = false;
+	this.providers = [];
+	
+	// TODO: Provide a way for applications to override the default namespace
+	this["namespace"] = "dojo.storage";
+	
+	this.initialize = function(){
+		// summary: 
+		//		Initializes the storage system and autodetects the best storage
+		//		provider we can provide on this platform
+		this.autodetect();
+	};
+	
+	/**
+	
+	*/
+	this.register = function(/*string*/ name, /*Object*/ instance) {
+		// summary:
+		//		Registers the existence of a new storage provider; used by
+		//		subclasses to inform the manager of their existence. 
+		// name:
+		//		The full class name of this provider, such as
+		//		"dojo.storage.browser.Flash6StorageProvider".
+		// instance:
+		//		An instance of this provider, which we will use to call
+		//		isAvailable() on. 
+		this.providers[this.providers.length] = instance;
+		this.providers[name] = instance;
+	};
+	
+	/**
+	    
+	*/
+	this.setProvider = function(storageClass){
+		// summary:
+		//		Instructs the storageManager to use the given storage class for
+		//		all storage requests.
+		// description:
+		//		Example:
+		//			dojo.storage.setProvider(
+		//				dojo.storage.browser.IEStorageProvider)
+	
+	};
+	
+	this.autodetect = function(){
+		// summary:
+		//		Autodetects the best possible persistent storage provider
+		//		available on this platform. 
+		if(this.initialized == true) // already finished
+			return;
+			
+		// go through each provider, seeing if it can be used
+		var providerToUse = null;
+		for(var i = 0; i < this.providers.length; i++) {
+			providerToUse = this.providers[i];
+			if(providerToUse.isAvailable()){
+				break;
+			}
+		}	
+		
+		if(providerToUse == null){ // no provider available
+			this.initialized = true;
+			this.available = false;
+			this.currentProvider = null;
+			dojo.raise("No storage provider found for this platform");
+		}
+			
+		// create this provider and copy over it's properties
+		this.currentProvider = providerToUse;
+	  	for(var i in providerToUse){
+	  		dojo.storage[i] = providerToUse[i];
+		}
+		dojo.storage.manager = this;
+		
+		// have the provider initialize itself
+		dojo.storage.initialize();
+		
+		this.initialized = true;
+		this.available = true;
+	};
+	
+	this.isAvailable = function(){ /*Boolean*/
+		// summary: Returns whether any storage options are available.
+		return this.available;
+	};
+	
+	this.isInitialized = function(){ /*Boolean*/
+	 	// summary:
+		//		Returns whether the storage system is initialized and ready to
+		//		be used. 
+
+		// FIXME: This should _really_ not be in here, but it fixes a bug
+		if(dojo.flash.ready == false){
+			return false;
+		}else{
+			return this.initialized;
+		}
+	};
+
+	this.supportsProvider = function(/*string*/ storageClass){
+		// summary: Determines if this platform supports the given storage provider.
+		// description:
+		//		Example:
+		//			dojo.storage.manager.supportsProvider(
+		//				"dojo.storage.browser.InternetExplorerStorageProvider");
+
+		// construct this class dynamically
+		try{
+			// dynamically call the given providers class level isAvailable()
+			// method
+			var provider = eval("new " + storageClass + "()");
+			var results = provider.isAvailable();
+			if(results == null || typeof results == "undefined")
+				return false;
+			return results;
+		}catch (exception){
+			dojo.debug("exception="+exception);
+			return false;
+		}
+	};
+
+	/** Gets the current provider. */
+	this.getProvider = function(){
+		return this.currentProvider;
+	};
+	
+	this.loaded = function(){
+		// summary:
+		//		The storage provider should call this method when it is loaded
+		//		and ready to be used. Clients who will use the provider will
+		//		connect to this method to know when they can use the storage
+		//		system:
+	};
+};

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/storage/Storage.as
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/storage/Storage.as?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/storage/Storage.as (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/storage/Storage.as Fri Sep 22 16:22:30 2006
@@ -0,0 +1,146 @@
+/*
+	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
+*/
+
+import DojoExternalInterface;
+
+class Storage {
+	public static var SUCCESS = "success";
+	public static var FAILED = "failed";
+	public static var PENDING = "pending";
+	
+	public var so;
+	
+	public function Storage(){
+		//getURL("javascript:dojo.debug('FLASH:Storage constructor')");
+		DojoExternalInterface.initialize();
+		DojoExternalInterface.addCallback("put", this, put);
+		DojoExternalInterface.addCallback("get", this, get);
+		DojoExternalInterface.addCallback("showSettings", this, showSettings);
+		DojoExternalInterface.addCallback("clear", this, clear);
+		DojoExternalInterface.addCallback("getKeys", this, getKeys);
+		DojoExternalInterface.addCallback("remove", this, remove);
+		DojoExternalInterface.loaded();
+		
+		// preload the System Settings finished button movie for offline
+		// access so it is in the cache
+		_root.createEmptyMovieClip("_settingsBackground", 1);
+		// getURL("javascript:alert('"+DojoExternalInterface.dojoPath+"');");
+		_root._settingsBackground.loadMovie(DojoExternalInterface.dojoPath + "storage_dialog.swf");
+	}
+
+	public function put(keyName, keyValue, namespace){
+		// Get the SharedObject for these values and save it
+		so = SharedObject.getLocal(namespace);
+		
+		// prepare a storage status handler
+		var self = this;
+		so.onStatus = function(infoObject:Object){
+			//getURL("javascript:dojo.debug('FLASH: onStatus, infoObject="+infoObject.code+"')");
+			
+			// delete the data value if the request was denied
+			if (infoObject.code == "SharedObject.Flush.Failed"){
+				delete self.so.data[keyName];
+			}
+			
+			var statusResults;
+			if(infoObject.code == "SharedObject.Flush.Failed"){
+				statusResults = Storage.FAILED;
+			}else if(infoObject.code == "SharedObject.Flush.Pending"){
+				statusResults = Storage.PENDING;
+			}else if(infoObject.code == "SharedObject.Flush.Success"){
+				statusResults = Storage.SUCCESS;
+			}
+			//getURL("javascript:dojo.debug('FLASH: onStatus, statusResults="+statusResults+"')");
+			
+			// give the status results to JavaScript
+			DojoExternalInterface.call("dojo.storage._onStatus", null, statusResults, 
+																 keyName);
+		}
+		
+		// save the key and value
+		so.data[keyName] = keyValue;
+		var flushResults = so.flush();
+		
+		// return results of this command to JavaScript
+		var statusResults;
+		if(flushResults == true){
+			statusResults = Storage.SUCCESS;
+		}else if(flushResults == "pending"){
+			statusResults = Storage.PENDING;
+		}else{
+			statusResults = Storage.FAILED;
+		}
+		
+		DojoExternalInterface.call("dojo.storage._onStatus", null, statusResults, 
+															 keyName);
+	}
+
+	public function get(keyName, namespace){
+		// Get the SharedObject for these values and save it
+		so = SharedObject.getLocal(namespace);
+		var results = so.data[keyName];
+		
+		return results;
+	}
+	
+	public function showSettings(){
+		// Show the configuration options for the Flash player, opened to the
+		// section for local storage controls (pane 1)
+		System.showSettings(1);
+		
+		// there is no way we can intercept when the Close button is pressed, allowing us
+		// to hide the Flash dialog. Instead, we need to load a movie in the
+		// background that we can show a close button on.
+		_root.createEmptyMovieClip("_settingsBackground", 1);
+		_root._settingsBackground.loadMovie(DojoExternalInterface.dojoPath + "storage_dialog.swf");
+	}
+	
+	public function clear(namespace){
+		so = SharedObject.getLocal(namespace);
+		so.clear();
+		so.flush();
+	}
+	
+	public function getKeys(namespace){
+		// Returns a list of the available keys in this namespace
+		
+		// get the storage object
+		so = SharedObject.getLocal(namespace);
+		
+		// get all of the keys
+		var results = new Array();
+		for(var i in so.data)
+			results.push(i);	
+		
+		// join the keys together in a comma seperated string
+		results = results.join(",");
+		
+		return results;
+	}
+	
+	public function remove(keyName, namespace){
+		// Removes a key
+
+		// get the storage object
+		so = SharedObject.getLocal(namespace);
+		
+		// delete this value
+		delete so.data[keyName];
+		
+		// save the changes
+		so.flush();
+	}
+
+	static function main(mc){
+		//getURL("javascript:dojo.debug('FLASH: storage loaded')");
+		_root.app = new Storage(); 
+	}
+}
+

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/storage/__package__.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/storage/__package__.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/storage/__package__.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/storage/__package__.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,17 @@
+/*
+	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({
+	common: ["dojo.storage"],
+	browser: ["dojo.storage.browser"],
+	dashboard: ["dojo.storage.dashboard"]
+});
+dojo.provide("dojo.storage.*");
+

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/storage/browser.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/storage/browser.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/storage/browser.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/storage/browser.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,196 @@
+/*
+	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.storage.browser");
+dojo.provide("dojo.storage.browser.FlashStorageProvider");
+
+dojo.require("dojo.storage");
+dojo.require("dojo.flash");
+dojo.require("dojo.json");
+dojo.require("dojo.uri.*");
+
+/** 
+		Storage provider that uses features in Flash to achieve permanent storage.
+		
+		@author Brad Neuberg, bkn3@columbia.edu 
+*/
+dojo.storage.browser.FlashStorageProvider = function(){
+}
+
+dojo.inherits(dojo.storage.browser.FlashStorageProvider, dojo.storage);
+
+// instance methods and properties
+dojo.lang.extend(dojo.storage.browser.FlashStorageProvider, {
+	"namespace": "default",
+	initialized: false,
+	_available: null,
+	_statusHandler: null,
+	
+	initialize: function(){
+		if(djConfig["disableFlashStorage"] == true){
+			return;
+		}
+		
+		// initialize our Flash
+		var loadedListener = function(){
+			dojo.storage._flashLoaded();
+		}
+		dojo.flash.addLoadedListener(loadedListener);
+		var swfloc6 = dojo.uri.dojoUri("Storage_version6.swf").toString();
+		var swfloc8 = dojo.uri.dojoUri("Storage_version8.swf").toString();
+		dojo.flash.setSwf({flash6: swfloc6, flash8: swfloc8, visible: false});
+	},
+	
+	isAvailable: function(){
+		if(djConfig["disableFlashStorage"] == true){
+			this._available = false;
+		}
+		
+		return this._available;
+	},
+	
+	setNamespace: function(ns){
+		this["namespace"] = ns;
+	},
+
+	put: function(key, value, resultsHandler){
+		if(this.isValidKey(key) == false){
+			dojo.raise("Invalid key given: " + key);
+		}
+			
+		this._statusHandler = resultsHandler;
+		
+		// serialize the value
+		// Handle strings differently so they have better performance
+		if(dojo.lang.isString(value)){
+			value = "string:" + value;
+		}else{
+			value = dojo.json.serialize(value);
+		}
+		
+		dojo.flash.comm.put(key, value, this["namespace"]);
+	},
+
+	get: function(key){
+		if(this.isValidKey(key) == false){
+			dojo.raise("Invalid key given: " + key);
+		}
+		
+		var results = dojo.flash.comm.get(key, this["namespace"]);
+
+		if(results == ""){
+			return null;
+		}
+    
+		// destringify the content back into a 
+		// real JavaScript object
+		// Handle strings differently so they have better performance
+		if(!dojo.lang.isUndefined(results) && results != null 
+			 && /^string:/.test(results)){
+			results = results.substring("string:".length);
+		}else{
+			results = dojo.json.evalJson(results);
+		}
+    
+		return results;
+	},
+
+	getKeys: function(){
+		var results = dojo.flash.comm.getKeys(this["namespace"]);
+		
+		if(results == ""){
+			return [];
+		}
+
+		// the results are returned comma seperated; split them
+		return results.split(",");
+	},
+
+	clear: function(){
+		dojo.flash.comm.clear(this["namespace"]);
+	},
+	
+	remove: function(key){
+	},
+	
+	isPermanent: function(){
+		return true;
+	},
+
+	getMaximumSize: function(){
+		return dojo.storage.SIZE_NO_LIMIT;
+	},
+
+	hasSettingsUI: function(){
+		return true;
+	},
+
+	showSettingsUI: function(){
+		dojo.flash.comm.showSettings();
+		dojo.flash.obj.setVisible(true);
+		dojo.flash.obj.center();
+	},
+
+	hideSettingsUI: function(){
+		// hide the dialog
+		dojo.flash.obj.setVisible(false);
+		
+		// call anyone who wants to know the dialog is
+		// now hidden
+		if(dojo.storage.onHideSettingsUI != null &&
+			!dojo.lang.isUndefined(dojo.storage.onHideSettingsUI)){
+			dojo.storage.onHideSettingsUI.call(null);	
+		}
+	},
+	
+	/** 
+			The provider name as a string, such as 
+			"dojo.storage.FlashStorageProvider". 
+	*/
+	getType: function(){
+		return "dojo.storage.FlashStorageProvider";
+	},
+	
+	/** Called when the Flash is finished loading. */
+	_flashLoaded: function(){
+		this.initialized = true;
+
+		// indicate that this storage provider is now loaded
+		dojo.storage.manager.loaded();
+	},
+	
+	/** 
+			Called if the storage system needs to tell us about the status
+			of a put() request. 
+	*/
+	_onStatus: function(statusResult, key){
+		var ds = dojo.storage;
+		var dfo = dojo.flash.obj;
+		//dojo.debug("_onStatus, statusResult="+statusResult+", key="+key);
+		if(statusResult == ds.PENDING){
+			dfo.center();
+			dfo.setVisible(true);
+		}else{
+			dfo.setVisible(false);
+		}
+		
+		if((!dj_undef("_statusHandler", ds))&&(ds._statusHandler != null)){
+			ds._statusHandler.call(null, statusResult, key);		
+		}
+	}
+});
+
+// register the existence of our storage providers
+dojo.storage.manager.register("dojo.storage.browser.FlashStorageProvider",
+								new dojo.storage.browser.FlashStorageProvider());
+
+// now that we are loaded and registered tell the storage manager to initialize
+// itself
+dojo.storage.manager.initialize();

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/storage/dashboard.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/storage/dashboard.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/storage/dashboard.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/storage/dashboard.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,52 @@
+/*
+	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.storage");
+dojo.require("dojo.json");
+dojo.provide("dojo.storage.dashboard");
+
+dojo.storage.dashboard.StorageProvider = function(){
+	this.initialized = false;
+}
+
+dojo.inherits(dojo.storage.dashboard.StorageProvider, dojo.storage.StorageProvider);
+
+dojo.lang.extend(dojo.storage.dashboard.StorageProvider, {
+	storageOnLoad: function(){
+		this.initialized = true;
+	},
+
+	set: function(key, value, ns){
+		if (ns && widget.system){
+			widget.system("/bin/mkdir " + ns);
+			var system = widget.system("/bin/echo " + value + " >" + ns + "/" + key);
+			if(system.errorString){
+				return false;
+			}
+			return true;
+		}
+
+		return widget.setPreferenceForKey(dojo.json.serialize(value), key);
+	},
+
+	get: function(key, ns){
+		if (ns && widget.system) {
+			var system = widget.system("/bin/cat " + ns + "/" + key);
+			if(system.errorString){
+				return "";
+			}
+			return system.outputString;
+		}
+
+		return dojo.json.evalJson(widget.preferenceForKey(key));
+	}
+});
+
+dojo.storage.setProvider(new dojo.storage.dashboard.StorageProvider());

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/storage/storage_dialog.fla
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/storage/storage_dialog.fla?view=auto&rev=449122
==============================================================================
Binary file - no diff available.

Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/storage/storage_dialog.fla
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/string.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/string.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/string.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/string.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,12 @@
+/*
+	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.string");
+dojo.require("dojo.string.common");

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/string/Builder.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/string/Builder.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/string/Builder.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/string/Builder.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,129 @@
+/*
+	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.string.Builder");
+dojo.require("dojo.string");
+
+// NOTE: testing shows that direct "+=" concatenation is *much* faster on
+// Spidermoneky and Rhino, while arr.push()/arr.join() style concatenation is
+// significantly quicker on IE (Jscript/wsh/etc.).
+
+dojo.string.Builder = function(/* string? */str){
+	//	summary
+	//	Builder object based on .NET's StringBuilder.
+	this.arrConcat = (dojo.render.html.capable && dojo.render.html["ie"]);
+
+	var a = [];
+	var b = "";
+	var length = this.length = b.length;
+
+	if(this.arrConcat){
+		if(b.length > 0){
+			a.push(b);
+		}
+		b = "";
+	}
+
+	this.toString = this.valueOf = function(){ 
+		//	summary
+		//	Concatenate internal buffer and return as a string
+		return (this.arrConcat) ? a.join("") : b;	//	string
+	};
+
+	this.append = function(){
+		//	summary
+		//	Append all arguments to the end of the internal buffer
+		for(var x=0; x<arguments.length; x++){
+			var s = arguments[x];
+			if((s instanceof String)||(typeof s == "string")){
+				if(this.arrConcat){
+					a.push(s);
+				}else{
+					b+=s;
+				}
+				length += s.length;
+				this.length = length;
+			}else{
+				// if we get something array-like, call append with it as args
+				this.append.apply(this, s);
+			}
+		}
+		return this;	//	dojo.string.Builder
+	};
+
+	this.clear = function(){
+		//	summary
+		//	Clear the internal buffer.
+		a = [];
+		b = "";
+		length = this.length = 0;
+		return this;	//	dojo.string.Builder
+	};
+
+	this.remove = function(/* integer */f, /* integer */l){
+		//	summary
+		//	Remove a section of string from the internal buffer.
+		var s = ""; 
+		if(this.arrConcat){
+			b = a.join(""); 
+		}
+		a=[];
+		if(f>0){
+			s = b.substring(0, (f-1));
+		}
+		b = s + b.substring(f + l); 
+		length = this.length = b.length; 
+		if(this.arrConcat){
+			a.push(b);
+			b="";
+		}
+		return this;	//	dojo.string.Builder
+	};
+
+	this.replace = function(/* string */o, /* string */n){
+		//	summary
+		//	replace phrase *o* with phrase *n*.
+		if(this.arrConcat){
+			b = a.join(""); 
+		}
+		a = []; 
+		b = b.replace(o,n); 
+		length = this.length = b.length; 
+		if(this.arrConcat){
+			a.push(b);
+			b="";
+		}
+		return this;	//	dojo.string.Builder
+	};
+
+	this.insert = function(/* integer */idx, /* string */s){
+		//	summary
+		//	Insert string s at index idx.
+		if(this.arrConcat){
+			b = a.join(""); 
+		}
+		a=[];
+		if(idx == 0){
+			b = s + b;
+		}else{
+			var t = b.split("");
+			t.splice(idx,0,s);
+			b = t.join("")
+		}
+		length = this.length = b.length; 
+		if(this.arrConcat){
+			a.push(b); 
+			b="";
+		}
+		return this;	//	dojo.string.Builder
+	};
+
+	this.append.apply(this, arguments);
+};

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/string/__package__.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/string/__package__.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/string/__package__.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/string/__package__.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,19 @@
+/*
+	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({
+	common: [
+		"dojo.string",
+		"dojo.string.common",
+		"dojo.string.extras",
+		"dojo.string.Builder"
+	]
+});
+dojo.provide("dojo.string.*");

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/string/common.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/string/common.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/string/common.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/string/common.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,78 @@
+/*
+	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.string.common");
+
+dojo.string.trim = function(/* string */str, /* integer? */wh){
+	//	summary
+	//	Trim whitespace from str.  If wh > 0, trim from start, if wh < 0, trim from end, else both
+	if(!str.replace){ return str; }
+	if(!str.length){ return str; }
+	var re = (wh > 0) ? (/^\s+/) : (wh < 0) ? (/\s+$/) : (/^\s+|\s+$/g);
+	return str.replace(re, "");	//	string
+}
+
+dojo.string.trimStart = function(/* string */str) {
+	//	summary
+	//	Trim whitespace at the beginning of 'str'
+	return dojo.string.trim(str, 1);	//	string
+}
+
+dojo.string.trimEnd = function(/* string */str) {
+	//	summary
+	//	Trim whitespace at the end of 'str'
+	return dojo.string.trim(str, -1);
+}
+
+dojo.string.repeat = function(/* string */str, /* integer */count, /* string? */separator) {
+	//	summary
+	//	Return 'str' repeated 'count' times, optionally placing 'separator' between each rep
+	var out = "";
+	for(var i = 0; i < count; i++) {
+		out += str;
+		if(separator && i < count - 1) {
+			out += separator;
+		}
+	}
+	return out;	//	string
+}
+
+dojo.string.pad = function(/* string */str, /* integer */len/*=2*/, /* string */ c/*='0'*/, /* integer */dir/*=1*/) {
+	//	summary
+	//	Pad 'str' to guarantee that it is at least 'len' length with the character 'c' at either the 
+	//	start (dir=1) or end (dir=-1) of the string
+	var out = String(str);
+	if(!c) {
+		c = '0';
+	}
+	if(!dir) {
+		dir = 1;
+	}
+	while(out.length < len) {
+		if(dir > 0) {
+			out = c + out;
+		} else {
+			out += c;
+		}
+	}
+	return out;	//	string
+}
+
+dojo.string.padLeft = function(/* string */str, /* integer */len, /* string */c) {
+	//	summary
+	//	same as dojo.string.pad(str, len, c, 1)
+	return dojo.string.pad(str, len, c, 1);	//	string
+}
+
+dojo.string.padRight = function(/* string */str, /* integer */len, /* string */c) {
+	//	summary
+	//	same as dojo.string.pad(str, len, c, -1)
+	return dojo.string.pad(str, len, c, -1);	//	string
+}

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/string/extras.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/string/extras.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/string/extras.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/string/extras.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,261 @@
+/*
+	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.string.extras");
+
+dojo.require("dojo.string.common");
+dojo.require("dojo.lang.common");
+dojo.require("dojo.lang.array");
+
+//TODO: should we use ${} substitution syntax instead, like widgets do?
+dojo.string.substituteParams = function(/*string*/template, /* object - optional or ... */hash){
+// summary:
+//	Performs parameterized substitutions on a string. Throws an exception if any parameter is unmatched.
+//
+// description:
+//	For example,
+//		dojo.string.substituteParams("File '%{0}' is not found in directory '%{1}'.","foo.html","/temp");
+//	returns
+//		"File 'foo.html' is not found in directory '/temp'."
+//
+// template: the original string template with %{values} to be replaced
+// hash: name/value pairs (type object) to provide substitutions.  Alternatively, substitutions may be
+//	included as arguments 1..n to this function, corresponding to template parameters 0..n-1
+
+	var map = (typeof hash == 'object') ? hash : dojo.lang.toArray(arguments, 1);
+
+	return template.replace(/\%\{(\w+)\}/g, function(match, key){
+		if(typeof(map[key]) != "undefined" && map[key] != null){
+			return map[key];
+		}
+		dojo.raise("Substitution not found: " + key);
+	}); // string
+};
+
+dojo.string.capitalize = function(/*string*/str){
+// summary:
+//	Uppercases the first letter of each word
+
+	if(!dojo.lang.isString(str)){ return ""; }
+	if(arguments.length == 0){ str = this; }
+
+	var words = str.split(' ');
+	for(var i=0; i<words.length; i++){
+		words[i] = words[i].charAt(0).toUpperCase() + words[i].substring(1);
+	}
+	return words.join(" "); // string
+}
+
+dojo.string.isBlank = function(/*string*/str){
+// summary:
+//	Return true if the entire string is whitespace characters
+
+	if(!dojo.lang.isString(str)){ return true; }
+	return (dojo.string.trim(str).length == 0); // boolean
+}
+
+//FIXME: not sure exactly what encodeAscii is trying to do, or if it's working right
+dojo.string.encodeAscii = function(/*string*/str){
+	if(!dojo.lang.isString(str)){ return str; } // unknown
+	var ret = "";
+	var value = escape(str);
+	var match, re = /%u([0-9A-F]{4})/i;
+	while((match = value.match(re))){
+		var num = Number("0x"+match[1]);
+		var newVal = escape("&#" + num + ";");
+		ret += value.substring(0, match.index) + newVal;
+		value = value.substring(match.index+match[0].length);
+	}
+	ret += value.replace(/\+/g, "%2B");
+	return ret; // string
+}
+
+dojo.string.escape = function(/*string*/type, /*string*/str){
+// summary:
+//	Adds escape sequences for special characters according to the convention of 'type'
+//
+// type: one of xml|html|xhtml|sql|regexp|regex|javascript|jscript|js|ascii
+// str: the string to be escaped
+
+	var args = dojo.lang.toArray(arguments, 1);
+	switch(type.toLowerCase()){
+		case "xml":
+		case "html":
+		case "xhtml":
+			return dojo.string.escapeXml.apply(this, args); // string
+		case "sql":
+			return dojo.string.escapeSql.apply(this, args); // string
+		case "regexp":
+		case "regex":
+			return dojo.string.escapeRegExp.apply(this, args); // string
+		case "javascript":
+		case "jscript":
+		case "js":
+			return dojo.string.escapeJavaScript.apply(this, args); // string
+		case "ascii":
+			// so it's encode, but it seems useful
+			return dojo.string.encodeAscii.apply(this, args); // string
+		default:
+			return str; // string
+	}
+}
+
+dojo.string.escapeXml = function(/*string*/str, /*boolean*/noSingleQuotes){
+//summary:
+//	Adds escape sequences for special characters in XML: &<>"'
+//  Optionally skips escapes for single quotes
+
+	str = str.replace(/&/gm, "&amp;").replace(/</gm, "&lt;")
+		.replace(/>/gm, "&gt;").replace(/"/gm, "&quot;");
+	if(!noSingleQuotes){ str = str.replace(/'/gm, "&#39;"); }
+	return str; // string
+}
+
+dojo.string.escapeSql = function(/*string*/str){
+//summary:
+//	Adds escape sequences for single quotes in SQL expressions
+
+	return str.replace(/'/gm, "''"); //string
+}
+
+dojo.string.escapeRegExp = function(/*string*/str){
+//summary:
+//	Adds escape sequences for special characters in regular expressions
+
+	return str.replace(/\\/gm, "\\\\").replace(/([\f\b\n\t\r[\^$|?*+(){}])/gm, "\\$1"); // string
+}
+
+//FIXME: should this one also escape backslash?
+dojo.string.escapeJavaScript = function(/*string*/str){
+//summary:
+//	Adds escape sequences for single and double quotes as well
+//	as non-visible characters in JavaScript string literal expressions
+
+	return str.replace(/(["'\f\b\n\t\r])/gm, "\\$1"); // string
+}
+
+//FIXME: looks a lot like escapeJavaScript, just adds quotes? deprecate one?
+dojo.string.escapeString = function(/*string*/str){
+//summary:
+//	Adds escape sequences for non-visual characters, double quote and backslash
+//	and surrounds with double quotes to form a valid string literal.
+	return ('"' + str.replace(/(["\\])/g, '\\$1') + '"'
+		).replace(/[\f]/g, "\\f"
+		).replace(/[\b]/g, "\\b"
+		).replace(/[\n]/g, "\\n"
+		).replace(/[\t]/g, "\\t"
+		).replace(/[\r]/g, "\\r"); // string
+}
+
+// TODO: make an HTML version
+dojo.string.summary = function(/*string*/str, /*number*/len){
+// summary:
+//	Truncates 'str' after 'len' characters and appends periods as necessary so that it ends with "..."
+
+	if(!len || str.length <= len){
+		return str; // string
+	}
+
+	return str.substring(0, len).replace(/\.+$/, "") + "..."; // string
+}
+
+dojo.string.endsWith = function(/*string*/str, /*string*/end, /*boolean*/ignoreCase){
+// summary:
+//	Returns true if 'str' ends with 'end'
+
+	if(ignoreCase){
+		str = str.toLowerCase();
+		end = end.toLowerCase();
+	}
+	if((str.length - end.length) < 0){
+		return false; // boolean
+	}
+	return str.lastIndexOf(end) == str.length - end.length; // boolean
+}
+
+dojo.string.endsWithAny = function(/*string*/str /* , ... */){
+// summary:
+//	Returns true if 'str' ends with any of the arguments[2 -> n]
+
+	for(var i = 1; i < arguments.length; i++) {
+		if(dojo.string.endsWith(str, arguments[i])) {
+			return true; // boolean
+		}
+	}
+	return false; // boolean
+}
+
+dojo.string.startsWith = function(/*string*/str, /*string*/start, /*boolean*/ignoreCase){
+// summary:
+//	Returns true if 'str' starts with 'start'
+
+	if(ignoreCase) {
+		str = str.toLowerCase();
+		start = start.toLowerCase();
+	}
+	return str.indexOf(start) == 0; // boolean
+}
+
+dojo.string.startsWithAny = function(/*string*/str /* , ... */){
+// summary:
+//	Returns true if 'str' starts with any of the arguments[2 -> n]
+
+	for(var i = 1; i < arguments.length; i++) {
+		if(dojo.string.startsWith(str, arguments[i])) {
+			return true; // boolean
+		}
+	}
+	return false; // boolean
+}
+
+dojo.string.has = function(/*string*/str /* , ... */) {
+// summary:
+//	Returns true if 'str' contains any of the arguments 2 -> n
+
+	for(var i = 1; i < arguments.length; i++) {
+		if(str.indexOf(arguments[i]) > -1){
+			return true; // boolean
+		}
+	}
+	return false; // boolean
+}
+
+dojo.string.normalizeNewlines = function(/*string*/text, /*string? (\n or \r)*/newlineChar){
+// summary:
+//	Changes occurences of CR and LF in text to CRLF, or if newlineChar is provided as '\n' or '\r',
+//	substitutes newlineChar for occurrences of CR/LF and CRLF
+
+	if (newlineChar == "\n"){
+		text = text.replace(/\r\n/g, "\n");
+		text = text.replace(/\r/g, "\n");
+	} else if (newlineChar == "\r"){
+		text = text.replace(/\r\n/g, "\r");
+		text = text.replace(/\n/g, "\r");
+	}else{
+		text = text.replace(/([^\r])\n/g, "$1\r\n").replace(/\r([^\n])/g, "\r\n$1");
+	}
+	return text; // string
+}
+
+dojo.string.splitEscaped = function(/*string*/str, /*string of length=1*/charac){
+// summary:
+//	Splits 'str' into an array separated by 'charac', but skips characters escaped with a backslash
+
+	var components = [];
+	for (var i = 0, prevcomma = 0; i < str.length; i++){
+		if (str.charAt(i) == '\\'){ i++; continue; }
+		if (str.charAt(i) == charac){
+			components.push(str.substring(prevcomma, i));
+			prevcomma = i + 1;
+		}
+	}
+	components.push(str.substr(prevcomma));
+	return components; // array
+}

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/style.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/style.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/style.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/style.js Fri Sep 22 16:22:30 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.provide("dojo.style");
+dojo.kwCompoundRequire({
+	browser: ["dojo.html.style"]
+});
+dojo.deprecated("dojo.style", "replaced by dojo.html.style", "0.5");

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/svg.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/svg.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/svg.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/svg.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,279 @@
+/*
+	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.svg");
+dojo.require("dojo.lang.common");
+dojo.require("dojo.dom");
+
+dojo.mixin(dojo.svg, dojo.dom);
+
+dojo.svg.graphics=dojo.svg.g=new function(/* DomDocument */ d){
+	//	summary
+	//	Singleton to encapsulate SVG rendering functions.
+	this.suspend=function(){
+		//	summary
+		//	Suspend the rendering engine
+		try { d.documentElement.suspendRedraw(0); } catch(e){ }
+	};
+	this.resume=function(){
+		//	summary
+		//	Resume the rendering engine
+		try { d.documentElement.unsuspendRedraw(0); } catch(e){ }
+	};
+	this.force=function(){
+		//	summary
+		//	Force the render engine to redraw
+		try { d.documentElement.forceRedraw(); } catch(e){ }
+	};
+}(document);
+
+dojo.svg.animations=dojo.svg.anim=new function(/* DOMDocument */ d){
+	//	summary
+	//	Singleton to encapsulate SVG animation functionality.
+	this.arePaused=function(){
+		//	summary
+		//	check to see if all animations are paused
+		try {
+			return d.documentElement.animationsPaused();	//	bool
+		} catch(e){
+			return false;	//	bool
+		}
+	} ;
+	this.pause=function(){
+		//	summary
+		//	pause all animations
+		try { d.documentElement.pauseAnimations(); } catch(e){ }
+	};
+	this.resume=function(){
+		//	summary
+		//	resume all animations
+		try { d.documentElement.unpauseAnimations(); } catch(e){ }
+	};
+}(document);
+
+//	fixme: these functions should be mixed in from dojo.style, but dojo.style is HTML-centric and needs to change.
+dojo.svg.toCamelCase=function(/* string */ selector){
+	//	summary
+	//	converts a CSS-style selector to a camelCased one
+	var arr=selector.split('-'), cc=arr[0];
+	for(var i=1; i < arr.length; i++) {
+		cc += arr[i].charAt(0).toUpperCase() + arr[i].substring(1);
+	}
+	return cc;	// string
+};
+dojo.svg.toSelectorCase=function(/* string */ selector) {
+	//	summary
+	//	converts a camelCased selector to a CSS style one
+	return selector.replace(/([A-Z])/g, "-$1" ).toLowerCase();	//	string
+};
+dojo.svg.getStyle=function(/* SVGElement */ node, /* string */ cssSelector){
+	//	summary
+	//	get the computed style of selector for node.
+	return document.defaultView.getComputedStyle(node, cssSelector);	//	object
+};
+dojo.svg.getNumericStyle=function(/* SVGElement */ node, /* string */ cssSelector){
+	//	summary
+	//	return the numeric version of the computed style of selector on node.
+	return parseFloat(dojo.svg.getStyle(node, cssSelector));
+};
+
+//	fixme: there are different ways of doing the following, need to take into account
+dojo.svg.getOpacity=function(/* SVGElement */node){
+	//	summary
+	//	Return the opacity of the passed element
+	return Math.min(1.0, dojo.svg.getNumericStyle(node, "fill-opacity"));	//	float
+};
+dojo.svg.setOpacity=function(/* SVGElement */ node, /* float */ opacity){
+	//	summary
+	//	set the opacity of node using attributes.
+	node.setAttributeNS(this.xmlns.svg, "fill-opacity", opacity);
+	node.setAttributeNS(this.xmlns.svg, "stroke-opacity", opacity);
+};
+dojo.svg.clearOpacity=function(/* SVGElement */ node){
+	//	summary
+	//	Set any attributes setting opacity to opaque (1.0)
+	node.setAttributeNS(this.xmlns.svg, "fill-opacity", "1.0");
+	node.setAttributeNS(this.xmlns.svg, "stroke-opacity", "1.0");
+};
+
+/**
+ *	Coordinates and dimensions.
+ */
+
+// TODO ////////////////////////////////////////////////////////// TODO
+dojo.svg.getCoords=function(/* SVGElement */ node){
+	if (node.getBBox) {
+		var box=node.getBBox();
+		return { x: box.x, y: box.y };
+	}
+	return null;
+};
+dojo.svg.setCoords=function(node, coords){
+	var p=dojo.svg.getCoords();
+	if (!p) return;
+	var dx=p.x - coords.x;
+	var dy=p.y - coords.y;
+	dojo.svg.translate(node, dx, dy);
+};
+dojo.svg.getDimensions=function(node){
+	if (node.getBBox){
+		var box=node.getBBox();
+		return { width: box.width, height : box.height };
+	}
+	return null;
+};
+dojo.svg.setDimensions=function(node, dim){
+	//	will only support shape-based and container elements; path-based elements are ignored.
+	if (node.width){
+		node.width.baseVal.value=dim.width;
+		node.height.baseVal.value=dim.height;
+	}
+	else if (node.r){
+		node.r.baseVal.value=Math.min(dim.width, dim.height)/2;
+	}
+	else if (node.rx){
+		node.rx.baseVal.value=dim.width/2;
+		node.ry.baseVal.value=dim.height/2;
+	}
+};
+
+/**
+ *	Transformations.
+ */
+dojo.svg.translate=function(node, dx, dy){
+	if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){
+		var t=node.ownerSVGElement.createSVGTransform();
+		t.setTranslate(dx, dy);
+		node.transform.baseVal.appendItem(t);
+	}
+};
+dojo.svg.scale=function(node, scaleX, scaleY){
+	if (!scaleY) var scaleY=scaleX;
+	if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){
+		var t=node.ownerSVGElement.createSVGTransform();
+		t.setScale(scaleX, scaleY);
+		node.transform.baseVal.appendItem(t);
+	}
+};
+dojo.svg.rotate=function(node, ang, cx, cy){
+	if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){
+		var t=node.ownerSVGElement.createSVGTransform();
+		if (!cx) t.setMatrix(t.matrix.rotate(ang));
+		else t.setRotate(ang, cx, cy);
+		node.transform.baseVal.appendItem(t);
+	}
+};
+dojo.svg.skew=function(node, ang, axis){
+	var dir=axis || "x";
+	if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){
+		var t=node.ownerSVGElement.createSVGTransform();
+		if (dir != "x") t.setSkewY(ang);
+		else t.setSkewX(ang);
+		node.transform.baseVal.appendItem(t);
+	}
+};
+dojo.svg.flip=function(node, axis){
+	var dir=axis || "x";
+	if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){
+		var t=node.ownerSVGElement.createSVGTransform();
+		t.setMatrix((dir != "x") ? t.matrix.flipY() : t.matrix.flipX());
+		node.transform.baseVal.appendItem(t);
+	}
+};
+dojo.svg.invert=function(node){
+	if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){
+		var t=node.ownerSVGElement.createSVGTransform();
+		t.setMatrix(t.matrix.inverse());
+		node.transform.baseVal.appendItem(t);
+	}
+};
+dojo.svg.applyMatrix=function(node, a, b, c, d, e, f){
+	if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){
+		var m;
+		if (b){
+			var m=node.ownerSVGElement.createSVGMatrix();
+			m.a=a;
+			m.b=b;
+			m.c=c;
+			m.d=d;
+			m.e=e;
+			m.f=f;
+		} else m=a;
+		var t=node.ownerSVGElement.createSVGTransform();
+		t.setMatrix(m);
+		node.transform.baseVal.appendItem(t);
+	}
+};
+
+/**
+ *	Grouping and z-index operations.
+ */
+dojo.svg.group=function(nodes){
+	//	expect an array of nodes, attaches the group to the parent of the first node.
+	var p=nodes.item(0).parentNode;
+	var g=document.createElementNS(this.xmlns.svg, "g");
+	for (var i=0; i < nodes.length; i++) g.appendChild(nodes.item(i));
+	p.appendChild(g);
+	return g;
+};
+dojo.svg.ungroup=function(g){
+	//	puts the children of the group on the same level as group was.
+	var p=g.parentNode;
+	while (g.childNodes.length > 0) p.appendChild(g.childNodes.item(0));
+	p.removeChild(g);
+};
+//	if the node is part of a group, return the group, else return null.
+dojo.svg.getGroup=function(node){
+	//	if the node is part of a group, return the group, else return null.
+	var a=this.getAncestors(node);
+	for (var i=0; i < a.length; i++){
+		if (a[i].nodeType == this.ELEMENT_NODE && a[i].nodeName.toLowerCase() == "g")
+			return a[i];
+	}
+	return null;
+};
+dojo.svg.bringToFront=function(node){
+	var n=this.getGroup(node) || node;
+	n.ownerSVGElement.appendChild(n);
+};
+dojo.svg.sendToBack=function(node){
+	var n=this.getGroup(node) || node;
+	n.ownerSVGElement.insertBefore(n, n.ownerSVGElement.firstChild);
+};
+
+//	TODO: possibly push node up a level in the DOM if it's at the beginning or end of the childNodes list.
+dojo.svg.bringForward=function(node){
+	var n=this.getGroup(node) || node;
+	if (this.getLastChildElement(n.parentNode) != n){
+		this.insertAfter(n, this.getNextSiblingElement(n), true);
+	}
+};
+dojo.svg.sendBackward=function(node){
+	var n=this.getGroup(node) || node;
+	if (this.getFirstChildElement(n.parentNode) != n){
+		this.insertBefore(n, this.getPreviousSiblingElement(n), true);
+	}
+};
+// END TODO ////////////////////////////////////////////////////// TODO
+
+dojo.svg.createNodesFromText=function(/* string */ txt, /* bool? */ wrap){
+	//	summary
+	//	Create a list of nodes from text
+	var docFrag=(new DOMParser()).parseFromString(txt, "text/xml").normalize();
+	if(wrap){ 
+		return [docFrag.firstChild.cloneNode(true)];	//	array
+	}
+	var nodes=[];
+	for(var x=0; x<docFrag.childNodes.length; x++){
+		nodes.push(docFrag.childNodes.item(x).cloneNode(true));
+	}
+	return nodes;	// array
+}
+// vim:ts=4:noet:tw=0:

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/text/__package__.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/text/__package__.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/text/__package__.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/text/__package__.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,17 @@
+/*
+	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({
+	common: [
+		"dojo.text.String",
+		"dojo.text.Builder"
+	]
+});
+dojo.provide("dojo.text.*");

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/text/textDirectory.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/text/textDirectory.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/text/textDirectory.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/text/textDirectory.js Fri Sep 22 16:22:30 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
+*/
+
+dojo.provide("dojo.text.textDirectory");
+dojo.provide("dojo.text.textDirectory.Property");
+dojo.provide("dojo.text.textDirectory.tokenise");
+dojo.require("dojo.string");
+
+/* adapted from Paul Sowden's iCalendar work */
+
+dojo.textDirectoryTokeniser = function () {}
+
+/*
+ * This class parses a single line from a text/directory file
+ * and returns an object with four named values; name, group, params
+ * and value. name, group and value are strings containing the original
+ * tokens unaltered and values is an array containing name/value pairs
+ * or a single name token packed into arrays.
+ */
+dojo.textDirectoryTokeniser.Property = function (line) {
+	// split into name/value pair
+	var left = dojo.string.trim(line.substring(0, line.indexOf(':')));
+	var right = dojo.string.trim(line.substr(line.indexOf(':') + 1));
+
+	// seperate name and paramters	
+	var parameters = dojo.string.splitEscaped(left,';');
+	this.name = parameters[0]
+	parameters.splice(0, 1);
+
+	// parse paramters
+	this.params = [];
+	for (var i = 0; i < parameters.length; i++) {
+		var arr = parameters[i].split("=");
+		var key = dojo.string.trim(arr[0].toUpperCase());
+		
+		if (arr.length == 1) { this.params.push([key]); continue; }
+		
+		var values = dojo.string.splitEscaped(arr[1],',');
+		for (var j = 0; j < values.length; j++) {
+			if (dojo.string.trim(values[j]) != '') {
+				this.params.push([key, dojo.string.trim(values[j])]);
+			}
+		}
+	}
+
+	// seperate group
+	if (this.name.indexOf('.') > 0) {
+		var arr = this.name.split('.');
+		this.group = arr[0];
+		this.name = arr[1];
+	}
+	
+	// don't do any parsing, leave to implementation
+	this.value = right;
+}
+
+
+// tokeniser, parses into an array of properties.
+dojo.textDirectoryTokeniser.tokenise = function (text) {
+	// normlize to one propterty per line and parse
+	var nText = dojo.string.normalizeNewlines(text,"\n");
+	nText = nText.replace(/\n[ \t]/g, '');
+	nText = nText.replace(/\x00/g, '');
+		
+	var lines = nText.split("\n");
+	var properties = []
+
+	for (var i = 0; i < lines.length; i++) {
+		if (dojo.string.trim(lines[i]) == '') { continue; }
+		var prop = new dojo.textDirectoryTokeniser.Property(lines[i]);
+		properties.push(prop);
+	}
+	return properties;
+}

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/undo/Manager.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/undo/Manager.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/undo/Manager.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/undo/Manager.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,200 @@
+/*
+	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.undo.Manager");
+dojo.require("dojo.lang.common");
+
+dojo.undo.Manager = function(parent) {
+	this.clear();
+	this._parent = parent;
+};
+dojo.extend(dojo.undo.Manager, {
+	_parent: null,
+	_undoStack: null,
+	_redoStack: null,
+	_currentManager: null,
+
+	canUndo: false,
+	canRedo: false,
+
+	isUndoing: false,
+	isRedoing: false,
+
+	// these events allow you to hook in and update your code (UI?) as necessary
+	onUndo: function(manager, item) {},
+	onRedo: function(manager, item) {},
+
+	// fired when you do *any* undo action, which means you'll have one for every item
+	// in a transaction. this is usually only useful for debugging
+	onUndoAny: function(manager, item) {},
+	onRedoAny: function(manager, item) {},
+
+	_updateStatus: function() {
+		this.canUndo = this._undoStack.length > 0;
+		this.canRedo = this._redoStack.length > 0;
+	},
+
+	clear: function() {
+		this._undoStack = [];
+		this._redoStack = [];
+		this._currentManager = this;
+
+		this.isUndoing = false;
+		this.isRedoing = false;
+
+		this._updateStatus();
+	},
+
+	undo: function() {
+		if(!this.canUndo) { return false; }
+
+		this.endAllTransactions();
+
+		this.isUndoing = true;
+		var top = this._undoStack.pop();
+		if(top instanceof dojo.undo.Manager){
+			top.undoAll();
+		}else{
+			top.undo();
+		}
+		if(top.redo){
+			this._redoStack.push(top);
+		}
+		this.isUndoing = false;
+
+		this._updateStatus();
+		this.onUndo(this, top);
+		if(!(top instanceof dojo.undo.Manager)) {
+			this.getTop().onUndoAny(this, top);
+		}
+		return true;
+	},
+
+	redo: function() {
+		if(!this.canRedo){ return false; }
+
+		this.isRedoing = true;
+		var top = this._redoStack.pop();
+		if(top instanceof dojo.undo.Manager) {
+			top.redoAll();
+		}else{
+			top.redo();
+		}
+		this._undoStack.push(top);
+		this.isRedoing = false;
+
+		this._updateStatus();
+		this.onRedo(this, top);
+		if(!(top instanceof dojo.undo.Manager)){
+			this.getTop().onRedoAny(this, top);
+		}
+		return true;
+	},
+
+	undoAll: function() {
+		while(this._undoStack.length > 0) {
+			this.undo();
+		}
+	},
+
+	redoAll: function() {
+		while(this._redoStack.length > 0) {
+			this.redo();
+		}
+	},
+
+	push: function(undo, redo /* optional */, description /* optional */) {
+		if(!undo) { return; }
+
+		if(this._currentManager == this) {
+			this._undoStack.push({
+				undo: undo,
+				redo: redo,
+				description: description
+			});
+		} else {
+			this._currentManager.push.apply(this._currentManager, arguments);
+		}
+		// adding a new undo-able item clears out the redo stack
+		this._redoStack = [];
+		this._updateStatus();
+	},
+
+	concat: function(manager) {
+		if ( !manager ) { return; }
+
+		if (this._currentManager == this ) {
+			for(var x=0; x < manager._undoStack.length; x++) {
+				this._undoStack.push(manager._undoStack[x]);
+			}
+			// adding a new undo-able item clears out the redo stack
+			if (manager._undoStack.length > 0) {
+				this._redoStack = [];
+			}
+			this._updateStatus();
+		} else {
+			this._currentManager.concat.apply(this._currentManager, arguments);
+		}
+	},
+
+	beginTransaction: function(description /* optional */) {
+		if(this._currentManager == this) {
+			var mgr = new dojo.undo.Manager(this);
+			mgr.description = description ? description : "";
+			this._undoStack.push(mgr);
+			this._currentManager = mgr;
+			return mgr;
+		} else {
+			//for nested transactions need to make sure the top level _currentManager is set
+			this._currentManager = this._currentManager.beginTransaction.apply(this._currentManager, arguments);
+		}
+	},
+
+	endTransaction: function(flatten /* optional */) {
+		if(this._currentManager == this) {
+			if(this._parent) {
+				this._parent._currentManager = this._parent;
+				// don't leave empty transactions hangin' around
+				if(this._undoStack.length == 0 || flatten) {
+					var idx = dojo.lang.find(this._parent._undoStack, this);
+					if (idx >= 0) {
+						this._parent._undoStack.splice(idx, 1);
+						//add the current transaction to parents undo stack
+						if (flatten) {
+							for(var x=0; x < this._undoStack.length; x++){
+								this._parent._undoStack.splice(idx++, 0, this._undoStack[x]);
+							}
+							this._updateStatus();
+						}
+					}
+				}
+				return this._parent;
+			}
+		} else {
+			//for nested transactions need to make sure the top level _currentManager is set
+			this._currentManager = this._currentManager.endTransaction.apply(this._currentManager, arguments);
+		}
+	},
+
+	endAllTransactions: function() {
+		while(this._currentManager != this) {
+			this.endTransaction();
+		}
+	},
+
+	// find the top parent of an undo manager
+	getTop: function() {
+		if(this._parent) {
+			return this._parent.getTop();
+		} else {
+			return this;
+		}
+	}
+});

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/undo/__package__.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/undo/__package__.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/undo/__package__.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/undo/__package__.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,12 @@
+/*
+	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.undo.Manager");
+dojo.provide("dojo.undo.*");

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/undo/browser.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/undo/browser.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/undo/browser.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/undo/browser.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,309 @@
+/*
+	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.undo.browser");
+dojo.require("dojo.io.common");
+
+try{
+	if((!djConfig["preventBackButtonFix"])&&(!dojo.hostenv.post_load_)){
+		document.write("<iframe style='border: 0px; width: 1px; height: 1px; position: absolute; bottom: 0px; right: 0px; visibility: visible;' name='djhistory' id='djhistory' src='"+(dojo.hostenv.getBaseScriptUri()+'iframe_history.html')+"'></iframe>");
+	}
+}catch(e){/* squelch */}
+
+if(dojo.render.html.opera){
+	dojo.debug("Opera is not supported with dojo.undo.browser, so back/forward detection will not work.");
+}
+
+/* NOTES:
+ *  Safari 1.2: 
+ *	back button "works" fine, however it's not possible to actually
+ *	DETECT that you've moved backwards by inspecting window.location.
+ *	Unless there is some other means of locating.
+ *	FIXME: perhaps we can poll on history.length?
+ *  Safari 2.0.3+ (and probably 1.3.2+):
+ *	works fine, except when changeUrl is used. When changeUrl is used,
+ *	Safari jumps all the way back to whatever page was shown before
+ *	the page that uses dojo.undo.browser support.
+ *  IE 5.5 SP2:
+ *	back button behavior is macro. It does not move back to the
+ *	previous hash value, but to the last full page load. This suggests
+ *	that the iframe is the correct way to capture the back button in
+ *	these cases.
+ *	Don't test this page using local disk for MSIE. MSIE will not create 
+ *	a history list for iframe_history.html if served from a file: URL. 
+ *	The XML served back from the XHR tests will also not be properly 
+ *	created if served from local disk. Serve the test pages from a web 
+ *	server to test in that browser.
+ *  IE 6.0:
+ *	same behavior as IE 5.5 SP2
+ * Firefox 1.0+:
+ *	the back button will return us to the previous hash on the same
+ *	page, thereby not requiring an iframe hack, although we do then
+ *	need to run a timer to detect inter-page movement.
+ */
+
+dojo.undo.browser = {
+	initialHref: window.location.href,
+	initialHash: window.location.hash,
+
+	moveForward: false,
+	historyStack: [],
+	forwardStack: [],
+	historyIframe: null,
+	bookmarkAnchor: null,
+	locationTimer: null,
+
+	/**
+	 * setInitialState sets the state object and back callback for the very first page that is loaded.
+	 * It is recommended that you call this method as part of an event listener that is registered via
+	 * dojo.addOnLoad().
+	 */
+	setInitialState: function(args){
+		this.initialState = this._createState(this.initialHref, args, this.initialHash);
+	},
+
+	//FIXME: Would like to support arbitrary back/forward jumps. Have to rework iframeLoaded among other things.
+	//FIXME: is there a slight race condition in moz using change URL with the timer check and when
+	//       the hash gets set? I think I have seen a back/forward call in quick succession, but not consistent.
+	/**
+	 * addToHistory takes one argument, and it is an object that defines the following functions:
+	 * - To support getting back button notifications, the object argument should implement a
+	 *   function called either "back", "backButton", or "handle". The string "back" will be
+	 *   passed as the first and only argument to this callback.
+	 * - To support getting forward button notifications, the object argument should implement a
+	 *   function called either "forward", "forwardButton", or "handle". The string "forward" will be
+	 *   passed as the first and only argument to this callback.
+	 * - If you want the browser location string to change, define "changeUrl" on the object. If the
+	 *   value of "changeUrl" is true, then a unique number will be appended to the URL as a fragment
+	 *   identifier (http://some.domain.com/path#uniquenumber). If it is any other value that does
+	 *   not evaluate to false, that value will be used as the fragment identifier. For example,
+	 *   if changeUrl: 'page1', then the URL will look like: http://some.domain.com/path#page1
+	 *   
+	 * Full example:
+	 * 
+	 * dojo.undo.browser.addToHistory({
+	 *   back: function() { alert('back pressed'); },
+	 *   forward: function() { alert('forward pressed'); },
+	 *   changeUrl: true
+	 * });
+	 */
+	addToHistory: function(args){
+		//If addToHistory is called, then that means we prune the
+		//forward stack -- the user went back, then wanted to
+		//start a new forward path.
+		this.forwardStack = []; 
+
+		var hash = null;
+		var url = null;
+		if(!this.historyIframe){
+			this.historyIframe = window.frames["djhistory"];
+		}
+		if(!this.bookmarkAnchor){
+			this.bookmarkAnchor = document.createElement("a");
+			dojo.body().appendChild(this.bookmarkAnchor);
+			this.bookmarkAnchor.style.display = "none";
+		}
+		if(args["changeUrl"]){
+			hash = "#"+ ((args["changeUrl"]!==true) ? args["changeUrl"] : (new Date()).getTime());
+			
+			//If the current hash matches the new one, just replace the history object with
+			//this new one. It doesn't make sense to track different state objects for the same
+			//logical URL. This matches the browser behavior of only putting in one history
+			//item no matter how many times you click on the same #hash link, at least in Firefox
+			//and Safari, and there is no reliable way in those browsers to know if a #hash link
+			//has been clicked on multiple times. So making this the standard behavior in all browsers
+			//so that dojo.undo.browser's behavior is the same in all browsers.
+			if(this.historyStack.length == 0 && this.initialState.urlHash == hash){
+				this.initialState = this._createState(url, args, hash);
+				return;
+			}else if(this.historyStack.length > 0 && this.historyStack[this.historyStack.length - 1].urlHash == hash){
+				this.historyStack[this.historyStack.length - 1] = this._createState(url, args, hash);
+				return;
+			}
+
+			this.changingUrl = true;
+			setTimeout("window.location.href = '"+hash+"'; dojo.undo.browser.changingUrl = false;", 1);
+			this.bookmarkAnchor.href = hash;
+			
+			if(dojo.render.html.ie){
+				url = this._loadIframeHistory();
+
+				var oldCB = args["back"]||args["backButton"]||args["handle"];
+
+				//The function takes handleName as a parameter, in case the
+				//callback we are overriding was "handle". In that case,
+				//we will need to pass the handle name to handle.
+				var tcb = function(handleName){
+					if(window.location.hash != ""){
+						setTimeout("window.location.href = '"+hash+"';", 1);
+					}
+					//Use apply to set "this" to args, and to try to avoid memory leaks.
+					oldCB.apply(this, [handleName]);
+				}
+		
+				//Set interceptor function in the right place.
+				if(args["back"]){
+					args.back = tcb;
+				}else if(args["backButton"]){
+					args.backButton = tcb;
+				}else if(args["handle"]){
+					args.handle = tcb;
+				}
+		
+				var oldFW = args["forward"]||args["forwardButton"]||args["handle"];
+		
+				//The function takes handleName as a parameter, in case the
+				//callback we are overriding was "handle". In that case,
+				//we will need to pass the handle name to handle.
+				var tfw = function(handleName){
+					if(window.location.hash != ""){
+						window.location.href = hash;
+					}
+					if(oldFW){ // we might not actually have one
+						//Use apply to set "this" to args, and to try to avoid memory leaks.
+						oldFW.apply(this, [handleName]);
+					}
+				}
+
+				//Set interceptor function in the right place.
+				if(args["forward"]){
+					args.forward = tfw;
+				}else if(args["forwardButton"]){
+					args.forwardButton = tfw;
+				}else if(args["handle"]){
+					args.handle = tfw;
+				}
+
+			}else if(dojo.render.html.moz){
+				// start the timer
+				if(!this.locationTimer){
+					this.locationTimer = setInterval("dojo.undo.browser.checkLocation();", 200);
+				}
+			}
+		}else{
+			url = this._loadIframeHistory();
+		}
+
+		this.historyStack.push(this._createState(url, args, hash));
+	},
+
+	checkLocation: function(){
+		if (!this.changingUrl){
+			var hsl = this.historyStack.length;
+
+			if((window.location.hash == this.initialHash||window.location.href == this.initialHref)&&(hsl == 1)){
+				// FIXME: could this ever be a forward button?
+				// we can't clear it because we still need to check for forwards. Ugg.
+				// clearInterval(this.locationTimer);
+				this.handleBackButton();
+				return;
+			}
+			
+			// first check to see if we could have gone forward. We always halt on
+			// a no-hash item.
+			if(this.forwardStack.length > 0){
+				if(this.forwardStack[this.forwardStack.length-1].urlHash == window.location.hash){
+					this.handleForwardButton();
+					return;
+				}
+			}
+	
+			// ok, that didn't work, try someplace back in the history stack
+			if((hsl >= 2)&&(this.historyStack[hsl-2])){
+				if(this.historyStack[hsl-2].urlHash==window.location.hash){
+					this.handleBackButton();
+					return;
+				}
+			}
+		}
+	},
+
+	iframeLoaded: function(evt, ifrLoc){
+		if(!dojo.render.html.opera){
+			var query = this._getUrlQuery(ifrLoc.href);
+			if(query == null){ 
+				// alert("iframeLoaded");
+				// we hit the end of the history, so we should go back
+				if(this.historyStack.length == 1){
+					this.handleBackButton();
+				}
+				return;
+			}
+			if(this.moveForward){
+				// we were expecting it, so it's not either a forward or backward movement
+				this.moveForward = false;
+				return;
+			}
+	
+			//Check the back stack first, since it is more likely.
+			//Note that only one step back or forward is supported.
+			if(this.historyStack.length >= 2 && query == this._getUrlQuery(this.historyStack[this.historyStack.length-2].url)){
+				this.handleBackButton();
+			}
+			else if(this.forwardStack.length > 0 && query == this._getUrlQuery(this.forwardStack[this.forwardStack.length-1].url)){
+				this.handleForwardButton();
+			}
+		}
+	},
+
+	handleBackButton: function(){
+		//The "current" page is always at the top of the history stack.
+		var current = this.historyStack.pop();
+		if(!current){ return; }
+		var last = this.historyStack[this.historyStack.length-1];
+		if(!last && this.historyStack.length == 0){
+			last = this.initialState;
+		}
+		if (last){
+			if(last.kwArgs["back"]){
+				last.kwArgs["back"]();
+			}else if(last.kwArgs["backButton"]){
+				last.kwArgs["backButton"]();
+			}else if(last.kwArgs["handle"]){
+				last.kwArgs.handle("back");
+			}
+		}
+		this.forwardStack.push(current);
+	},
+
+	handleForwardButton: function(){
+		var last = this.forwardStack.pop();
+		if(!last){ return; }
+		if(last.kwArgs["forward"]){
+			last.kwArgs.forward();
+		}else if(last.kwArgs["forwardButton"]){
+			last.kwArgs.forwardButton();
+		}else if(last.kwArgs["handle"]){
+			last.kwArgs.handle("forward");
+		}
+		this.historyStack.push(last);
+	},
+
+	_createState: function(url, args, hash){
+		return {"url": url, "kwArgs": args, "urlHash": hash};	
+	},
+
+	_getUrlQuery: function(url){
+		var segments = url.split("?");
+		if (segments.length < 2){
+			return null;
+		}
+		else{
+			return segments[1];
+		}
+	},
+	
+	_loadIframeHistory: function(){
+		var url = dojo.hostenv.getBaseScriptUri()+"iframe_history.html?"+(new Date()).getTime();
+		this.moveForward = true;
+		dojo.io.setIFrameSrc(this.historyIframe, url, false);	
+		return url;
+	}
+}

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/uri/Uri.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/uri/Uri.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/uri/Uri.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/uri/Uri.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,92 @@
+/*
+	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.uri.Uri");
+
+dojo.uri = new function() {
+	this.dojoUri = function (uri) {
+		// returns a Uri object resolved relative to the dojo root
+		return new dojo.uri.Uri(dojo.hostenv.getBaseScriptUri(), uri);
+	}
+	
+	// returns a Uri object relative to a (top-level) module
+	// for example dojo.uri.moduleUri("dojo","Editor"), or dojo.uri.moduleUri("acme","someWidget")
+	this.moduleUri = function(module, uri){
+		var loc = dojo.hostenv.getModulePrefix(module);
+		if(!loc){return null;}
+		if(loc.lastIndexOf("/") != loc.length-1){loc += "/";}
+		return new dojo.uri.Uri(dojo.hostenv.getBaseScriptUri()+loc,uri);
+	}
+
+	this.nsUri = function(ns,uri){
+		// by convention a namespace matches a top-level module, but strictly speaking Dojo namespaces are a widget concept
+		dojo.deprecated("dojo.uri.nsUri", "replaced by dojo.uri.moduleUri", "0.4");
+		return dojo.uri.moduleUri(ns,uri);
+	}
+
+	this.Uri = function (/*uri1, uri2, [...]*/) {
+		// An object representing a Uri.
+		// Each argument is evaluated in order relative to the next until
+		// a conanical uri is producued. To get an absolute Uri relative
+		// to the current document use
+		//      new dojo.uri.Uri(document.baseURI, uri)
+
+		// TODO: support for IPv6, see RFC 2732
+
+		// resolve uri components relative to each other
+		var uri = arguments[0];
+		for (var i = 1; i < arguments.length; i++) {
+			if(!arguments[i]) { continue; }
+
+			// Safari doesn't support this.constructor so we have to be explicit
+			var relobj = new dojo.uri.Uri(arguments[i].toString());
+			var uriobj = new dojo.uri.Uri(uri.toString());
+			
+			if (relobj.path == "" && relobj.scheme == null &&
+				relobj.authority == null && relobj.query == null) {
+				if (relobj.fragment != null) { uriobj.fragment = relobj.fragment; }
+				relobj = uriobj;
+			}
+			
+			if (relobj.scheme != null && relobj.authority != null)
+				uri = "";
+			if (relobj.scheme != null) { uri += relobj.scheme + ":"; }
+			if (relobj.authority != null) { uri += "//" + relobj.authority; }
+			uri += relobj.path;
+			if (relobj.query != null) { uri += "?" + relobj.query; }
+			if (relobj.fragment != null) { uri += "#" + relobj.fragment; }
+		}
+		
+		this.uri = uri.toString();
+
+		// break the uri into its main components
+		var regexp = "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$";
+	    var r = this.uri.match(new RegExp(regexp));
+
+		this.scheme = r[2] || (r[1] ? "" : null);
+		this.authority = r[4] || (r[3] ? "" : null);
+		this.path = r[5]; // can never be undefined
+		this.query = r[7] || (r[6] ? "" : null);
+		this.fragment  = r[9] || (r[8] ? "" : null);
+		
+		if (this.authority != null) {
+			// server based naming authority
+			regexp = "^((([^:]+:)?([^@]+))@)?([^:]*)(:([0-9]+))?$";
+			r = this.authority.match(new RegExp(regexp));
+			
+			this.user = r[3] || null;
+			this.password = r[4] || null;
+			this.host = r[5];
+			this.port = r[7] || null;
+		}
+	
+		this.toString = function(){ return this.uri; }
+	}
+};

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/uri/__package__.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/uri/__package__.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/uri/__package__.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/uri/__package__.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,14 @@
+/*
+	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({
+	common: [["dojo.uri.Uri", false, false]]
+});
+dojo.provide("dojo.uri.*");

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/uuid/LightweightGenerator.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/uuid/LightweightGenerator.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/uuid/LightweightGenerator.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/uuid/LightweightGenerator.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,69 @@
+/*
+	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.uuid.LightweightGenerator");
+
+dojo.uuid.LightweightGenerator = new function() {
+/*
+ * The LightweightGenerator is intended to be small and fast,
+ * but not necessarily good.
+ * 
+ * Small: The LightweightGenerator has a small footprint. 
+ * Once comments are stripped, it's only about 25 lines of 
+ * code, and it doesn't dojo.require() any other packages.
+ *
+ * Fast: The LightweightGenerator can generate lots of new 
+ * UUIDs fairly quickly (at least, more quickly than the other 
+ * dojo UUID generators).
+ *
+ * Not necessarily good: We use Math.random() as our source
+ * of randomness, which may or may not provide much randomness. 
+ */
+	var HEX_RADIX = 16;
+
+	function _generateRandomEightCharacterHexString() {
+		// Make random32bitNumber be a randomly generated floating point number
+		// between 0 and (4,294,967,296 - 1), inclusive.
+		var random32bitNumber = Math.floor( (Math.random() % 1) * Math.pow(2, 32) );
+		var eightCharacterHexString = random32bitNumber.toString(HEX_RADIX);
+		while (eightCharacterHexString.length < 8) {
+			eightCharacterHexString = "0" + eightCharacterHexString;
+		}
+		return eightCharacterHexString; // for example: "3B12F1DF"
+	}
+
+	this.generate = function(/* constructor? */ returnType) {
+		// Summary: 
+		//   This function generates random UUIDs, meaning "version 4" UUIDs.
+		// returnType: constructor The type of object to return. Usually String or dojo.uuid.Uuid
+		// Description: 
+		//   A typical generated value would be something like this:
+		//   "3b12f1df-5232-4804-897e-917bf397618a"
+		// Examples: 
+		//   var string = dojo.uuid.LightweightGenerator.generate();
+		//   var string = dojo.uuid.LightweightGenerator.generate(String);
+		//   var uuid   = dojo.uuid.LightweightGenerator.generate(dojo.uuid.Uuid);
+		var hyphen = "-";
+		var versionCodeForRandomlyGeneratedUuids = "4"; // 8 == binary2hex("0100")
+		var variantCodeForDCEUuids = "8"; // 8 == binary2hex("1000")
+		var a = _generateRandomEightCharacterHexString();
+		var b = _generateRandomEightCharacterHexString();
+		b = b.substring(0, 4) + hyphen + versionCodeForRandomlyGeneratedUuids + b.substring(5, 8);
+		var c = _generateRandomEightCharacterHexString();
+		c = variantCodeForDCEUuids + c.substring(1, 4) + hyphen + c.substring(4, 8);
+		var d = _generateRandomEightCharacterHexString();
+		var returnValue = a + hyphen + b + hyphen + c + d;
+		returnValue = returnValue.toLowerCase();
+		if (returnType && (returnType != String)) {
+			returnValue = new returnType(returnValue);
+		}
+		return returnValue;
+	};
+}();

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/uuid/NameBasedGenerator.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/uuid/NameBasedGenerator.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/uuid/NameBasedGenerator.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/uuid/NameBasedGenerator.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,37 @@
+/*
+	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.uuid.NameBasedGenerator");
+
+dojo.uuid.NameBasedGenerator = new function() {
+	this.generate = function(/* constructor? */ returnType) {
+		// Summary: 
+		//   This function generates name-based UUIDs, meaning "version 3" 
+		//   and "version 5" UUIDs.
+		// returnType: constructor The type of object to return. Usually String or dojo.uuid.Uuid
+		// Examples: 
+		//   var string = dojo.uuid.NameBasedGenerator.generate();
+		//   var string = dojo.uuid.NameBasedGenerator.generate(String);
+		//   var uuid   = dojo.uuid.NameBasedGenerator.generate(dojo.uuid.Uuid);
+
+		dojo.unimplemented('dojo.uuid.NameBasedGenerator.generate');
+		
+		// FIXME:
+		// For an algorithm to generate name-based UUIDs, 
+		// see sections 4.3 of RFC 4122:
+		//  http://www.ietf.org/rfc/rfc4122.txt
+		
+		var returnValue = "00000000-0000-0000-0000-000000000000"; // FIXME
+		if (returnType && (returnType != String)) {
+			returnValue = new returnType(returnValue);
+		}
+		return returnValue; // object
+	};
+}();
\ No newline at end of file

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