tapestry-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jkuhn...@apache.org
Subject svn commit: r406128 [14/27] - in /tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo: ./ src/ src/animation/ src/collections/ src/compat/ src/crypto/ src/data/ src/data/format/ src/data/provider/ src/debug/ src/dnd/ src/event/ sr...
Date Sat, 13 May 2006 16:37:00 GMT
Added: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/reflect/reflection.js
URL: http://svn.apache.org/viewcvs/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/reflect/reflection.js?rev=406128&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/reflect/reflection.js (added)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/reflect/reflection.js Sat May 13 09:36:25 2006
@@ -0,0 +1,198 @@
+/*
+	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.deprecated("dojo.reflect", "merged into dojo.lang (dojo.lang[type])", "0.4");
+dojo.provide("dojo.reflect");
+
+/*****************************************************************
+	reflect.js
+	v.1.5.0
+	(c) 2003-2004 Thomas R. Trenka, Ph.D.
+
+	Derived from the reflection functions of f(m).
+	http://dojotoolkit.org
+	http://fm.dept-z.com
+
+	There is a dependency on the variable dJ_global, which
+	should always refer to the global object.
+******************************************************************/
+if(!dj_global){ var dj_global = this; }
+
+dojo.reflect = {} ;
+dojo.reflect.$unknownType = function(){ } ;
+dojo.reflect.ParameterInfo = function(name, type){ 
+	this.name = name ;
+	this.type = (type) ? type : dojo.reflect.$unknownType ;
+} ;
+dojo.reflect.PropertyInfo = function(name, type) { 
+	this.name = name ;
+	this.type = (type) ? type : dojo.reflect.$unknownType ;
+} ;
+dojo.reflect.MethodInfo = function(name, fn){
+	var parse = function(f) {
+		var o = {} ; 
+		var s = f.toString() ;
+		var param = ((s.substring(s.indexOf('(')+1, s.indexOf(')'))).replace(/\s+/g, "")).split(",") ;
+		o.parameters = [] ;
+		for (var i = 0; i < param.length; i++) {
+			o.parameters.push(new dojo.reflect.ParameterInfo(param[i])) ;
+		}
+		o.body = (s.substring(s.indexOf('{')+1, s.lastIndexOf('}'))).replace(/(^\s*)|(\s*$)/g, "") ;
+		return o ;
+	} ;
+
+	var tmp = parse(fn) ;
+	var p = tmp.parameters ;
+	var body = tmp.body ;
+	
+	this.name = (name) ? name : "anonymous" ;
+	this.getParameters = function(){ return p ; } ;
+	this.getNullArgumentsObject = function() {
+		var a = [] ;
+		for (var i = 0; i < p.length; i++){
+			a.push(null);
+		}
+		return a ;
+	} ;
+	this.getBody = function() { return body ; } ;
+	this.type = Function ;
+	this.invoke = function(src, args){ return fn.apply(src, args) ; } ;
+} ;
+
+//	Static object that can activate instances of the passed type.
+dojo.reflect.Activator = new (function(){
+	this.createInstance = function(type, args) {
+		switch (typeof(type)) {
+			case "function" : { 
+				var o = {} ;
+				type.apply(o, args) ;
+				return o ;
+			} ;
+			case "string" : {
+				var o = {} ;
+				(dojo.reflect.Reflector.getTypeFromString(type)).apply(o, args) ;
+				return o ;
+			} ;
+		}
+		throw new Error("dojo.reflect.Activator.createInstance(): no such type exists.");
+	}
+})() ;
+
+dojo.reflect.Reflector = new (function(){
+	this.getTypeFromString = function(s) {
+		var parts = s.split("."), i = 0, obj = dj_global ; 
+		do { obj = obj[parts[i++]] ; } while (i < parts.length && obj) ; 
+		return (obj != dj_global) ? obj : null ;
+	}; 
+
+	this.typeExists = function(s) {
+		var parts = s.split("."), i = 0, obj = dj_global ; 
+		do { obj = obj[parts[i++]] ; } while (i < parts.length && obj) ; 
+		return (obj && obj != dj_global) ;
+	}; 
+
+	this.getFieldsFromType = function(s) { 
+		var type = s ;
+		if (typeof(s) == "string") {
+			type = this.getTypeFromString(s) ;
+		}
+		var nullArgs = (new dojo.reflect.MethodInfo(type)).getNullArgumentsObject() ;
+		return this.getFields(dojo.reflect.Activator.createInstance(s, nullArgs)) ;
+	};
+
+	this.getPropertiesFromType = function(s) { 
+		var type = s ;
+		if (typeof(s) == "string") {
+			type = this.getTypeFromString(s);
+		}
+		var nullArgs = (new dojo.reflect.MethodInfo(type)).getNullArgumentsObject() ;
+		return this.getProperties(dojo.reflect.Activator.createInstance(s, nullArgs)) ;
+	};
+
+	this.getMethodsFromType = function(s) { 
+		var type = s ;
+		if (typeof(s) == "string") {
+			type = this.getTypeFromString(s) ;
+		}
+		var nullArgs = (new dojo.reflect.MethodInfo(type)).getNullArgumentsObject() ;
+		return this.getMethods(dojo.reflect.Activator.createInstance(s, nullArgs)) ;
+	};
+
+	this.getType = function(o) { return o.constructor ; } ;
+
+	this.getFields = function(obj) {
+		var arr = [] ;
+		for (var p in obj) { 
+			if(this.getType(obj[p]) != Function){
+				arr.push(new dojo.reflect.PropertyInfo(p, this.getType(obj[p]))) ;
+			}else{
+				arr.push(new dojo.reflect.MethodInfo(p, obj[p]));
+			}
+		}
+		return arr ;
+	};
+
+	this.getProperties = function(obj) {
+		var arr = [] ;
+		var fi = this.getFields(obj) ;
+		for (var i = 0; i < fi.length; i++){
+			if (this.isInstanceOf(fi[i], dojo.reflect.PropertyInfo)){
+				arr.push(fi[i]) ;
+			}
+		}
+		return arr ;
+	};
+
+	this.getMethods = function(obj) {
+		var arr = [] ;
+		var fi = this.getFields(obj) ;
+		for (var i = 0; i < fi.length; i++){
+			if (this.isInstanceOf(fi[i], dojo.reflect.MethodInfo)){
+				arr.push(fi[i]) ;
+			}
+		}
+		return arr ;
+	};
+
+	/*
+	this.implements = function(o, type) {
+		if (this.isSubTypeOf(o, type)) return false ;
+		var f = this.getFieldsFromType(type) ;
+		for (var i = 0; i < f.length; i++) {
+			if (typeof(o[(f[i].name)]) == "undefined"){
+				return false;
+			}
+		}
+		return true ;
+	};
+	*/
+
+	this.getBaseClass = function(o) {
+		if (o.getType().prototype.prototype.constructor){
+			return (o.getType()).prototype.prototype.constructor ;
+		}
+		return Object ;
+	} ;
+
+	this.isInstanceOf = function(o, type) { 
+		return (this.getType(o) == type) ; 
+	};
+
+	this.isSubTypeOf = function(o, type) { 
+		return (o instanceof type) ; 
+	};
+
+	this.isBaseTypeOf = function(o, type) { 
+		return (type instanceof o); 
+	};
+})();
+
+// back-compat
+dojo.provide("dojo.reflect.reflection");

Added: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/regexp.js
URL: http://svn.apache.org/viewcvs/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/regexp.js?rev=406128&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/regexp.js (added)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/regexp.js Sat May 13 09:36:25 2006
@@ -0,0 +1,566 @@
+/*
+	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.regexp");
+dojo.provide("dojo.regexp.us");
+
+// *** Regular Expression Generators ***
+
+/**
+  Builds a RE that matches a top-level domain.
+
+  @param flags  An object.
+    flags.allowCC  Include 2 letter country code domains.  Default is true.
+    flags.allowGeneric  Include the generic domains.  Default is true.
+    flags.allowInfra  Include infrastructure domains.  Default is true.
+
+  @return  A string for a regular expression for a top-level domain.
+*/
+dojo.regexp.tld = function(flags) {
+	// assign default values to missing paramters
+	flags = (typeof flags == "object") ? flags : {};
+	if (typeof flags.allowCC != "boolean") { flags.allowCC = true; }
+	if (typeof flags.allowInfra != "boolean") { flags.allowInfra = true; }
+	if (typeof flags.allowGeneric != "boolean") { flags.allowGeneric = true; }
+
+	// Infrastructure top-level domain - only one at present
+	var infraRE = "arpa";
+
+	// Generic top-level domains RE.
+	var genericRE = 
+		"aero|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro|travel|xxx|jobs|mobi|post";
+	
+	// Country Code top-level domains RE
+	var ccRE = 
+		"ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|" +
+		"bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|" +
+		"ec|ee|eg|er|es|et|fi|fj|fk|fm|fo|fr|ga|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|" +
+		"hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kr|kw|ky|kz|la|" +
+		"lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|" +
+		"mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|" +
+		"ro|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sk|sl|sm|sn|sr|st|su|sv|sy|sz|tc|td|tf|tg|th|tj|tk|tm|tn|" +
+		"to|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw";
+
+	// Build top-level domain RE
+	var a = [];
+	if (flags.allowInfra) { a.push(infraRE); }
+	if (flags.allowGeneric) { a.push(genericRE); }
+	if (flags.allowCC) { a.push(ccRE); }
+
+	var tldRE = "";
+	if (a.length > 0) {
+		tldRE = "(" + a.join("|") + ")";
+	}
+
+	return tldRE;
+}
+
+/**
+  Builds a RE that matches an IP Address.
+  Supports 5 formats for IPv4: dotted decimal, dotted hex, dotted octal, decimal and hexadecimal.
+  Supports 2 formats for Ipv6.
+
+  @param flags  An object.  All flags are boolean with default = true.
+    flags.allowDottedDecimal  Example, 207.142.131.235.  No zero padding.
+    flags.allowDottedHex  Example, 0x18.0x11.0x9b.0x28.  Case insensitive.  Zero padding allowed.
+    flags.allowDottedOctal  Example, 0030.0021.0233.0050.  Zero padding allowed.
+    flags.allowDecimal  Example, 3482223595.  A decimal number between 0-4294967295.
+    flags.allowHex  Example, 0xCF8E83EB.  Hexadecimal number between 0x0-0xFFFFFFFF.
+      Case insensitive.  Zero padding allowed.
+    flags.allowIPv6   IPv6 address written as eight groups of four hexadecimal digits.
+    flags.allowHybrid   IPv6 address written as six groups of four hexadecimal digits
+      followed by the usual 4 dotted decimal digit notation of IPv4. x:x:x:x:x:x:d.d.d.d
+
+  @return  A string for a regular expression for an IP address.
+*/
+dojo.regexp.ipAddress = function(flags) {
+	// assign default values to missing paramters
+	flags = (typeof flags == "object") ? flags : {};
+	if (typeof flags.allowDottedDecimal != "boolean") { flags.allowDottedDecimal = true; }
+	if (typeof flags.allowDottedHex != "boolean") { flags.allowDottedHex = true; }
+	if (typeof flags.allowDottedOctal != "boolean") { flags.allowDottedOctal = true; }
+	if (typeof flags.allowDecimal != "boolean") { flags.allowDecimal = true; }
+	if (typeof flags.allowHex != "boolean") { flags.allowHex = true; }
+	if (typeof flags.allowIPv6 != "boolean") { flags.allowIPv6 = true; }
+	if (typeof flags.allowHybrid != "boolean") { flags.allowHybrid = true; }
+
+	// decimal-dotted IP address RE.
+	var dottedDecimalRE = 
+		// Each number is between 0-255.  Zero padding is not allowed.
+		"((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])";
+
+	// dotted hex IP address RE.  Each number is between 0x0-0xff.  Zero padding is allowed, e.g. 0x00.
+	var dottedHexRE = "(0[xX]0*[\\da-fA-F]?[\\da-fA-F]\\.){3}0[xX]0*[\\da-fA-F]?[\\da-fA-F]";
+
+	// dotted octal IP address RE.  Each number is between 0000-0377.  
+	// Zero padding is allowed, but each number must have at least 4 characters.
+	var dottedOctalRE = "(0+[0-3][0-7][0-7]\\.){3}0+[0-3][0-7][0-7]";
+
+	// decimal IP address RE.  A decimal number between 0-4294967295.  
+	var decimalRE =  "(0|[1-9]\\d{0,8}|[1-3]\\d{9}|4[01]\\d{8}|42[0-8]\\d{7}|429[0-3]\\d{6}|" +
+		"4294[0-8]\\d{5}|42949[0-5]\\d{4}|429496[0-6]\\d{3}|4294967[01]\\d{2}|42949672[0-8]\\d|429496729[0-5])";
+
+	// hexadecimal IP address RE. 
+	// A hexadecimal number between 0x0-0xFFFFFFFF. Case insensitive.  Zero padding is allowed.
+	var hexRE = "0[xX]0*[\\da-fA-F]{1,8}";
+
+	// IPv6 address RE. 
+	// The format is written as eight groups of four hexadecimal digits, x:x:x:x:x:x:x:x,
+	// where x is between 0000-ffff. Zero padding is optional. Case insensitive. 
+	var ipv6RE = "([\\da-fA-F]{1,4}\\:){7}[\\da-fA-F]{1,4}";
+
+	// IPv6/IPv4 Hybrid address RE. 
+	// The format is written as six groups of four hexadecimal digits, 
+	// followed by the 4 dotted decimal IPv4 format. x:x:x:x:x:x:d.d.d.d
+	var hybridRE = "([\\da-fA-F]{1,4}\\:){6}" + 
+		"((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])";
+
+	// Build IP Address RE
+	var a = [];
+	if (flags.allowDottedDecimal) { a.push(dottedDecimalRE); }
+	if (flags.allowDottedHex) { a.push(dottedHexRE); }
+	if (flags.allowDottedOctal) { a.push(dottedOctalRE); }
+	if (flags.allowDecimal) { a.push(decimalRE); }
+	if (flags.allowHex) { a.push(hexRE); }
+	if (flags.allowIPv6) { a.push(ipv6RE); }
+	if (flags.allowHybrid) { a.push(hybridRE); }
+
+	var ipAddressRE = "";
+	if (a.length > 0) {
+		ipAddressRE = "(" + a.join("|") + ")";
+	}
+
+	return ipAddressRE;
+}
+
+/**
+  Builds a RE that matches a host.
+	A host is a domain name or an IP address, possibly followed by a port number.
+
+  @param flags  An object.
+    flags.allowIP  Allow an IP address for hostname.  Default is true.
+    flags.allowLocal  Allow the host to be "localhost".  Default is false.
+    flags.allowPort  Allow a port number to be present.  Default is true.
+    flags in regexp.ipAddress can be applied.
+    flags in regexp.tld can be applied.
+
+  @return  A string for a regular expression for a host.
+*/
+dojo.regexp.host = function(flags) {
+	// assign default values to missing paramters
+	flags = (typeof flags == "object") ? flags : {};
+	if (typeof flags.allowIP != "boolean") { flags.allowIP = true; }
+	if (typeof flags.allowLocal != "boolean") { flags.allowLocal = false; }
+	if (typeof flags.allowPort != "boolean") { flags.allowPort = true; }
+
+	// Domain names can not end with a dash.
+	var domainNameRE = "([0-9a-zA-Z]([-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?\\.)+" + dojo.regexp.tld(flags);
+
+	// port number RE
+	portRE = ( flags.allowPort ) ? "(\\:" + dojo.regexp.integer({signed: false}) + ")?" : "";
+
+	// build host RE
+	var hostNameRE = domainNameRE;
+	if (flags.allowIP) { hostNameRE += "|" +  dojo.regexp.ipAddress(flags); }
+	if (flags.allowLocal) { hostNameRE += "|localhost"; }
+
+	return "(" + hostNameRE + ")" + portRE;
+}
+
+/**
+  Builds a regular expression that matches a URL.
+
+  @param flags  An object.
+    flags.scheme  Can be true, false, or [true, false]. 
+      This means: required, not allowed, or match either one.
+    flags in regexp.host can be applied.
+    flags in regexp.ipAddress can be applied.
+    flags in regexp.tld can be applied.
+
+  @return  A string for a regular expression for a URL.
+*/
+dojo.regexp.url = function(flags) {
+	// assign default values to missing paramters
+	flags = (typeof flags == "object") ? flags : {};
+	if (typeof flags.scheme == "undefined") { flags.scheme = [true, false]; }
+
+	// Scheme RE
+	var protocalRE = dojo.regexp.buildGroupRE(flags.scheme,
+		function(q) { if (q) { return "(https?|ftps?)\\://"; }  return ""; }
+	);
+
+	// Path and query and anchor RE
+	var pathRE = "(/([^?#\\s/]+/)*)?([^?#\\s/]+(\\?[^?#\\s/]*)?(#[A-Za-z][\\w.:-]*)?)?";
+
+	return (protocalRE + dojo.regexp.host(flags) + pathRE);
+}
+
+/**
+  Builds a regular expression that matches an email address.
+
+  @param flags  An object.
+    flags.allowCruft  Allow address like <mailto:foo@yahoo.com>.  Default is false.
+    flags in regexp.host can be applied.
+    flags in regexp.ipAddress can be applied.
+    flags in regexp.tld can be applied.
+
+  @return  A string for a regular expression for an email address.
+*/
+dojo.regexp.emailAddress = function(flags) {
+	// assign default values to missing paramters
+	flags = (typeof flags == "object") ? flags : {};
+	if (typeof flags.allowCruft != "boolean") { flags.allowCruft = false; }
+	flags.allowPort = false; // invalid in email addresses
+
+	// user name RE - apostrophes are valid if there's not 2 in a row
+	var usernameRE = "([\\da-z]+[-._+&'])*[\\da-z]+";
+
+	// build emailAddress RE
+	var emailAddressRE = usernameRE + "@" + dojo.regexp.host(flags);
+
+	// Allow email addresses with cruft
+	if ( flags.allowCruft ) {
+		emailAddressRE = "<?(mailto\\:)?" + emailAddressRE + ">?";
+	}
+
+	return emailAddressRE;
+}
+
+/**
+  Builds a regular expression that matches a list of email addresses.
+
+  @param flags  An object.
+    flags.listSeparator  The character used to separate email addresses.  Default is ";", ",", "\n" or " ".
+    flags in regexp.emailAddress can be applied.
+    flags in regexp.host can be applied.
+    flags in regexp.ipAddress can be applied.
+    flags in regexp.tld can be applied.
+
+  @return  A string for a regular expression for an email address list.
+*/
+dojo.regexp.emailAddressList = function(flags) {
+	// assign default values to missing paramters
+	flags = (typeof flags == "object") ? flags : {};
+	if (typeof flags.listSeparator != "string") { flags.listSeparator = "\\s;,"; }
+
+	// build a RE for an Email Address List
+	var emailAddressRE = dojo.regexp.emailAddress(flags);
+	var emailAddressListRE = "(" + emailAddressRE + "\\s*[" + flags.listSeparator + "]\\s*)*" + 
+		emailAddressRE + "\\s*[" + flags.listSeparator + "]?\\s*";
+
+	return emailAddressListRE;
+}
+
+/**
+  Builds a regular expression that matches an integer.
+
+  @param flags  An object.
+    flags.signed  The leading plus-or-minus sign.  Can be true, false, or [true, false].
+      Default is [true, false], (i.e. will match if it is signed or unsigned).
+    flags.separator  The character used as the thousands separator.  Default is no separator.
+      For more than one symbol use an array, e.g. [",", ""], makes ',' optional.
+
+  @return  A string for a regular expression for an integer.
+*/
+dojo.regexp.integer = function(flags) {
+	// assign default values to missing paramters
+	flags = (typeof flags == "object") ? flags : {};
+	if (typeof flags.signed == "undefined") { flags.signed = [true, false]; }
+	if (typeof flags.separator == "undefined") { flags.separator = ""; }
+
+	// build sign RE
+	var signRE = dojo.regexp.buildGroupRE(flags.signed,
+		function(q) { if (q) { return "[-+]"; }  return ""; }
+	);
+
+	// number RE
+	var numberRE = dojo.regexp.buildGroupRE(flags.separator,
+		function(sep) { 
+			if ( sep == "" ) { 
+				return "(0|[1-9]\\d*)"; 
+			}
+			return "(0|[1-9]\\d{0,2}([" + sep + "]\\d{3})*)"; 
+		}
+	);
+	var numberRE;
+
+	// integer RE
+	return (signRE + numberRE);
+}
+
+/**
+  Builds a regular expression to match a real number in exponential notation.
+
+  @param flags  An object.
+    flags.places  The integer number of decimal places.
+      If not given, the decimal part is optional and the number of places is unlimited.
+    flags.decimal  A string for the character used as the decimal point.  Default is ".".
+    flags.exponent  Express in exponential notation.  Can be true, false, or [true, false].
+      Default is [true, false], (i.e. will match if the exponential part is present are not).
+    flags.eSigned  The leading plus-or-minus sign on the exponent.  Can be true, false, 
+      or [true, false].  Default is [true, false], (i.e. will match if it is signed or unsigned).
+    flags in regexp.integer can be applied.
+
+  @return  A string for a regular expression for a real number.
+*/
+dojo.regexp.realNumber = function(flags) {
+	// assign default values to missing paramters
+	flags = (typeof flags == "object") ? flags : {};
+	if (typeof flags.places != "number") { flags.places = Infinity; }
+	if (typeof flags.decimal != "string") { flags.decimal = "."; }
+	if (typeof flags.exponent == "undefined") { flags.exponent = [true, false]; }
+	if (typeof flags.eSigned == "undefined") { flags.eSigned = [true, false]; }
+
+	// integer RE
+	var integerRE = dojo.regexp.integer(flags);
+
+	// decimal RE
+	var decimalRE = "";
+	if ( flags.places == Infinity) { 
+		decimalRE = "(\\" + flags.decimal + "\\d+)?"; 
+	}
+	else if ( flags.places > 0) { 
+		decimalRE = "\\" + flags.decimal + "\\d{" + flags.places + "}"; 
+	}
+
+	// exponent RE
+	var exponentRE = dojo.regexp.buildGroupRE(flags.exponent,
+		function(q) { 
+			if (q) { return "([eE]" + dojo.regexp.integer({signed: flags.eSigned}) + ")"; }
+			return ""; 
+		}
+	);
+
+	// real number RE
+	return (integerRE + decimalRE + exponentRE);
+}
+
+/**
+  Builds a regular expression to match a monetary value.
+
+  @param flags  An object.
+    flags.signed  The leading plus-or-minus sign.  Can be true, false, or [true, false].
+      Default is [true, false], (i.e. will match if it is signed or unsigned).
+    flags.symbol  A currency symbol such as Yen "�", Pound "�", or the Euro sign "�".  
+      Default is "$".  For more than one symbol use an array, e.g. ["$", ""], makes $ optional.
+    flags.placement  The symbol can come "before" the number or "after".  Default is "before".
+    flags.separator  The character used as the thousands separator. The default is ",".
+    flags.cents  The two decimal places for cents.  Can be true, false, or [true, false].
+      Default is [true, false], (i.e. will match if cents are present are not).
+    flags.decimal  A string for the character used as the decimal point.  Default is ".".
+
+  @return  A string for a regular expression for a monetary value.
+*/
+dojo.regexp.currency = function(flags) {
+	// assign default values to missing paramters
+	flags = (typeof flags == "object") ? flags : {};
+	if (typeof flags.signed == "undefined") { flags.signed = [true, false]; }
+	if (typeof flags.symbol == "undefined") { flags.symbol = "$"; }
+	if (typeof flags.placement != "string") { flags.placement = "before"; }
+	if (typeof flags.separator != "string") { flags.separator = ","; }
+	if (typeof flags.cents == "undefined") { flags.cents = [true, false]; }
+	if (typeof flags.decimal != "string") { flags.decimal = "."; }
+
+	// build sign RE
+	var signRE = dojo.regexp.buildGroupRE(flags.signed,
+		function(q) { if (q) { return "[-+]"; }  return ""; }
+	);
+
+	// build symbol RE
+	var symbolRE = dojo.regexp.buildGroupRE(flags.symbol,
+		function(symbol) { 
+			// escape all special characters
+			return "\\s?" + symbol.replace( /([.$?*!=:|\\\/^])/g, "\\$1") + "\\s?";
+		}
+	);
+
+	// number RE
+	var numberRE = dojo.regexp.integer( {signed: false, separator: flags.separator} );
+
+	// build cents RE
+	var centsRE = dojo.regexp.buildGroupRE(flags.cents,
+		function(q) { if (q) { return "(\\" + flags.decimal + "\\d\\d)"; }  return ""; }
+	);
+
+	// build currency RE
+	var currencyRE;
+	if (flags.placement == "before") {
+		currencyRE = signRE + symbolRE + numberRE + centsRE;
+	}
+	else {
+		currencyRE = signRE + numberRE + centsRE + symbolRE;
+	}
+
+	return currencyRE;
+}
+
+/**
+  A regular expression to match US state and territory abbreviations.
+
+  @param flags  An object.
+    flags.allowTerritories  Allow Guam, Puerto Rico, etc.  Default is true.
+    flags.allowMilitary  Allow military 'states', e.g. Armed Forces Europe (AE).  Default is true.
+
+  @return  A string for a regular expression for a US state.
+*/
+dojo.regexp.us.state = function(flags) {
+	// assign default values to missing paramters
+	flags = (typeof flags == "object") ? flags : {};
+	if (typeof flags.allowTerritories != "boolean") { flags.allowTerritories = true; }
+	if (typeof flags.allowMilitary != "boolean") { flags.allowMilitary = true; }
+
+	// state RE
+	var statesRE = 
+		"AL|AK|AZ|AR|CA|CO|CT|DE|DC|FL|GA|HI|ID|IL|IN|IA|KS|KY|LA|ME|MD|MA|MI|MN|MS|MO|MT|" + 
+		"NE|NV|NH|NJ|NM|NY|NC|ND|OH|OK|OR|PA|RI|SC|SD|TN|TX|UT|VT|VA|WA|WV|WI|WY";
+
+	// territories RE
+	var territoriesRE = "AS|FM|GU|MH|MP|PW|PR|VI";
+
+	// military states RE
+	var militaryRE = "AA|AE|AP";
+
+	// Build states and territories RE
+	if (flags.allowTerritories) { statesRE += "|" + territoriesRE; }
+	if (flags.allowMilitary) { statesRE += "|" + militaryRE; }
+
+	return "(" + statesRE + ")";
+}
+
+/**
+  Builds a regular expression to match any International format for time.
+  The RE can match one format or one of multiple formats.
+
+  Format
+  h        12 hour, no zero padding.
+  hh       12 hour, has leading zero.
+  H        24 hour, no zero padding.
+  HH       24 hour, has leading zero.
+  m        minutes, no zero padding.
+  mm       minutes, has leading zero.
+  s        seconds, no zero padding.
+  ss       seconds, has leading zero.
+  t        am or pm, case insensitive.
+  All other characters must appear literally in the expression.
+
+  Example
+    "h:m:s t"  ->   2:5:33 PM
+    "HH:mm:ss" ->  14:05:33
+
+  @param flags  An object.
+    flags.format  A string or an array of strings.  Default is "h:mm:ss t".
+    flags.amSymbol  The symbol used for AM.  Default is "AM".
+    flags.pmSymbol  The symbol used for PM.  Default is "PM".
+
+  @return  A string for a regular expression for a time value.
+*/
+dojo.regexp.time = function(flags) {
+	// assign default values to missing paramters
+	flags = (typeof flags == "object") ? flags : {};
+	if (typeof flags.format == "undefined") { flags.format = "h:mm:ss t"; }
+	if (typeof flags.amSymbol != "string") { flags.amSymbol = "AM"; }
+	if (typeof flags.pmSymbol != "string") { flags.pmSymbol = "PM"; }
+
+	// Converts a time format to a RE
+	var timeRE = function(format) {
+		// escape all special characters
+		format = format.replace( /([.$?*!=:|{}\(\)\[\]\\\/^])/g, "\\$1");
+		var amRE = flags.amSymbol.replace( /([.$?*!=:|{}\(\)\[\]\\\/^])/g, "\\$1");
+		var pmRE = flags.pmSymbol.replace( /([.$?*!=:|{}\(\)\[\]\\\/^])/g, "\\$1");
+
+		// replace tokens with Regular Expressions
+		format = format.replace("hh", "(0[1-9]|1[0-2])");
+		format = format.replace("h", "([1-9]|1[0-2])");
+		format = format.replace("HH", "([01][0-9]|2[0-3])");
+		format = format.replace("H", "([0-9]|1[0-9]|2[0-3])");
+		format = format.replace("mm", "([0-5][0-9])");
+		format = format.replace("m", "([1-5][0-9]|[0-9])");
+		format = format.replace("ss", "([0-5][0-9])");
+		format = format.replace("s", "([1-5][0-9]|[0-9])");
+		format = format.replace("t", "\\s?(" + amRE + "|" + pmRE + ")\\s?" );
+
+		return format;
+	};
+
+	// build RE for multiple time formats
+	return dojo.regexp.buildGroupRE(flags.format, timeRE);
+}
+
+/**
+  Builds a regular expression to match any sort of number based format.
+  Use it for phone numbers, social security numbers, zip-codes, etc.
+  The RE can match one format or one of multiple formats.
+
+  Format
+    #        Stands for a digit, 0-9.
+    ?        Stands for an optional digit, 0-9 or nothing.
+    All other characters must appear literally in the expression.
+
+  Example   
+    "(###) ###-####"       ->   (510) 542-9742
+    "(###) ###-#### x#???" ->   (510) 542-9742 x153
+    "###-##-####"          ->   506-82-1089       i.e. social security number
+    "#####-####"           ->   98225-1649        i.e. zip code
+
+  @param flags  An object.
+    flags.format  A string or an Array of strings for multiple formats.
+  @return  A string for a regular expression for the number format(s).
+*/
+dojo.regexp.numberFormat = function(flags) {
+	// assign default values to missing paramters
+	flags = (typeof flags == "object") ? flags : {};
+	if (typeof flags.format == "undefined") { flags.format = "###-###-####"; }
+
+	// Converts a number format to RE.
+	var digitRE = function(format) {
+		// escape all special characters, except '?'
+		format = format.replace( /([.$*!=:|{}\(\)\[\]\\\/^])/g, "\\$1");
+
+		// Now replace '?' with Regular Expression
+		format = format.replace(/\?/g, "\\d?");
+
+		// replace # with Regular Expression
+		format = format.replace(/#/g, "\\d");
+
+		return format;
+	};
+
+	// build RE for multiple number formats
+	return dojo.regexp.buildGroupRE(flags.format, digitRE);
+}
+
+
+/**
+  This is basically a utility function used by some of the RE generators.
+  Builds a regular expression that groups subexpressions.
+  The subexpressions are constructed by the function, re, in the second parameter.
+  re builds one subexpression for each elem in the array a, in the first parameter.
+
+  @param a  A single value or an array of values.
+  @param re  A function.  Takes one parameter and converts it to a regular expression. 
+  @return  A string for a regular expression that groups all the subexpressions.
+*/
+dojo.regexp.buildGroupRE = function(a, re) {
+
+	// case 1: a is a single value.
+	if ( !( a instanceof Array ) ) { 
+		return re(a);
+	}
+
+	// case 2: a is an array
+	var b = [];
+	for (var i = 0; i < a.length; i++) {
+		// convert each elem to a RE
+		b.push(re(a[i]));
+	}
+
+	 // join the REs as alternatives in a RE group.
+	return "(" + b.join("|") + ")";
+}

Added: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/Deferred.js
URL: http://svn.apache.org/viewcvs/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/Deferred.js?rev=406128&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/Deferred.js (added)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/Deferred.js Sat May 13 09:36:25 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.rpc.Deferred");
+dojo.require("dojo.Deferred");
+
+dojo.rpc.Deferred = dojo.Deferred;
+dojo.rpc.Deferred.prototype = dojo.Deferred.prototype;

Added: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/JotService.js
URL: http://svn.apache.org/viewcvs/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/JotService.js?rev=406128&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/JotService.js (added)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/JotService.js Sat May 13 09:36:25 2006
@@ -0,0 +1,41 @@
+/*
+	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.rpc.JotService");
+dojo.require("dojo.rpc.RpcService");
+dojo.require("dojo.rpc.JsonService");
+dojo.require("dojo.json");
+
+dojo.rpc.JotService = function(){
+	this.serviceUrl = "/_/jsonrpc";
+}
+
+dojo.inherits(dojo.rpc.JotService, dojo.rpc.JsonService);
+
+dojo.lang.extend(dojo.rpc.JotService, {
+	bind: function(method, parameters, deferredRequestHandler, url){
+		dojo.io.bind({
+			url: url||this.serviceUrl,
+			content: {
+				json: this.createRequest(method, parameters)
+			},
+			method: "POST",
+			mimetype: "text/json",
+			load: this.resultCallback(deferredRequestHandler),
+			error: this.errorCallback(deferredRequestHandler),
+			preventCache: true
+		});
+	},
+
+	createRequest: function(method, params){
+		var req = { "params": params, "method": method, "id": this.lastSubmissionId++ };
+		return dojo.json.serialize(req);
+	}
+});

Added: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/JsonService.js
URL: http://svn.apache.org/viewcvs/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/JsonService.js?rev=406128&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/JsonService.js (added)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/JsonService.js Sat May 13 09:36:25 2006
@@ -0,0 +1,103 @@
+/*
+	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.rpc.JsonService");
+dojo.require("dojo.rpc.RpcService");
+dojo.require("dojo.io.*");
+dojo.require("dojo.json");
+dojo.require("dojo.lang");
+
+dojo.rpc.JsonService = function(args){
+	// passing just the URL isn't terribly useful. It's expected that at
+	// various times folks will want to specify:
+	//	- just the serviceUrl (for use w/ remoteCall())
+	//	- the text of the SMD to evaluate
+	// 	- a raw SMD object
+	//	- the SMD URL
+	if(args){
+		if(dojo.lang.isString(args)){
+			// we assume it's an SMD file to be processed, since this was the
+			// earlier function signature
+
+			// FIXME: also accept dojo.uri.Uri objects?
+			this.connect(args);
+		}else{
+			// otherwise we assume it's an arguments object with the following
+			// (optional) properties:
+			//	- serviceUrl
+			//	- strictArgChecks
+			//	- smdUrl
+			//	- smdStr
+			//	- smdObj
+			if(args["smdUrl"]){
+				this.connect(args.smdUrl);
+			}
+			if(args["smdStr"]){
+				this.processSmd(dj_eval("("+args.smdStr+")"));
+			}
+			if(args["smdObj"]){
+				this.processSmd(args.smdObj);
+			}
+			if(args["serviceUrl"]){
+				this.serviceUrl = args.serviceUrl;
+			}
+			if(typeof args["strictArgChecks"] != "undefined"){
+				this.strictArgChecks = args.strictArgChecks;
+			}
+		}
+	}
+}
+
+dojo.inherits(dojo.rpc.JsonService, dojo.rpc.RpcService);
+
+dojo.lang.extend(dojo.rpc.JsonService, {
+
+	bustCache: false,
+	
+	contentType: "application/json-rpc",
+
+	lastSubmissionId: 0,
+
+	callRemote: function(method, params){
+		var deferred = new dojo.rpc.Deferred();
+		this.bind(method, params, deferred);
+		return deferred;
+	},
+
+	bind: function(method, parameters, deferredRequestHandler, url){
+		dojo.io.bind({
+			url: url||this.serviceUrl,
+			postContent: this.createRequest(method, parameters),
+			method: "POST",
+			contentType: this.contentType,
+			mimetype: "text/json",
+			load: this.resultCallback(deferredRequestHandler),
+			preventCache:this.bustCache 
+		});
+	},
+
+	createRequest: function(method, params){
+		var req = { "params": params, "method": method, "id": ++this.lastSubmissionId };
+		var data = dojo.json.serialize(req);
+		dojo.debug("JsonService: JSON-RPC Request: " + data);
+		return data;
+	},
+
+	parseResults: function(obj){
+		if(!obj){ return; }
+		if(obj["Result"]||obj["result"]){
+			return obj["result"]||obj["Result"];
+		}else if(obj["ResultSet"]){
+			return obj["ResultSet"];
+		}else{
+			return obj;
+		}
+	}
+});

Added: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/RpcService.js
URL: http://svn.apache.org/viewcvs/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/RpcService.js?rev=406128&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/RpcService.js (added)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/RpcService.js Sat May 13 09:36:25 2006
@@ -0,0 +1,116 @@
+/*
+	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.rpc.RpcService");
+dojo.require("dojo.io.*");
+dojo.require("dojo.json");
+dojo.require("dojo.lang.func");
+dojo.require("dojo.rpc.Deferred");
+
+dojo.rpc.RpcService = function(url){
+	// summary
+	// constructor for rpc base class
+	if(url){
+		this.connect(url);
+	}
+}
+
+dojo.lang.extend(dojo.rpc.RpcService, {
+
+	strictArgChecks: true,
+	serviceUrl: "",
+
+	parseResults: function(obj){
+		// summary
+		// parse the results coming back from an rpc request.  
+   		// this base implementation, just returns the full object
+		// subclasses should parse and only return the actual results
+		return obj;
+	},
+
+	errorCallback: function(/* dojo.rpc.Deferred */ deferredRequestHandler){
+		// summary
+		// create callback that calls the Deferres errback method
+		return function(type, obj, e){
+			deferredRequestHandler.errback(e);
+		}
+	},
+
+	resultCallback: function(/* dojo.rpc.Deferred */ deferredRequestHandler){
+		// summary
+		// create callback that calls the Deferred's callback method
+		var tf = dojo.lang.hitch(this, 
+			function(type, obj, e){
+				var results = this.parseResults(obj||e);
+				deferredRequestHandler.callback(results); 
+			}
+		);
+		return tf;
+	},
+
+
+	generateMethod: function(/*string*/ method, /*array*/ parameters, /*string*/ url){
+		// summary
+		// generate the local bind methods for the remote object
+		return dojo.lang.hitch(this, function(){
+			var deferredRequestHandler = new dojo.rpc.Deferred();
+
+			// if params weren't specified, then we can assume it's varargs
+			if( (this.strictArgChecks) &&
+				(parameters != null) &&
+				(arguments.length != parameters.length)
+			){
+				// put error stuff here, no enough params
+				dojo.raise("Invalid number of parameters for remote method.");
+			} else {
+				this.bind(method, arguments, deferredRequestHandler, url);
+			}
+
+			return deferredRequestHandler;
+		});
+	},
+
+	processSmd: function(/*json*/ object){
+		// summary
+		// callback method for reciept of a smd object.  Parse the smd and
+		// generate functions based on the description
+		dojo.debug("RpcService: Processing returned SMD.");
+		if(object.methods){
+			dojo.lang.forEach(object.methods, function(m){
+				if(m && m["name"]){
+					dojo.debug("RpcService: Creating Method: this.", m.name, "()");
+					this[m.name] = this.generateMethod(	m.name,
+														m.parameters, 
+														m["url"]||m["serviceUrl"]||m["serviceURL"]);
+					if(dojo.lang.isFunction(this[m.name])){
+						dojo.debug("RpcService: Successfully created", m.name, "()");
+					}else{
+						dojo.debug("RpcService: Failed to create", m.name, "()");
+					}
+				}
+			}, this);
+		}
+
+		this.serviceUrl = object.serviceUrl||object.serviceURL;
+		dojo.debug("RpcService: Dojo RpcService is ready for use.");
+	},
+
+	connect: function(/*String*/ smdUrl){
+		// summary
+		// connect to a remote url and retrieve a smd object
+		dojo.debug("RpcService: Attempting to load SMD document from:", smdUrl);
+		dojo.io.bind({
+			url: smdUrl,
+			mimetype: "text/json",
+			load: dojo.lang.hitch(this, function(type, object, e){ return this.processSmd(object); }),
+			sync: true
+		});		
+	}
+});

Added: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/YahooService.js
URL: http://svn.apache.org/viewcvs/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/YahooService.js?rev=406128&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/YahooService.js (added)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/YahooService.js Sat May 13 09:36:25 2006
@@ -0,0 +1,55 @@
+/*
+	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.rpc.YahooService");
+dojo.require("dojo.rpc.RpcService");
+dojo.require("dojo.rpc.JsonService");
+dojo.require("dojo.json");
+dojo.require("dojo.uri.*");
+dojo.require("dojo.io.ScriptSrcIO");
+
+dojo.rpc.YahooService = function(appId){
+	this.appId = appId;
+	if(!appId){
+		this.appId = "dojotoolkit";
+		dojo.debug(	"please initializae the YahooService class with your own",
+					"application ID. Using the default may cause problems during",
+					"deployment of your application");
+	}
+	this.connect(dojo.uri.dojoUri("src/rpc/yahoo.smd"));
+	this.scrictArgChecks = false;
+}
+
+dojo.inherits(dojo.rpc.YahooService, dojo.rpc.JsonService);
+
+dojo.lang.extend(dojo.rpc.YahooService, {
+	strictArgChecks: false,
+
+	bind: function(method, parameters, deferredRequestHandler, url){
+		var params = parameters;
+		if(	(dojo.lang.isArrayLike(parameters))&&
+			(parameters.length == 1)){
+			params = parameters[0];
+		}
+		params.output = "json";
+		params.appid= this.appId;
+		dojo.io.bind({
+			url: url||this.serviceUrl,
+			transport: "ScriptSrcTransport",
+			// FIXME: need to get content interpolation fixed
+			content: params,
+			jsonParamName: "callback",
+			mimetype: "text/json",
+			load: this.resultCallback(deferredRequestHandler),
+			error: this.errorCallback(deferredRequestHandler),
+			preventCache: true
+		});
+	}
+});

Added: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/__package__.js
URL: http://svn.apache.org/viewcvs/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/__package__.js?rev=406128&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/__package__.js (added)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/__package__.js Sat May 13 09:36:25 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.rpc.JsonService", false, false]
+});
+dojo.provide("dojo.rpc.*");

Added: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/yahoo.smd
URL: http://svn.apache.org/viewcvs/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/yahoo.smd?rev=406128&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/yahoo.smd (added)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/rpc/yahoo.smd Sat May 13 09:36:25 2006
@@ -0,0 +1,263 @@
+{
+	"SMDVersion":".1",
+	"objectName":"yahoo",
+	"serviceType":"JSON-P",
+	"methods":[
+		//
+		// MAPS 
+		//
+		{
+			// http://developer.yahoo.com/maps/rest/V1/mapImage.html
+			"name":"mapImage",
+			"serviceURL": "http://api.local.yahoo.com/MapsService/V1/mapImage",
+			"parameters":[
+				{ "name":"street", "type":"STRING" },
+				{ "name":"city", "type":"STRING" },
+				{ "name":"zip", "type":"INTEGER" },
+				{ "name":"location", "type":"STRING" },
+				{ "name":"longitude", "type":"FLOAT" },
+				{ "name":"latitude", "type":"FLOAT" },
+				{ "name":"image_type", "type":"STRING" },
+				{ "name":"image_width", "type":"INTEGER" },
+				{ "name":"image_height", "type":"INTEGER" },
+				{ "name":"zoom", "type":"INTEGER" },
+				{ "name":"radius", "type":"INTEGER" }
+			]
+		},
+		{
+			// http://developer.yahoo.com/traffic/rest/V1/index.html
+			"name":"trafficData",
+			"serviceURL": "http://api.local.yahoo.com/MapsService/V1/trafficData",
+			"parameters":[
+				{ "name":"street", "type":"STRING" },
+				{ "name":"city", "type":"STRING" },
+				{ "name":"zip", "type":"INTEGER" },
+				{ "name":"location", "type":"STRING" },
+				{ "name":"longitude", "type":"FLOAT" },
+				{ "name":"latitude", "type":"FLOAT" },
+				{ "name":"severity", "type":"INTEGER" },
+				{ "name":"include_map", "type":"INTEGER" },
+				{ "name":"image_type", "type":"STRING" },
+				{ "name":"image_width", "type":"INTEGER" },
+				{ "name":"image_height", "type":"INTEGER" },
+				{ "name":"zoom", "type":"INTEGER" },
+				{ "name":"radius", "type":"INTEGER" }
+			]
+		},
+		/*
+			// Yahoo's geocoding service is f'd for JSON and Y! advises that it
+			// may not be returning
+		{
+			// http://developer.yahoo.com/maps/rest/V1/geocode.html
+			"name":"geocode",
+			"serviceURL": "http://api.local.yahoo.com/MapsService/V1/geocode",
+			"parameters":[
+				{ "name":"street", "type":"STRING" },
+				{ "name":"city", "type":"STRING" },
+				{ "name":"zip", "type":"INTEGER" },
+				{ "name":"location", "type":"STRING" }
+			]
+		},
+		*/
+		//
+		// LOCAL SEARCH
+		//
+		{
+			// http://developer.yahoo.com/search/local/V3/localSearch.html
+			"name":"localSearch",
+			"serviceURL": "http://api.local.yahoo.com/LocalSearchService/V3/localSearch",
+			"parameters":[
+				{ "name":"street", "type":"STRING" },
+				{ "name":"city", "type":"STRING" },
+				{ "name":"zip", "type":"INTEGER" },
+				{ "name":"location", "type":"STRING" },
+				{ "name":"listing_id", "type":"STRING" },
+				{ "name":"sort", "type":"STRING" }, // "relevence", "title", "distance", or "rating"
+				{ "name":"start", "type":"INTEGER" },
+				{ "name":"radius", "type":"FLOAT" },
+				{ "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
+				{ "name":"longitude", "type":"FLOAT" },
+				{ "name":"latitude", "type":"FLOAT" },
+				{ "name":"category", "type":"INTEGER" },
+				{ "name":"omit_category", "type":"INTEGER" },
+				{ "name":"minimum_rating", "type":"INTEGER" }
+			]
+		},
+		//
+		// WEB SEARCH
+		//
+
+		// NOTE: contextual search and term extraction are not stubbed out
+		// becaues I'm not sure if we can POST via script src inclusion method
+		{
+			// http://developer.yahoo.com/search/web/V1/webSearch.html 
+			"name":"webSearch",
+			"serviceURL": "http://api.search.yahoo.com/WebSearchService/V1/webSearch",
+			"parameters":[
+				{ "name":"query", "type":"STRING" },
+				{ "name":"type", "type":"STRING" }, // defaults to "all"
+				{ "name":"region", "type":"STRING" }, // defaults to "us"
+				{ "name":"results", "type":"INTEGER" }, // defaults to 10
+				{ "name":"start", "type":"INTEGER" }, // defaults to 1
+				{ "name":"format", "type":"STRING" }, // defaults to "any", can be "html", "msword", "pdf", "ppt", "rst", "txt", or "xls"
+				{ "name":"adult_ok", "type":"INTEGER" }, // defaults to null
+				{ "name":"similar_ok", "type":"INTEGER" }, // defaults to null
+				{ "name":"language", "type":"STRING" }, // defaults to null
+				{ "name":"country", "type":"STRING" }, // defaults to null
+				{ "name":"site", "type":"STRING" }, // defaults to null
+				{ "name":"subscription", "type":"STRING" }, // defaults to null
+				{ "name":"license", "type":"STRING" } // defaults to "any"
+			]
+		},
+		{
+			// http://developer.yahoo.com/search/web/V1/spellingSuggestion.html
+			"name":"spellingSuggestion",
+			"serviceURL": "http://api.search.yahoo.com/WebSearchService/V1/spellingSuggestion",
+			"parameters":[ { "name":"query", "type":"STRING" } ]
+		},
+		{
+			// http://developer.yahoo.com/search/web/V1/relatedSuggestion.html
+			"name":"spellingSuggestion",
+			"serviceURL": "http://api.search.yahoo.com/WebSearchService/V1/relatedSuggestion",
+			"parameters":[
+				{ "name":"query", "type":"STRING" },
+				{ "name":"results", "type":"INTEGER" } // 1-50, defaults to 10
+			]
+		},
+		//
+		// IMAGE SEARCH
+		//
+		{
+			// http://developer.yahoo.com/search/image/V1/imageSearch.html
+			"name":"imageSearch",
+			"serviceURL": "http://api.search.yahoo.com/ImageSearchService/V1/imageSearch",
+			"parameters":[
+				{ "name":"query", "type":"STRING" },
+				{ "name":"type", "type":"STRING" }, // defaults to "all", can by "any" or "phrase"
+				{ "name":"results", "type":"INTEGER" }, // defaults to 10
+				{ "name":"start", "type":"INTEGER" }, // defaults to 1
+				{ "name":"format", "type":"STRING" }, // defaults to "any", can be "bmp", "gif", "jpeg", or "png"
+				{ "name":"adult_ok", "type":"INTEGER" }, // defaults to null
+				{ "name":"coloration", "type":"STRING" }, // "any", "color", or "bw"
+				{ "name":"site", "type":"STRING" } // defaults to null
+			]
+		},
+		//
+		// SITE EXPLORER
+		//
+		{
+			// http://developer.yahoo.com/search/siteexplorer/V1/inlinkData.html 
+			"name":"inlinkData",
+			"serviceURL": "http://api.search.yahoo.com/SiteExplorerService/V1/inlinkData",
+			"parameters":[
+				{ "name":"query", "type":"STRING" },
+				{ "name":"type", "type":"STRING" }, // defaults to "all", can by "any" or "phrase"
+				{ "name":"entire_site", "type":"INTEGER" }, // defaults to null
+				{ "name":"omit_inlinks", "type":"STRING" }, // "domain" or "subdomain", defaults to null
+				{ "name":"results", "type":"INTEGER" }, // defaults to 50
+				{ "name":"start", "type":"INTEGER" }, // defaults to 1
+				{ "name":"site", "type":"STRING" } // defaults to null
+			]
+		},
+		{
+			// http://developer.yahoo.com/search/siteexplorer/V1/pageData.html
+			"name":"pageData",
+			"serviceURL": "http://api.search.yahoo.com/SiteExplorerService/V1/pageData",
+			"parameters":[
+				{ "name":"query", "type":"STRING" },
+				{ "name":"type", "type":"STRING" }, // defaults to "all", can by "any" or "phrase"
+				{ "name":"domain_only", "type":"INTEGER" }, // defaults to null
+				{ "name":"results", "type":"INTEGER" }, // defaults to 50
+				{ "name":"start", "type":"INTEGER" }, // defaults to 1
+				{ "name":"site", "type":"STRING" } // defaults to null
+			]
+		},
+		//
+		// MUSIC SEARCH
+		//
+		{
+			// http://developer.yahoo.com/search/audio/V1/artistSearch.html
+			"name":"artistSearch",
+			"serviceURL": "http://api.search.yahoo.com/AudioSearchService/V1/artistSearch",
+			"parameters":[
+				{ "name":"artist", "type":"STRING" },
+				{ "name":"artistid", "type":"STRING" },
+				{ "name":"type", "type":"STRING" }, // "all", "any", or "phrase"
+				{ "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
+				{ "name":"start", "type":"INTEGER" } // defaults to 1
+			]
+		},
+		{
+			// http://developer.yahoo.com/search/audio/V1/albumSearch.html
+			"name":"albumSearch",
+			"serviceURL": "http://api.search.yahoo.com/AudioSearchService/V1/albumSearch",
+			"parameters":[
+				{ "name":"artist", "type":"STRING" },
+				{ "name":"artistid", "type":"STRING" },
+				{ "name":"album", "type":"STRING" },
+				{ "name":"type", "type":"STRING" }, // "all", "any", or "phrase"
+				{ "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
+				{ "name":"start", "type":"INTEGER" } // defaults to 1
+			]
+		},
+		{
+			// http://developer.yahoo.com/search/audio/V1/songSearch.html
+			"name":"songSearch",
+			"serviceURL": "http://api.search.yahoo.com/AudioSearchService/V1/songSearch",
+			"parameters":[
+				{ "name":"artist", "type":"STRING" },
+				{ "name":"artistid", "type":"STRING" },
+				{ "name":"album", "type":"STRING" },
+				{ "name":"albumid", "type":"STRING" },
+				{ "name":"song", "type":"STRING" },
+				{ "name":"songid", "type":"STRING" },
+				{ "name":"type", "type":"STRING" }, // "all", "any", or "phrase"
+				{ "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
+				{ "name":"start", "type":"INTEGER" } // defaults to 1
+			]
+		},
+		{
+			// http://developer.yahoo.com/search/audio/V1/songDownloadLocation.html
+			"name":"songDownloadLocation",
+			"serviceURL": "http://api.search.yahoo.com/AudioSearchService/V1/songDownloadLocation",
+			"parameters":[
+				{ "name":"songid", "type":"STRING" },
+				// "source" can contain:
+				//	audiolunchbox artistdirect buymusic dmusic
+				//	emusic epitonic garageband itunes yahoo
+				//	livedownloads mp34u msn musicmatch mapster passalong
+				//	rhapsody soundclick theweb
+				{ "name":"source", "type":"STRING" },
+				{ "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
+				{ "name":"start", "type":"INTEGER" } // defaults to 1
+			]
+		},
+		//
+		// NEWS SEARCH
+		//
+		{
+			// http://developer.yahoo.com/search/news/V1/newsSearch.html
+			"name":"newsSearch",
+			"serviceURL": "http://api.search.yahoo.com/NewsSearchService/V1/newsSearch",
+			"parameters":[
+				{ "name":"query", "type":"STRING" },
+				{ "name":"type", "type":"STRING" }, // defaults to "all"
+				{ "name":"results", "type":"INTEGER" }, // defaults to 10
+				{ "name":"start", "type":"INTEGER" }, // defaults to 1
+				{ "name":"sort", "type":"STRING" }, // "rank" or "date"
+				{ "name":"language", "type":"STRING" }, // defaults to null
+				{ "name":"site", "type":"STRING" } // defaults to null
+			]
+		}
+		/*
+		{
+			// 
+			"name":"",
+			"serviceURL": "",
+			"parameters":[
+				{ "name":"street", "type":"STRING" },
+			]
+		}
+		*/
+	]
+}

Added: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/selection/Selection.js
URL: http://svn.apache.org/viewcvs/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/selection/Selection.js?rev=406128&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/selection/Selection.js (added)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/selection/Selection.js Sat May 13 09:36:25 2006
@@ -0,0 +1,425 @@
+/*
+	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.selection.Selection");
+dojo.require("dojo.lang.array");
+dojo.require("dojo.lang.func");
+dojo.require("dojo.math");
+
+dojo.selection.Selection = function(items, isCollection) {
+	this.items = [];
+	this.selection = [];
+	this._pivotItems = [];
+	this.clearItems();
+
+	if(items) {
+		if(isCollection) {
+			this.setItemsCollection(items);
+		} else {
+			this.setItems(items);
+		}
+	}
+}
+dojo.lang.extend(dojo.selection.Selection, {
+	items: null, // items to select from, order matters for growable selections
+
+	selection: null, // items selected, aren't stored in order (see sorted())
+	lastSelected: null, // last item selected
+
+	allowImplicit: true, // if true, grow selection will start from 0th item when nothing is selected
+	length: 0, // number of *selected* items
+
+	// if true, the selection is treated as an in-order and can grow by ranges, not just by single item
+	isGrowable: true,
+
+	_pivotItems: null, // stack of pivot items
+	_pivotItem: null, // item we grow selections from, top of stack
+
+	// event handlers
+	onSelect: function(item) {},
+	onDeselect: function(item) {},
+	onSelectChange: function(item, selected) {},
+
+	_find: function(item, inSelection) {
+		if(inSelection) {
+			return dojo.lang.find(item, this.selection);
+		} else {
+			return dojo.lang.find(item, this.items);
+		}
+	},
+
+	isSelectable: function(item) {
+		// user-customizable, will filter items through this
+		return true;
+	},
+
+	setItems: function(/* ... */) {
+		this.clearItems();
+		this.addItems.call(this, arguments);
+	},
+
+	// this is in case you have an active collection array-like object
+	// (i.e. getElementsByTagName collection) that manages its own order
+	// and item list
+	setItemsCollection: function(collection) {
+		this.items = collection;
+	},
+
+	addItems: function(/* ... */) {
+		var args = dojo.lang.unnest(arguments);
+		for(var i = 0; i < args.length; i++) {
+			this.items.push(args[i]);
+		}
+	},
+
+	addItemsAt: function(item, before /* ... */) {
+		if(this.items.length == 0) { // work for empy case
+			return this.addItems(dojo.lang.toArray(arguments, 2));
+		}
+
+		if(!this.isItem(item)) {
+			item = this.items[item];
+		}
+		if(!item) { throw new Error("addItemsAt: item doesn't exist"); }
+		var idx = this._find(item);
+		if(idx > 0 && before) { idx--; }
+		for(var i = 2; i < arguments.length; i++) {
+			if(!this.isItem(arguments[i])) {
+				this.items.splice(idx++, 0, arguments[i]);
+			}
+		}
+	},
+
+	removeItem: function(item) {
+		// remove item
+		var idx = this._find(item);
+		if(idx > -1) {
+			this.items.splice(i, 1);
+		}
+		// remove from selection
+		// FIXME: do we call deselect? I don't think so because this isn't how
+		// you usually want to deselect an item. For example, if you deleted an
+		// item, you don't really want to deselect it -- you want it gone. -DS
+		id = this._find(item, true);
+		if(idx > -1) {
+			this.selection.splice(i, 1);
+		}
+	},
+
+	clearItems: function() {
+		this.items = [];
+		this.deselectAll();
+	},
+
+	isItem: function(item) {
+		return this._find(item) > -1;
+	},
+
+	isSelected: function(item) {
+		return this._find(item, true) > -1;
+	},
+
+	/**
+	 * allows you to filter item in or out of the selection
+	 * depending on the current selection and action to be taken
+	**/
+	selectFilter: function(item, selection, add, grow) {
+		return true;
+	},
+
+	/**
+	 * update -- manages selections, most selecting should be done here
+	 *  item => item which may be added/grown to/only selected/deselected
+	 *  add => behaves like ctrl in windows selection world
+	 *  grow => behaves like shift
+	 *  noToggle => if true, don't toggle selection on item
+	**/
+	update: function(item, add, grow, noToggle) {
+		if(!this.isItem(item)) { return false; }
+
+		if(this.isGrowable && grow) {
+			if(!this.isSelected(item)
+				&& this.selectFilter(item, this.selection, false, true)) {
+				this.grow(item);
+				this.lastSelected = item;
+			}
+		} else if(add) {
+			if(this.selectFilter(item, this.selection, true, false)) {
+				if(noToggle) {
+					if(this.select(item)) {
+						this.lastSelected = item;
+					}
+				} else if(this.toggleSelected(item)) {
+					this.lastSelected = item;
+				}
+			}
+		} else {
+			this.deselectAll();
+			this.select(item);
+		}
+
+		this.length = this.selection.length;
+	},
+
+	/**
+	 * Grow a selection.
+	 *  toItem => which item to grow selection to
+	 *  fromItem => which item to start the growth from (it won't be selected)
+	 *
+	 * Any items in (fromItem, lastSelected] that aren't part of
+	 * (fromItem, toItem] will be deselected
+	**/
+	grow: function(toItem, fromItem) {
+		if(!this.isGrowable) { return; }
+
+		if(arguments.length == 1) {
+			fromItem = this._pivotItem;
+			if(!fromItem && this.allowImplicit) {
+				fromItem = this.items[0];
+			}
+		}
+		if(!toItem || !fromItem) { return false; }
+
+		var fromIdx = this._find(fromItem);
+
+		// get items to deselect (fromItem, lastSelected]
+		var toDeselect = {};
+		var lastIdx = -1;
+		if(this.lastSelected) {
+			lastIdx = this._find(this.lastSelected);
+			var step = fromIdx < lastIdx ? -1 : 1;
+			var range = dojo.math.range(lastIdx, fromIdx, step);
+			for(var i = 0; i < range.length; i++) {
+				toDeselect[range[i]] = true;
+			}
+		}
+
+		// add selection (fromItem, toItem]
+		var toIdx = this._find(toItem);
+		var step = fromIdx < toIdx ? -1 : 1;
+		var shrink = lastIdx >= 0 && step == 1 ? lastIdx < toIdx : lastIdx > toIdx;
+		var range = dojo.math.range(toIdx, fromIdx, step);
+		if(range.length) {
+			for(var i = range.length-1; i >= 0; i--) {
+				var item = this.items[range[i]];
+				if(this.selectFilter(item, this.selection, false, true)) {
+					if(this.select(item, true) || shrink) {
+						this.lastSelected = item;
+					}
+					if(range[i] in toDeselect) {
+						delete toDeselect[range[i]];
+					}
+				}
+			}
+		} else {
+			this.lastSelected = fromItem;
+		}
+
+		// now deselect...
+		for(var i in toDeselect) {
+			if(this.items[i] == this.lastSelected) {
+				dbg("oops!");
+			}
+			this.deselect(this.items[i]);
+		}
+
+		// make sure everything is all kosher after selections+deselections
+		this._updatePivot();
+	},
+
+	/**
+	 * Grow selection upwards one item from lastSelected
+	**/
+	growUp: function() {
+		if(!this.isGrowable) { return; }
+
+		var idx = this._find(this.lastSelected) - 1;
+		while(idx >= 0) {
+			if(this.selectFilter(this.items[idx], this.selection, false, true)) {
+				this.grow(this.items[idx]);
+				break;
+			}
+			idx--;
+		}
+	},
+
+	/**
+	 * Grow selection downwards one item from lastSelected
+	**/
+	growDown: function() {
+		if(!this.isGrowable) { return; }
+
+		var idx = this._find(this.lastSelected);
+		if(idx < 0 && this.allowImplicit) {
+			this.select(this.items[0]);
+			idx = 0;
+		}
+		idx++;
+		while(idx > 0 && idx < this.items.length) {
+			if(this.selectFilter(this.items[idx], this.selection, false, true)) {
+				this.grow(this.items[idx]);
+				break;
+			}
+			idx++;
+		}
+	},
+
+	toggleSelected: function(item, noPivot) {
+		if(this.isItem(item)) {
+			if(this.select(item, noPivot)) { return 1; }
+			if(this.deselect(item)) { return -1; }
+		}
+		return 0;
+	},
+
+	select: function(item, noPivot) {
+		if(this.isItem(item) && !this.isSelected(item)
+			&& this.isSelectable(item)) {
+			this.selection.push(item);
+			this.lastSelected = item;
+			this.onSelect(item);
+			this.onSelectChange(item, true);
+			if(!noPivot) {
+				this._addPivot(item);
+			}
+			return true;
+		}
+		return false;
+	},
+
+	deselect: function(item) {
+		var idx = this._find(item, true);
+		if(idx > -1) {
+			this.selection.splice(idx, 1);
+			this.onDeselect(item);
+			this.onSelectChange(item, false);
+			if(item == this.lastSelected) {
+				this.lastSelected = null;
+			}
+
+			this._removePivot(item);
+
+			return true;
+		}
+		return false;
+	},
+
+	selectAll: function() {
+		for(var i = 0; i < this.items.length; i++) {
+			this.select(this.items[i]);
+		}
+	},
+
+	deselectAll: function() {
+		while(this.selection && this.selection.length) {
+			this.deselect(this.selection[0]);
+		}
+	},
+
+	selectNext: function() {
+		var idx = this._find(this.lastSelected);
+		while(idx > -1 && ++idx < this.items.length) {
+			if(this.isSelectable(this.items[idx])) {
+				this.deselectAll();
+				this.select(this.items[idx]);
+				return true;
+			}
+		}
+		return false;
+	},
+
+	selectPrevious: function() {
+		//debugger;
+		var idx = this._find(this.lastSelected);
+		while(idx-- > 0) {
+			if(this.isSelectable(this.items[idx])) {
+				this.deselectAll();
+				this.select(this.items[idx]);
+				return true;
+			}
+		}
+		return false;
+	},
+
+	// select first selectable item
+	selectFirst: function() {
+		this.deselectAll();
+		var idx = 0;
+		while(this.items[idx] && !this.select(this.items[idx])) {
+			idx++;
+		}
+		return this.items[idx] ? true : false;
+	},
+
+	// select last selectable item
+	selectLast: function() {
+		this.deselectAll();
+		var idx = this.items.length-1;
+		while(this.items[idx] && !this.select(this.items[idx])) {
+			idx--;
+		}
+		return this.items[idx] ? true : false;
+	},
+
+	_addPivot: function(item, andClear) {
+		this._pivotItem = item;
+		if(andClear) {
+			this._pivotItems = [item];
+		} else {
+			this._pivotItems.push(item);
+		}
+	},
+
+	_removePivot: function(item) {
+		var i = dojo.lang.find(item, this._pivotItems);
+		if(i > -1) {
+			this._pivotItems.splice(i, 1);
+			this._pivotItem = this._pivotItems[this._pivotItems.length-1];
+		}
+
+		this._updatePivot();
+	},
+
+	_updatePivot: function() {
+		if(this._pivotItems.length == 0) {
+			if(this.lastSelected) {
+				this._addPivot(this.lastSelected);
+			}
+		}
+	},
+
+	sorted: function() {
+		return dojo.lang.toArray(this.selection).sort(
+			dojo.lang.hitch(this, function(a, b) {
+				var A = this._find(a), B = this._find(b);
+				if(A > B) {
+					return 1;
+				} else if(A < B) {
+					return -1;
+				} else {
+					return 0;
+				}
+			})
+		);
+	},
+
+	// remove any items from the selection that are no longer in this.items
+	updateSelected: function() {
+		for(var i = 0; i < this.selection.length; i++) {
+			if(this._find(this.selection[i]) < 0) {
+				var removed = this.selection.splice(i, 1);
+
+				this._removePivot(removed[0]);
+			}
+		}
+
+		this.length = this.selection.length;
+	}
+});

Added: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/storage.js
URL: http://svn.apache.org/viewcvs/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/storage.js?rev=406128&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/storage.js (added)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/storage.js Sat May 13 09:36:25 2006
@@ -0,0 +1,418 @@
+/*
+	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 Alex Russel, alex@dojotoolkit.org
+		@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.storage = function(){
+}
+
+dojo.lang.extend(dojo.storage, {
+	/** 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,
+
+	/** 
+	  Allows this storage provider to initialize itself. This is called
+	  after the page has finished loading, so you can not do document.writes(). 
+	*/
+	initialize: function(){
+	 dojo.unimplemented("dojo.storage.initialize");
+	},
+	
+	/** 
+	  Returns whether this storage provider is 
+	  available on this platform. 
+	
+	  @returns True or false if this storage 
+	  provider is supported.
+	*/
+	isAvailable: function(){
+		dojo.unimplemented("dojo.storage.isAvailable");
+	},
+	
+	/**
+	  Puts a key and value into this storage system.
+
+	  @param key A string key to use when retrieving 
+	         this value in the future.
+	  @param value A value to store; this can be 
+	         any JavaScript type.
+	  @param 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);	
+	*/
+	put: function(key, value, resultsHandler){ 
+    dojo.unimplemented("dojo.storage.put");
+  },
+
+	/**
+	  Gets the value with the given key. Returns null
+	  if this key is not in the storage system.
+	
+	  @param key A string key to get the value of.
+	  @returns Returns any JavaScript object type; 
+	  null if the key is not
+	  present. 
+	*/
+	get: function(key){
+    dojo.unimplemented("dojo.storage.get");
+  },
+
+	/**
+	  Determines whether the storage has the given 
+	  key. 
+	
+	    @returns Whether this key is 
+	             present or not. 
+	*/
+	hasKey: function(key){
+		if (this.get(key) != null)
+			return true;
+		else
+			return false;
+	},
+
+	/**
+	  Enumerates all of the available keys in 
+	  this storage system.
+	
+	  @returns Array of string keys in this 
+	           storage system.
+	*/
+	getKeys: function(){
+    dojo.unimplemented("dojo.storage.getKeys");
+  },
+
+	/**
+	  Completely clears this storage system of all 
+	  of it's values and keys. 
+	*/
+	clear: function(){
+    dojo.unimplemented("dojo.storage.clear");
+  },
+  
+  /** Removes the given key from the storage system. */
+  remove: function(key){
+  	dojo.unimplemented("dojo.storage.remove");
+  },
+
+	/**
+	  Returns whether this storage provider's 
+	  values are persisted when this platform 
+	  is shutdown. 
+	
+	  @returns True or false whether this 
+	  storage is permanent. 
+	*/
+	isPermanent: function(){
+		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");
+  },
+
+	/**
+	  Determines whether this provider has a 
+	  settings UI.
+	
+	  @returns True or false if this provider has 
+	           the ability to show a
+	           a settings UI to change it's 
+	           values, change the amount of storage
+	           available, etc. 
+	*/
+	hasSettingsUI: function(){
+		return false;
+	},
+
+	/**
+	  If this provider has a settings UI, it is 
+	  shown. 
+	*/
+	showSettingsUI: function(){
+	 dojo.unimplemented("dojo.storage.showSettingsUI");
+	},
+
+	/**
+	  If this provider has a settings UI, hides
+	  it.
+	*/
+	hideSettingsUI: function(){
+	 dojo.unimplemented("dojo.storage.hideSettingsUI");
+	},
+	
+	/** 
+	  The provider name as a string, such as 
+	  "dojo.storage.FlashStorageProvider". 
+	*/
+	getType: function(){
+		dojo.unimplemented("dojo.storage.getType");
+	},
+	
+	/**
+	  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. 
+	*/
+	isValidKey: function(keyName){
+		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 = new Array();
+	
+	// TODO: Provide a way for applications to override the default namespace
+	this.namespace = "dojo.storage";
+	
+	/** Initializes the storage system. */
+	this.initialize = function(){
+		// autodetect the best storage provider we can provide on this platform
+		this.autodetect();
+	}
+	
+	/**
+	  Registers the existence of a new storage provider; used by subclasses
+	  to inform the manager of their existence. 
+	
+	  @param name The full class name of this provider, such as 
+	  "dojo.storage.browser.Flash6StorageProvider".
+	  @param instance An instance of this provider, which we will use to
+	  call isAvailable() on. 
+	*/
+	this.register = function(name, instance) {
+		this.providers[this.providers.length] = instance;
+		this.providers[name] = instance;
+	}
+	
+	/**
+	  Instructs the storageManager to use 
+	  the given storage class for all storage requests.
+	    
+	  Example:
+	    
+	  dojo.storage.setProvider(
+	         dojo.storage.browser.IEStorageProvider)
+	*/
+	this.setProvider = function(storageClass){
+	
+	}
+	
+	/** 
+	  Autodetects the best possible persistent
+	  storage provider available on this platform. 
+	*/
+	this.autodetect = function(){
+		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;
+	}
+	
+	/** Returns whether any storage options are available. */
+	this.isAvailable = function(){
+		return this.available;
+	}
+	
+	/** 
+	 	Returns whether the storage system is initialized and
+	 	ready to be used. 
+	*/
+	this.isInitialized = function(){
+		// FIXME: This should _really_ not be in here, but it fixes a bug
+		if(dojo.flash.ready == false){
+			return false;
+		}else{
+			return this.initialized;
+		}
+	}
+
+	/**
+	  Determines if this platform supports
+	  the given storage provider.
+	
+	  Example:
+			
+	  dojo.storage.manager.supportsProvider(
+	    "dojo.storage.browser.InternetExplorerStorageProvider");
+	*/
+	this.supportsProvider = function(storageClass){
+		// 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;
+	}
+	
+	/** 
+	  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:
+	
+	  dojo.connect(dojo.storage.manager, "loaded", someInstance, 
+	               someInstance.someMethod);
+	*/
+	this.loaded = function(){
+	}
+}

Added: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/storage/Storage.as
URL: http://svn.apache.org/viewcvs/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/storage/Storage.as?rev=406128&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/storage/Storage.as (added)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/storage/Storage.as Sat May 13 09:36:25 2006
@@ -0,0 +1,144 @@
+/*
+	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(){
+		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);
+		_root._settingsBackground.loadMovie("../../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("../../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 seperate 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/framework/src/java/org/apache/tapestry/html/dojo/src/storage/__package__.js
URL: http://svn.apache.org/viewcvs/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/storage/__package__.js?rev=406128&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/storage/__package__.js (added)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/storage/__package__.js Sat May 13 09:36:25 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.*");
+

Added: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/storage/browser.js
URL: http://svn.apache.org/viewcvs/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/storage/browser.js?rev=406128&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/storage/browser.js (added)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/storage/browser.js Sat May 13 09:36:25 2006
@@ -0,0 +1,195 @@
+/*
+	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 Alex Russel, alex@dojotoolkit.org
+		@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(){
+		// 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(namespace){
+		this.namespace = namespace;
+	},
+
+	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 new Array();
+		}
+
+		// the results are returned comma seperated; split them
+		results = results.split(",");
+		
+		return results;
+	},
+
+	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){
+		//dojo.debug("_onStatus, statusResult="+statusResult+", key="+key);
+		if(statusResult == dojo.storage.PENDING){
+			dojo.flash.obj.center();
+			dojo.flash.obj.setVisible(true);
+		}else{
+			dojo.flash.obj.setVisible(false);
+		}
+		
+		if(!dojo.lang.isUndefined(dojo.storage._statusHandler) 
+				&& dojo.storage._statusHandler != null){
+			dojo.storage._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();
+															

Added: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/storage/dashboard.js
URL: http://svn.apache.org/viewcvs/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/storage/dashboard.js?rev=406128&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/storage/dashboard.js (added)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/storage/dashboard.js Sat May 13 09:36:25 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());



Mime
View raw message