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

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/validate/common.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/validate/common.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/validate/common.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/validate/common.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,226 @@
+/*
+	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.validate.common");
+dojo.require("dojo.validate");
+dojo.require("dojo.regexp");
+
+// *** Validation Functions ****
+
+/**
+  Checks if a string has non whitespace characters. 
+  Parameters allow you to constrain the length.
+
+  @param value  A string.
+  @param flags  An object.
+    flags.length  If set, checks if there are exactly flags.length number of characters.
+    flags.minlength  If set, checks if there are at least flags.minlength number of characters.
+    flags.maxlength  If set, checks if there are at most flags.maxlength number of characters.
+  @return  true or false.
+*/
+dojo.validate.isText = function(value, flags) {
+	flags = (typeof flags == "object") ? flags : {};
+
+	// test for text
+	if ( /^\s*$/.test(value) ) { return false; }
+
+	// length tests
+	if ( typeof flags.length == "number" && flags.length != value.length ) { return false; }
+	if ( typeof flags.minlength == "number" && flags.minlength > value.length ) { return false; }
+	if ( typeof flags.maxlength == "number" && flags.maxlength < value.length ) { return false; }
+
+	return true;
+}
+
+/**
+  Validates whether a string is in an integer format. 
+
+  @param value  A string.
+  @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. sign is optional).
+    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  true or false.
+*/
+dojo.validate.isInteger = function(value, flags) {
+	var re = new RegExp("^" + dojo.regexp.integer(flags) + "$");
+	return re.test(value);
+}
+
+/**
+  Validates whether a string is a real valued number. 
+  Format is the usual exponential notation.
+
+  @param value  A string.
+  @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  The character used for the decimal point.  Default is ".".
+    flags.exponent  Express in exponential notation.  Can be true, false, or [true, false].
+      Default is [true, false], (i.e. the exponential part is optional).
+    flags.eSigned  The leading plus-or-minus sign on the exponent.  Can be true, false, 
+      or [true, false].  Default is [true, false], (i.e. sign is optional).
+    flags in regexp.integer can be applied.
+  @return  true or false.
+*/
+dojo.validate.isRealNumber = function(value, flags) {
+	var re = new RegExp("^" + dojo.regexp.realNumber(flags) + "$");
+	return re.test(value);
+}
+
+/**
+  Validates whether a string denotes a monetary value. 
+
+  @param value  A string.
+  @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. sign is optional).
+    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. cents are optional).
+    flags.decimal  The character used for the decimal point.  Default is ".".
+  @return  true or false.
+*/
+dojo.validate.isCurrency = function(value, flags) {
+	var re = new RegExp("^" + dojo.regexp.currency(flags) + "$");
+	return re.test(value);
+}
+
+/**
+  Validates whether a string denoting an integer, 
+  real number, or monetary value is between a max and min. 
+
+  @param value  A string.
+  @param flags  An object.
+    flags.max  A number, which the value must be less than or equal to for the validation to be true.
+    flags.min  A number, which the value must be greater than or equal to for the validation to be true.
+    flags.decimal  The character used for the decimal point.  Default is ".".
+  @return  true or false.
+*/
+dojo.validate.isInRange = function(value, flags) {
+	// assign default values to missing paramters
+	flags = (typeof flags == "object") ? flags : {};
+	var max = (typeof flags.max == "number") ? flags.max : Infinity;
+	var min = (typeof flags.min == "number") ? flags.min : -Infinity;
+	var dec = (typeof flags.decimal == "string") ? flags.decimal : ".";
+	
+	// splice out anything not part of a number
+	var pattern = "[^" + dec + "\\deE+-]";
+	value = value.replace(RegExp(pattern, "g"), "");
+
+	// trim ends of things like e, E, or the decimal character
+	value = value.replace(/^([+-]?)(\D*)/, "$1");
+	value = value.replace(/(\D*)$/, "");
+
+	// replace decimal with ".". The minus sign '-' could be the decimal!
+	pattern = "(\\d)[" + dec + "](\\d)";
+	value = value.replace(RegExp(pattern, "g"), "$1.$2");
+
+	value = Number(value);
+	if ( value < min || value > max ) { return false; }
+
+	return true;
+}
+
+
+/**
+  Validates any sort of number based format.
+  Use it for phone numbers, social security numbers, zip-codes, etc.
+  The value can be validated against 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 value  A string.
+  @param flags  An object.
+    flags.format  A string or an Array of strings for multiple formats.
+  @return  true or false
+*/
+dojo.validate.isNumberFormat = function(value, flags) {
+	var re = new RegExp("^" + dojo.regexp.numberFormat(flags) + "$", "i");
+	return re.test(value);
+}
+
+/**
+	Procedural API Description
+
+		The main aim is to make input validation expressible in a simple format.
+		You define profiles which declare the required and optional fields and any constraints they might have.
+		The results are provided as an object that makes it easy to handle missing and invalid input.
+
+	Usage
+
+		var results = dojo.validate.check(form, profile);
+
+	Profile Object
+
+		var profile = {
+			// filters change the field value and are applied before validation.
+			trim: ["tx1", "tx2"],
+			uppercase: ["tx9"],
+			lowercase: ["tx5", "tx6", "tx7"],
+			ucfirst: ["tx10"],
+			digit: ["tx11"],
+
+			// required input fields that are blank will be reported missing.
+			// required radio button groups and drop-down lists with no selection will be reported missing.
+			// checkbox groups and selectboxes can be required to have more than one value selected.
+			// List required fields by name and use this notation to require more than one value: {checkboxgroup: 2}, {selectboxname: 3}.
+			required: ["tx7", "tx8", "pw1", "ta1", "rb1", "rb2", "cb3", "s1", {"doubledip":2}, {"tripledip":3}],
+
+			// dependant/conditional fields are required if the target field is present and not blank.
+			// At present only textbox, password, and textarea fields are supported.
+			dependancies:	{
+				cc_exp: "cc_no",	
+				cc_type: "cc_no",	
+			},
+
+			// Fields can be validated using any boolean valued function.  
+			// Use arrays to specify parameters in addition to the field value.
+			constraints: {
+				field_name1: myValidationFunction,
+				field_name2: dojo.validate.isInteger,
+				field_name3: [myValidationFunction, additional parameters],
+				field_name4: [dojo.validate.isValidDate, "YYYY.MM.DD"],
+				field_name5: [dojo.validate.isEmailAddress, false, true],
+			},
+
+			// Confirm is a sort of conditional validation.
+			// It associates each field in its property list with another field whose value should be equal.
+			// If the values are not equal, the field in the property list is reported as Invalid. Unless the target field is blank.
+			confirm: {
+				email_confirm: "email",	
+				pw2: "pw1",	
+			}
+		};
+
+	Results Object
+
+		isSuccessful(): Returns true if there were no invalid or missing fields, else it returns false.
+		hasMissing():  Returns true if the results contain any missing fields.
+		getMissing():  Returns a list of required fields that have values missing.
+		isMissing(field):  Returns true if the field is required and the value is missing.
+		hasInvalid():  Returns true if the results contain fields with invalid data.
+		getInvalid():  Returns a list of fields that have invalid values.
+		isInvalid(field):  Returns true if the field has an invalid value.
+
+*/

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/validate/datetime.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/validate/datetime.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/validate/datetime.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/validate/datetime.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,168 @@
+/*
+	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.validate.datetime");
+dojo.require("dojo.validate.common");
+
+/**
+  Validates a time value in any International format.
+  The value can be validated against 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.
+  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 value  A string.
+  @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  true or false
+*/
+dojo.validate.isValidTime = function(value, flags) {
+	var re = new RegExp("^" + dojo.regexp.time(flags) + "$", "i");
+	return re.test(value);
+}
+
+/**
+  Validates 12-hour time format.
+  Zero-padding is not allowed for hours, required for minutes and seconds.
+  Seconds are optional.
+
+  @param value  A string.
+  @return  true or false
+*/
+dojo.validate.is12HourTime = function(value) {
+	return dojo.validate.isValidTime(value, {format: ["h:mm:ss t", "h:mm t"]});
+}
+
+/**
+  Validates 24-hour military time format.
+  Zero-padding is required for hours, minutes, and seconds.
+  Seconds are optional.
+
+  @param value  A string.
+  @return  true or false
+*/
+dojo.validate.is24HourTime = function(value) {
+	return dojo.validate.isValidTime(value, {format: ["HH:mm:ss", "HH:mm"]} );
+}
+
+/**
+  Returns true if the date conforms to the format given and is a valid date. Otherwise returns false.
+
+  @param dateValue  A string for the date.
+  @param format  A string, default is  "MM/DD/YYYY".
+  @return  true or false
+
+  Accepts any type of format, including ISO8601.
+  All characters in the format string are treated literally except the following tokens:
+
+  YYYY - matches a 4 digit year
+  M - matches a non zero-padded month
+  MM - matches a zero-padded month
+  D -  matches a non zero-padded date
+  DD -  matches a zero-padded date
+  DDD -  matches an ordinal date, 001-365, and 366 on leapyear
+  ww - matches week of year, 01-53
+  d - matches day of week, 1-7
+
+  Examples: These are all today's date.
+
+  Date          Format
+  2005-W42-3    YYYY-Www-d
+  2005-292      YYYY-DDD
+  20051019      YYYYMMDD
+  10/19/2005    M/D/YYYY
+  19.10.2005    D.M.YYYY
+*/
+dojo.validate.isValidDate = function(dateValue, format) {
+	// Default is the American format
+	if (typeof format == "object" && typeof format.format == "string"){ format = format.format; }
+	if (typeof format != "string") { format = "MM/DD/YYYY"; }
+
+	// Create a literal regular expression based on format
+	var reLiteral = format.replace(/([$^.*+?=!:|\/\\\(\)\[\]\{\}])/g, "\\$1");
+
+	// Convert all the tokens to RE elements
+	reLiteral = reLiteral.replace( "YYYY", "([0-9]{4})" );
+	reLiteral = reLiteral.replace( "MM", "(0[1-9]|10|11|12)" );
+	reLiteral = reLiteral.replace( "M", "([1-9]|10|11|12)" );
+	reLiteral = reLiteral.replace( "DDD", "(00[1-9]|0[1-9][0-9]|[12][0-9][0-9]|3[0-5][0-9]|36[0-6])" );
+	reLiteral = reLiteral.replace( "DD", "(0[1-9]|[12][0-9]|30|31)" );
+	reLiteral = reLiteral.replace( "D", "([1-9]|[12][0-9]|30|31)" );
+	reLiteral = reLiteral.replace( "ww", "(0[1-9]|[1-4][0-9]|5[0-3])" );
+	reLiteral = reLiteral.replace( "d", "([1-7])" );
+
+	// Anchor pattern to begining and end of string
+	reLiteral = "^" + reLiteral + "$";
+
+	// Dynamic RE that parses the original format given
+	var re = new RegExp(reLiteral);
+	
+	// Test if date is in a valid format
+	if (!re.test(dateValue))  return false;
+
+	// Parse date to get elements and check if date is valid
+	// Assume valid values for date elements not given.
+	var year = 0, month = 1, date = 1, dayofyear = 1, week = 1, day = 1;
+
+	// Capture tokens
+	var tokens = format.match( /(YYYY|MM|M|DDD|DD|D|ww|d)/g );
+
+	// Capture date values
+	var values = re.exec(dateValue);
+
+	// Match up tokens with date values
+	for (var i = 0; i < tokens.length; i++) {
+		switch (tokens[i]) {
+		case "YYYY":
+			year = Number(values[i+1]); break;
+		case "M":
+		case "MM":
+			month = Number(values[i+1]); break;
+		case "D":
+		case "DD":
+			date = Number(values[i+1]); break;
+		case "DDD":
+			dayofyear = Number(values[i+1]); break;
+		case "ww":
+			week = Number(values[i+1]); break;
+		case "d":
+			day = Number(values[i+1]); break;
+		}
+	}
+
+	// Leap years are divisible by 4, but not by 100, unless by 400
+	var leapyear = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
+
+	// 31st of a month with 30 days
+	if (date == 31 && (month == 4 || month == 6 || month == 9 || month == 11)) return false; 
+
+	// February 30th or 31st
+	if (date >= 30 && month == 2) return false; 
+
+	// February 29th outside a leap year
+	if (date == 29 && month == 2 && !leapyear) return false; 
+	if (dayofyear == 366 && !leapyear)  return false;
+
+	return true;
+}

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/validate/de.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/validate/de.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/validate/de.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/validate/de.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,30 @@
+/*
+	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.validate.us");
+dojo.require("dojo.validate.common");
+
+/**
+  Validates German currency.
+
+  @param value  A string.
+  @return  true or false.
+*/
+dojo.validate.isGermanCurrency = function(value) {
+	var flags = {
+		symbol: "�",
+		placement: "after",
+		decimal: ",",
+		separator: "."
+	};
+	return dojo.validate.isCurrency(value, flags);
+}
+
+

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/validate/jp.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/validate/jp.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/validate/jp.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/validate/jp.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,28 @@
+/*
+	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.validate.jp");
+dojo.require("dojo.validate.common");
+
+/**
+  Validates Japanese currency.
+
+  @param value  A string.
+  @return  true or false.
+*/
+dojo.validate.isJapaneseCurrency = function(value) {
+	var flags = {
+		symbol: "�",
+		cents: false
+	};
+	return dojo.validate.isCurrency(value, flags);
+}
+
+

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/validate/us.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/validate/us.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/validate/us.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/validate/us.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,94 @@
+/*
+	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.validate.us");
+dojo.require("dojo.validate.common");
+
+/**
+  Validates U.S. currency.
+
+  @param value  A string.
+  @param flags  An object.
+    flags in validate.isCurrency can be applied.
+  @return  true or false.
+*/
+dojo.validate.us.isCurrency = function(value, flags) {
+	return dojo.validate.isCurrency(value, flags);
+}
+
+
+/**
+  Validates US state and territory abbreviations.
+
+	@param value  A two character string.
+  @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  true or false
+*/
+dojo.validate.us.isState = function(value, flags) {
+	var re = new RegExp("^" + dojo.regexp.us.state(flags) + "$", "i");
+	return re.test(value);
+}
+
+/**
+  Validates 10 US digit phone number for several common formats:
+
+  @param value The telephone number string
+  @return true or false
+*/
+dojo.validate.us.isPhoneNumber = function(value) {
+	var flags = {
+		format: [
+			"###-###-####",
+			"(###) ###-####",
+			"(###) ### ####",
+			"###.###.####",
+			"###/###-####",
+			"### ### ####",
+			"###-###-#### x#???",
+			"(###) ###-#### x#???",
+			"(###) ### #### x#???",
+			"###.###.#### x#???",
+			"###/###-#### x#???",
+			"### ### #### x#???",
+			"##########"
+		]
+	};
+
+	return dojo.validate.isNumberFormat(value, flags);
+}
+
+// Validates social security number
+dojo.validate.us.isSocialSecurityNumber = function(value) {
+	var flags = {
+		format: [
+			"###-##-####",
+			"### ## ####",
+			"#########"
+		]
+	};
+
+	return dojo.validate.isNumberFormat(value, flags);
+}
+
+// Validates U.S. zip-code
+dojo.validate.us.isZipCode = function(value) {
+	var flags = {
+		format: [
+			"#####-####",
+			"##### ####",
+			"#########",
+			"#####"
+		]
+	};
+
+	return dojo.validate.isNumberFormat(value, flags);
+}

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/Button.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/Button.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/Button.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/Button.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,315 @@
+/*
+	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.widget.Button");
+dojo.provide("dojo.widget.html.Button");
+
+dojo.require("dojo.lang.extras");
+dojo.require("dojo.html");
+dojo.require("dojo.style");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlWidget");
+
+dojo.widget.defineWidget(
+	"dojo.widget.html.Button",
+	dojo.widget.HtmlWidget,
+	{
+		widgetType: "Button",
+		isContainer: true,
+	
+		// Constructor arguments
+		caption: "",
+		disabled: false,
+	
+		templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlButtonTemplate.html"),
+		templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlButtonTemplate.css"),
+		
+		// button images
+		inactiveImg: "src/widget/templates/images/soriaButton-",
+		activeImg: "src/widget/templates/images/soriaActive-",
+		pressedImg: "src/widget/templates/images/soriaPressed-",
+		disabledImg: "src/widget/templates/images/soriaDisabled-",
+		width2height: 1.0/3.0,
+	
+		// attach points
+		containerNode: null,
+		leftImage: null,
+		centerImage: null,
+		rightImage: null,
+	
+		fillInTemplate: function(args, frag){
+			if(this.caption != ""){
+				this.containerNode.appendChild(document.createTextNode(this.caption));
+			}
+			dojo.html.disableSelection(this.containerNode);
+		},
+
+		postCreate: function(args, frag){
+			this.sizeMyself();
+		},
+	
+		sizeMyself: function(){
+			// we cannot size correctly if any of our ancestors are hidden (display:none),
+			// so temporarily attach to document.body
+			if(this.domNode.parentNode){
+				var placeHolder = document.createElement("span");
+				dojo.dom.insertBefore(placeHolder, this.domNode);
+			}
+			dojo.html.body().appendChild(this.domNode);
+			
+			this.sizeMyselfHelper();
+			
+			// Put this.domNode back where it was originally
+			if(placeHolder){
+				dojo.dom.insertBefore(this.domNode, placeHolder);
+				dojo.dom.removeNode(placeHolder);
+			}
+		},
+
+		sizeMyselfHelper: function(){
+			this.height = dojo.style.getOuterHeight(this.containerNode);
+			this.containerWidth = dojo.style.getOuterWidth(this.containerNode);
+			var endWidth= this.height * this.width2height;
+	
+			this.containerNode.style.left=endWidth+"px";
+	
+			this.leftImage.height = this.rightImage.height = this.centerImage.height = this.height;
+			this.leftImage.width = this.rightImage.width = endWidth+1;
+			this.centerImage.width = this.containerWidth;
+			this.centerImage.style.left=endWidth+"px";
+			this._setImage(this.disabled ? this.disabledImg : this.inactiveImg);
+
+			if ( this.disabled ) {
+				dojo.html.prependClass(this.domNode, "dojoButtonDisabled");
+			} else {
+				dojo.html.removeClass(this.domNode, "dojoButtonDisabled");
+			}
+				
+			this.domNode.style.height=this.height + "px";
+			this.domNode.style.width= (this.containerWidth+2*endWidth) + "px";
+		},
+	
+		onMouseOver: function(e){
+			if( this.disabled ){ return; }
+			dojo.html.prependClass(this.domNode, "dojoButtonHover");
+			this._setImage(this.activeImg);
+		},
+	
+		onMouseDown: function(e){
+			if( this.disabled ){ return; }
+			dojo.html.prependClass(this.domNode, "dojoButtonDepressed");
+			dojo.html.removeClass(this.domNode, "dojoButtonHover");
+			this._setImage(this.pressedImg);
+		},
+		onMouseUp: function(e){
+			if( this.disabled ){ return; }
+			dojo.html.prependClass(this.domNode, "dojoButtonHover");
+			dojo.html.removeClass(this.domNode, "dojoButtonDepressed");
+			this._setImage(this.activeImg);
+		},
+	
+		onMouseOut: function(e){
+			if( this.disabled ){ return; }
+			dojo.html.removeClass(this.domNode, "dojoButtonHover");
+			this._setImage(this.inactiveImg);
+		},
+	
+		buttonClick: function(e){
+			if( !this.disabled ) { this.onClick(e); }
+		},
+
+		onClick: function(e) { },
+
+		_setImage: function(prefix){
+			this.leftImage.src=dojo.uri.dojoUri(prefix + "l.gif");
+			this.centerImage.src=dojo.uri.dojoUri(prefix + "c.gif");
+			this.rightImage.src=dojo.uri.dojoUri(prefix + "r.gif");
+		},
+		
+		_toggleMenu: function(menuId){
+			var menu = dojo.widget.getWidgetById(menuId);
+			if ( !menu ) { return; }
+	
+			if ( menu.open && !menu.isShowingNow) {
+				var pos = dojo.style.getAbsolutePosition(this.domNode, false);
+				menu.open(pos.x, pos.y+this.height, this);
+			} else if ( menu.close && menu.isShowingNow ){
+				menu.close();
+			} else {
+				menu.toggle();
+			}
+		},
+		
+		setCaption: function(content){
+			this.caption=content;
+			this.containerNode.innerHTML=content;
+			this.sizeMyself();
+		},
+		
+		setDisabled: function(disabled){
+			this.disabled=disabled;
+			this.sizeMyself();
+		}
+	});
+
+/**** DropDownButton - push the button and a menu shows up *****/
+dojo.widget.defineWidget(
+	"dojo.widget.html.DropDownButton",
+	dojo.widget.html.Button,
+	{
+		widgetType: "DropDownButton",
+	
+		menuId: "",
+
+		arrow: null,
+	
+		downArrow: "src/widget/templates/images/whiteDownArrow.gif",
+		disabledDownArrow: "src/widget/templates/images/whiteDownArrow.gif",
+	
+		fillInTemplate: function(args, frag){
+			dojo.widget.html.DropDownButton.superclass.fillInTemplate.call(this, args, frag);
+	
+			this.arrow = document.createElement("img");
+			dojo.html.setClass(this.arrow, "downArrow");
+		},
+
+		sizeMyselfHelper: function(){
+			// draw the arrow (todo: why is the arror in containerNode rather than outside it?)
+			this.arrow.src = dojo.uri.dojoUri(this.disabled ? this.disabledDownArrow : this.downArrow);
+			this.containerNode.appendChild(this.arrow);
+
+			dojo.widget.html.DropDownButton.superclass.sizeMyselfHelper.call(this);
+		},
+
+		onClick: function (e){
+			this._toggleMenu(this.menuId);
+		}
+	});
+
+/**** ComboButton - left side is normal button, right side shows menu *****/
+dojo.widget.defineWidget(
+	"dojo.widget.html.ComboButton",
+	dojo.widget.html.Button,
+	{
+		widgetType: "ComboButton",
+	
+		menuId: "",
+	
+		templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlComboButtonTemplate.html"),
+	
+		// attach points
+		leftPart: null,
+		rightPart: null,
+		arrowBackgroundImage: null,
+	
+		// constants
+		splitWidth: 2,		// pixels between left&right part of button
+		arrowWidth: 5,		// width of segment holding down arrow
+	
+		sizeMyselfHelper: function(e){
+			this.height = dojo.style.getOuterHeight(this.containerNode);
+			this.containerWidth = dojo.style.getOuterWidth(this.containerNode);
+			var endWidth= this.height/3;
+	
+			// left part
+			this.leftImage.height = this.rightImage.height = this.centerImage.height = 
+				this.arrowBackgroundImage.height = this.height;
+			this.leftImage.width = endWidth+1;
+			this.centerImage.width = this.containerWidth;
+			this.leftPart.style.height = this.height + "px";
+			this.leftPart.style.width = endWidth + this.containerWidth + "px";
+			this._setImageL(this.disabled ? this.disabledImg : this.inactiveImg);
+	
+			// right part
+			this.arrowBackgroundImage.width=this.arrowWidth;
+			this.rightImage.width = endWidth+1;
+			this.rightPart.style.height = this.height + "px";
+			this.rightPart.style.width = this.arrowWidth + endWidth + "px";
+			this._setImageR(this.disabled ? this.disabledImg : this.inactiveImg);
+	
+			// outer container
+			this.domNode.style.height=this.height + "px";
+			var totalWidth = this.containerWidth+this.splitWidth+this.arrowWidth+2*endWidth;
+			this.domNode.style.width= totalWidth + "px";
+		},
+	
+		/** functions on left part of button**/
+		leftOver: function(e){
+			if( this.disabled ){ return; }
+			dojo.html.prependClass(this.leftPart, "dojoButtonHover");
+			this._setImageL(this.activeImg);
+		},
+	
+		leftDown: function(e){
+			if( this.disabled ){ return; }
+			dojo.html.prependClass(this.leftPart, "dojoButtonDepressed");
+			dojo.html.removeClass(this.leftPart, "dojoButtonHover");
+			this._setImageL(this.pressedImg);
+		},
+		leftUp: function(e){
+			if( this.disabled ){ return; }
+			dojo.html.prependClass(this.leftPart, "dojoButtonHover");
+			dojo.html.removeClass(this.leftPart, "dojoButtonDepressed");
+			this._setImageL(this.activeImg);
+		},
+	
+		leftOut: function(e){
+			if( this.disabled ){ return; }
+			dojo.html.removeClass(this.leftPart, "dojoButtonHover");
+			this._setImageL(this.inactiveImg);
+		},
+	
+		leftClick: function(e){
+			if ( !this.disabled ) {
+				this.onClick(e);
+			}
+		},
+	
+		_setImageL: function(prefix){
+			this.leftImage.src=dojo.uri.dojoUri(prefix + "l.gif");
+			this.centerImage.src=dojo.uri.dojoUri(prefix + "c.gif");
+		},
+	
+		/*** functions on right part of button ***/
+		rightOver: function(e){
+			if( this.disabled ){ return; }
+			dojo.html.prependClass(this.rightPart, "dojoButtonHover");
+			this._setImageR(this.activeImg);
+		},
+	
+		rightDown: function(e){
+			if( this.disabled ){ return; }
+			dojo.html.prependClass(this.rightPart, "dojoButtonDepressed");
+			dojo.html.removeClass(this.rightPart, "dojoButtonHover");
+			this._setImageR(this.pressedImg);
+		},
+		rightUp: function(e){
+			if( this.disabled ){ return; }
+			dojo.html.prependClass(this.rightPart, "dojoButtonHover");
+			dojo.html.removeClass(this.rightPart, "dojoButtonDepressed");
+			this._setImageR(this.activeImg);
+		},
+	
+		rightOut: function(e){
+			if( this.disabled ){ return; }
+			dojo.html.removeClass(this.rightPart, "dojoButtonHover");
+			this._setImageR(this.inactiveImg);
+		},
+	
+		rightClick: function(e){
+			if( this.disabled ){ return; }
+			this._toggleMenu(this.menuId);
+		},
+	
+		_setImageR: function(prefix){
+			this.arrowBackgroundImage.src=dojo.uri.dojoUri(prefix + "c.gif");
+			this.rightImage.src=dojo.uri.dojoUri(prefix + "r.gif");
+		}
+	});
\ No newline at end of file

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/Button2.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/Button2.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/Button2.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/Button2.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,33 @@
+/*
+	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.widget.Button2");
+dojo.require("dojo.widget.Button");
+dojo.require("dojo.widget.*");
+
+dojo.widget.tags.addParseTreeHandler("dojo:button2");
+dojo.widget.tags.addParseTreeHandler("dojo:dropdownbutton2");
+dojo.widget.tags.addParseTreeHandler("dojo:combobutton2");
+
+dojo.deprecated("dojo.widget.Button2", "Use dojo.widget.Button instead", "0.4");
+
+dojo.requireAfterIf("html", "dojo.widget.html.Button2");
+
+dojo.widget.Button2 = function(){}
+dojo.inherits(dojo.widget.Button2, dojo.widget.Button);
+dojo.lang.extend(dojo.widget.Button2, { widgetType: "Button2" });
+
+dojo.widget.DropDownButton2 = function(){}
+dojo.inherits(dojo.widget.DropDownButton2, dojo.widget.DropDownButton);
+dojo.lang.extend(dojo.widget.DropDownButton2, { widgetType: "DropDownButton2" });
+
+dojo.widget.ComboButton2 = function(){}
+dojo.inherits(dojo.widget.ComboButton2, dojo.widget.ComboButton);
+dojo.lang.extend(dojo.widget.ComboButton2, { widgetType: "ComboButton2" });

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/Chart.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/Chart.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/Chart.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/Chart.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,199 @@
+/*
+	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.widget.Chart");
+dojo.provide("dojo.widget.Chart.PlotTypes");
+dojo.provide("dojo.widget.Chart.DataSeries");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.graphics.color");
+dojo.require("dojo.graphics.color.hsl");
+dojo.widget.tags.addParseTreeHandler("dojo:chart");
+
+dojo.widget.Chart = function(){
+	dojo.widget.Widget.call(this);
+	this.widgetType = "Chart";
+	this.isContainer = false;
+	this.series = [];
+	// FIXME: why is this a mixin method?
+	this.assignColors = function(){
+		var hue=30;
+		var sat=120;
+		var lum=120;
+		var steps = Math.round(330/this.series.length);
+
+		for(var i=0; i<this.series.length; i++){
+			var c=dojo.graphics.color.hsl2rgb(hue,sat,lum);
+			if(!this.series[i].color){
+				this.series[i].color = dojo.graphics.color.rgb2hex(c[0],c[1],c[2]);
+			}
+			hue += steps;
+		}
+	};
+}
+dojo.inherits(dojo.widget.Chart, dojo.widget.Widget);
+
+dojo.widget.Chart.PlotTypes = {
+	Bar:"bar",
+	Line:"line",
+	Scatter:"scatter",
+	Bubble:"bubble"
+};
+
+/*
+ *	Every chart has a set of data series; this is the series.  Note that each
+ *	member of value is an object and in the minimum has 2 properties: .x and
+ *	.value.
+ */
+dojo.widget.Chart.DataSeries = function(key, label, plotType, color){
+	// FIXME: why the hell are plot types specified neumerically? What is this? C?
+	this.id = "DataSeries"+dojo.widget.Chart.DataSeries.count++;
+	this.key = key;
+	this.label = label||this.id;
+	this.plotType = plotType||0;
+	this.color = color;
+	this.values = [];
+};
+
+dojo.lang.extend(dojo.widget.Chart.DataSeries, {
+	add: function(v){
+		if(v.x==null||v.value==null){
+			dojo.raise("dojo.widget.Chart.DataSeries.add: v must have both an 'x' and 'value' property.");
+		}
+		this.values.push(v);
+	},
+
+	clear: function(){
+		this.values=[];
+	},
+
+	createRange: function(len){
+		var idx = this.values.length-1;
+		var length = (len||this.values.length);
+		return { "index": idx, "length": length, "start":Math.max(idx-length,0) };
+	},
+
+	//	trend values
+	getMean: function(len){
+		var range = this.createRange(len);
+		if(range.index<0){ return 0; }
+		var t = 0;
+		var c = 0;
+		for(var i=range.index; i>=range.start; i--){
+			var n = parseFloat(this.values[i].value);
+			if(!isNaN(n)){ t += n; c++; }
+		}
+		t /= Math.max(c,1);
+		return t;
+	},
+
+	getMovingAverage: function(len){
+		var range = this.createRange(len);
+		if(range.index<0){ return 0; }
+		var t = 0;
+		var c = 0;
+		for(var i=range.index; i>=range.start; i--){
+			var n = parseFloat(this.values[i].value);
+			if(!isNaN(n)){ t += n; c++; }
+		}
+		t /= Math.max(c,1);
+		return t;
+	},
+
+	getVariance: function(len){
+		var range = this.createRange(len);
+		if(range.index < 0){ return 0; }
+		var t = 0; // FIXME: for tom: wtf are t, c, and s?
+		var s = 0;
+		var c = 0;
+		for(var i=range.index; i>=range.start; i--){
+			var n = parseFloat(this.values[i].value);
+			if(!isNaN(n)){
+				t += n;
+				s += Math.pow(n,2);
+				c++;
+			}
+		}
+		return (s/c)-Math.pow(t/c,2);
+	},
+
+	getStandardDeviation: function(len){
+		return Math.sqrt(this.getVariance(len));
+	},
+
+	getMax: function(len){
+		var range = this.createRange(len);
+		if(range.index < 0){ return 0; }
+		var t = 0;
+		for (var i=range.index; i>=range.start; i--){
+			var n=parseFloat(this.values[i].value);
+			if (!isNaN(n)){
+				t=Math.max(n,t);
+			}
+		}
+		return t;
+	},
+
+	getMin: function(len){
+		var range=this.createRange(len);
+		if(range.index < 0){ return 0; }
+		var t = 0;
+		for(var i=range.index; i>=range.start; i--){
+			var n = parseFloat(this.values[i].value);
+			if(!isNaN(n)){
+				t=Math.min(n,t);
+			}
+		}
+		return t;
+	},
+
+	getMedian: function(len){
+		var range = this.createRange(len);
+
+		if(range.index<0){ return 0; }
+
+		var a = [];
+		for (var i=range.index; i>=range.start; i--){
+			var n=parseFloat(this.values[i].value);
+			if (!isNaN(n)){
+				var b=false;
+				for(var j=0; j<a.length&&!b; j++){
+					if (n==a[j]) b=true; 
+				}
+				if(!b){ a.push(n); }
+			}
+		}
+		a.sort();
+		if(a.length>0){ return a[Math.ceil(a.length/2)]; }
+		return 0;
+	},
+
+	getMode: function(len){
+		var range=this.createRange(len);
+		if(range.index<0){ return 0; }
+		var o = {};
+		var ret = 0
+		var m = 0;
+		for(var i=range.index; i>=range.start; i--){
+			var n=parseFloat(this.values[i].value);
+			if(!isNaN(n)){
+				if (!o[this.values[i].value]) o[this.values[i].value] = 1;
+				else o[this.values[i].value]++;
+			}
+		}
+		for(var p in o){
+			if(m<o[p]){ m=o[p]; ret=p; }
+		}
+		return parseFloat(ret);
+	}
+});
+
+dojo.requireIf(dojo.render.svg.support.builtin, "dojo.widget.svg.Chart");
+dojo.requireIf(dojo.render.html.ie, "dojo.widget.vml.Chart");

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/CiviCrmDatePicker.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/CiviCrmDatePicker.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/CiviCrmDatePicker.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/CiviCrmDatePicker.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,118 @@
+/*
+	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.widget.CiviCrmDatePicker");
+dojo.provide("dojo.widget.HtmlCiviCrmDatePicker");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.event.*");
+dojo.require("dojo.widget.DatePicker");
+dojo.require("dojo.widget.html.DatePicker");
+dojo.require("dojo.widget.html.TimePicker");
+dojo.require("dojo.html");
+
+dojo.widget.HtmlCiviCrmDatePicker = function(){
+	this.widgetType = "CiviCrmDatePicker";
+	this.idPrefix = "scheduled_date_time";
+	this.mode = "datetime"; // can also be date or time
+
+	this.datePicker = null;
+	this.timePicker = null;
+
+	// html nodes
+	this.dateHolderTd = null;
+	this.timeHolderTd = null;
+	this.formItemsTd = null;
+	this.formItemsTr = null;
+
+	this.monthSelect = null;
+	this.daySelect = null;
+	this.yearSelect = null;
+	this.hourSelect = null;
+	this.minSelect = null;
+	this.apSelect = null;
+
+	this.templatePath = dojo.uri.dojoUri("src/widget/templates/HtmlCiviCrmDatePicker.html");
+
+	this.modeFormats = {
+		date: "MdY",
+		time: "hiA"
+	};
+
+	this.formatMappings = {
+		"M": "monthSelect",
+		"d": "daySelect",
+		"Y": "yearSelect",
+		"h": "hourSelect",
+		"i": "minSelect",
+		"A": "apSelect"
+	};
+
+	this.setDateSelects = function(){
+		var dateObj = this.datePicker.date;
+		this.monthSelect.value = new String(dateObj.getMonth()+1);
+		this.daySelect.value = new String(dateObj.getDate());
+		this.yearSelect.value = new String(dateObj.getFullYear());
+	}
+
+	this.setTimeSelects = function(){
+		var st = this.timePicker.selectedTime;
+		this.hourSelect.value = new String(st.hour);
+		this.minSelect.value = new String(st.minute);
+		this.apSelect.value = st.amPm.toUpperCase();
+	}
+
+	this.fillInTemplate = function(args, frag){
+		var nr = frag["dojo:"+this.widgetType.toLowerCase()]["nodeRef"];
+		var sref = {};
+		while(nr.firstChild){
+			if(nr.firstChild.name){
+				sref[nr.firstChild.name] = nr.firstChild;
+			}
+			this.formItemsTd.appendChild(nr.firstChild);
+		}
+
+		if(this.mode.indexOf("date") != -1){
+			this.datePicker = dojo.widget.createWidget("DatePicker", {}, this.dateHolderTd);
+			dojo.event.connect(	this.datePicker, "onSetDate", 
+								this, "setDateSelects");
+
+			var mfd = this.modeFormats.date;
+			for(var x=0; x<mfd.length; x++){
+				this[this.formatMappings[mfd[x]]] = sref[this.idPrefix+"["+mfd[x]+"]"];
+			}
+		}
+		if(this.mode.indexOf("time") != -1){
+			this.timePicker = dojo.widget.createWidget("TimePicker", {}, this.timeHolderTd);
+			dojo.event.connect(	this.timePicker, "onSetTime", 
+								this, "setTimeSelects");
+			var mfd = this.modeFormats.time;
+			for(var x=0; x<mfd.length; x++){
+				this[this.formatMappings[mfd[x]]] = sref[this.idPrefix+"["+mfd[x]+"]"];
+			}
+		}
+	}
+
+	this.unhide = function(){
+		this.formItemsTr.style.display = "";
+	}
+
+	this.postCreate = function(){
+		dojo.event.kwConnect({
+			type: "before", 
+			srcObj: dojo.html.getParentByType(this.domNode, "form"),
+			srcFunc: "onsubmit", 
+			targetObj: this,
+			targetFunc: "unhide"
+		});
+	}
+}
+dojo.inherits(dojo.widget.HtmlCiviCrmDatePicker, dojo.widget.HtmlWidget);
+dojo.widget.tags.addParseTreeHandler("dojo:civicrmdatepicker");
+

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/ContentPane.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/ContentPane.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/ContentPane.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/ContentPane.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,16 @@
+/*
+	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
+*/
+
+// This widget doesn't do anything; is basically the same as <div>.
+// It's useful as a child of LayoutContainer, SplitContainer, or TabContainer.
+// But note that those classes can contain any widget as a child.
+
+dojo.provide("dojo.widget.ContentPane");
+dojo.requireAfterIf("html", "dojo.widget.html.ContentPane");

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/ContextMenu.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/ContextMenu.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/ContextMenu.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/ContextMenu.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,33 @@
+/*
+	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.widget.ContextMenu");
+
+dojo.deprecated("dojo.widget.ContextMenu",  "use dojo.widget.Menu2", "0.4");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.DomWidget");
+
+dojo.widget.ContextMenu = function(){
+	dojo.widget.Widget.call(this);
+	this.widgetType = "ContextMenu";
+	this.isContainer = true;
+	this.isOpened = false;
+	
+	// copy children widgets output directly to parent (this node), to avoid
+	// errors trying to insert an <li> under a <div>
+	this.snarfChildDomOutput = true;
+
+}
+
+dojo.inherits(dojo.widget.ContextMenu, dojo.widget.Widget);
+dojo.widget.tags.addParseTreeHandler("dojo:contextmenu");
+
+dojo.requireAfterIf("html", "dojo.widget.html.ContextMenu");

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/DatePicker.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/DatePicker.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/DatePicker.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/DatePicker.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,61 @@
+/*
+	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.widget.DatePicker");
+dojo.provide("dojo.widget.DatePicker.util");
+dojo.require("dojo.widget.DomWidget");
+dojo.require("dojo.date");
+
+// NOTE: this function is only used as mixin (never as a constructor)
+dojo.widget.DatePicker = function() {
+	// the following aliases prevent breaking people using 0.2.x
+	this.months = dojo.date.months,
+	this.weekdays = dojo.date.days,
+	this.toRfcDate = dojo.widget.DatePicker.util.toRfcDate,
+	this.fromRfcDate = dojo.widget.DatePicker.util.fromRfcDate,
+	this.initFirstSaturday = dojo.widget.DatePicker.util.initFirstSaturday
+};
+
+dojo.requireAfterIf("html", "dojo.widget.html.DatePicker");
+
+dojo.widget.DatePicker.util = new function() {
+	this.months = dojo.date.months;
+	this.weekdays = dojo.date.days;
+	
+	this.toRfcDate = function(jsDate) {
+		if(!jsDate) {
+			var jsDate = new Date();
+		}
+		// because this is a date picker and not a time picker, we don't return a time
+		return dojo.date.format(jsDate, "%Y-%m-%d");
+	}
+	
+	this.fromRfcDate = function(rfcDate) {
+		// backwards compatible support for use of "any" instead of just not 
+		// including the time
+		if(rfcDate.indexOf("Tany")!=-1) {
+			rfcDate = rfcDate.replace("Tany","");
+		}
+		var jsDate = new Date();
+		dojo.date.setIso8601(jsDate, rfcDate);
+		return jsDate;
+	}
+	
+	this.initFirstSaturday = function(month, year) {
+		if(!month) {
+			month = this.date.getMonth();
+		}
+		if(!year) {
+			year = this.date.getFullYear();
+		}
+		var firstOfMonth = new Date(year, month, 1);
+		return {year: year, month: month, date: 7 - firstOfMonth.getDay()};
+	}
+}

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/Dialog.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/Dialog.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/Dialog.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/Dialog.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,269 @@
+/*
+	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.widget.Dialog");
+dojo.provide("dojo.widget.html.Dialog");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.ContentPane");
+dojo.require("dojo.event.*");
+dojo.require("dojo.graphics.color");
+dojo.require("dojo.html");
+
+dojo.widget.defineWidget(
+	"dojo.widget.html.Dialog",
+	dojo.widget.html.ContentPane,
+	{
+		templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlDialog.html"),
+		isContainer: true,
+		_scrollConnected: false,
+		
+		// provide a focusable element or element id if you need to
+		// work around FF's tendency to send focus into outer space on hide
+		focusElement: "",
+
+		bg: null,
+		bgColor: "black",
+		bgOpacity: 0.4,
+		followScroll: true,
+		_fromTrap: false,
+		anim: null,
+		blockDuration: 0,
+		lifetime: 0,
+
+		trapTabs: function(e){
+			if(e.target == this.tabStart) {
+				if(this._fromTrap) {
+					this._fromTrap = false;
+				} else {
+					this._fromTrap = true;
+					this.tabEnd.focus();
+				}
+			} else if(e.target == this.tabEnd) {
+				if(this._fromTrap) {
+					this._fromTrap = false;
+				} else {
+					this._fromTrap = true;
+					this.tabStart.focus();
+				}
+			}
+		},
+
+		clearTrap: function(e) {
+			var _this = this;
+			setTimeout(function() {
+				_this._fromTrap = false;
+			}, 100);
+		},
+
+		postCreate: function(args, frag, parentComp) {
+			with(this.domNode.style) {
+				position = "absolute";
+				zIndex = 999;
+				display = "none";
+				overflow = "visible";
+			}
+			var b = document.body;
+			b.appendChild(this.domNode);
+
+			this.bg = document.createElement("div");
+			this.bg.className = "dialogUnderlay";
+			with(this.bg.style) {
+				position = "absolute";
+				left = top = "0px";
+				zIndex = 998;
+				display = "none";
+			}
+			this.setBackgroundColor(this.bgColor);
+			b.appendChild(this.bg);
+
+			this.bgIframe = new dojo.html.BackgroundIframe(this.bg);
+		},
+
+		setBackgroundColor: function(color) {
+			if(arguments.length >= 3) {
+				color = new dojo.graphics.color.Color(arguments[0], arguments[1], arguments[2]);
+			} else {
+				color = new dojo.graphics.color.Color(color);
+			}
+			this.bg.style.backgroundColor = color.toString();
+			return this.bgColor = color;
+		},
+		
+		setBackgroundOpacity: function(op) {
+			if(arguments.length == 0) { op = this.bgOpacity; }
+			dojo.style.setOpacity(this.bg, op);
+			try {
+				this.bgOpacity = dojo.style.getOpacity(this.bg);
+			} catch (e) {
+				this.bgOpacity = op;
+			}
+			return this.bgOpacity;
+		},
+
+		sizeBackground: function() {
+			if(this.bgOpacity > 0) {
+				var h = Math.max(
+					document.documentElement.scrollHeight || document.body.scrollHeight,
+					dojo.html.getViewportHeight());
+				var w = dojo.html.getViewportWidth();
+				this.bg.style.width = w + "px";
+				this.bg.style.height = h + "px";
+			}
+			this.bgIframe.onResized();
+		},
+
+		showBackground: function() {
+			this.sizeBackground();
+			if(this.bgOpacity > 0) {
+				this.bg.style.display = "block";
+			}
+		},
+
+		placeDialog: function() {
+			var scroll_offset = dojo.html.getScrollOffset();
+			var viewport_size = dojo.html.getViewportSize();
+
+			// find the size of the dialog
+			var w = dojo.style.getOuterWidth(this.containerNode);
+			var h = dojo.style.getOuterHeight(this.containerNode);
+
+			var x = scroll_offset[0] + (viewport_size[0] - w)/2;
+			var y = scroll_offset[1] + (viewport_size[1] - h)/2;
+
+			with(this.domNode.style) {
+				left = x + "px";
+				top = y + "px";
+			}
+		},
+
+		show: function() {
+			this.setBackgroundOpacity();
+			this.showBackground();
+
+			dojo.widget.html.Dialog.superclass.show.call(this);
+
+			// FIXME: moz doesn't generate onscroll events for mouse or key scrolling (wtf)
+			// we should create a fake event by polling the scrolltop/scrollleft every X ms.
+			// this smells like it should be a dojo feature rather than just for this widget.
+
+			if (this.followScroll && !this._scrollConnected){
+				this._scrollConnected = true;
+				dojo.event.connect(window, "onscroll", this, "onScroll");
+			}
+			
+			if(this.lifetime){
+				this.timeRemaining = this.lifetime;
+				if(!this.blockDuration){
+					dojo.event.connect(this.bg, "onclick", this, "hide");
+				}else{
+					dojo.event.disconnect(this.bg, "onclick", this, "hide");
+				}
+				if(this.timerNode){
+					this.timerNode.innerHTML = Math.ceil(this.timeRemaining/1000);
+				}
+				if(this.blockDuration && this.closeNode){
+					if(this.lifetime > this.blockDuration){
+						this.closeNode.style.visibility = "hidden";
+					}else{
+						this.closeNode.style.display = "none";
+					}
+				}
+				this.timer = setInterval(dojo.lang.hitch(this, "onTick"), 100);
+			}
+
+			this.checkSize();
+		},
+
+		onLoad: function(){
+			// when href is specified we need to reposition
+			// the dialog after the data is loaded
+			this.placeDialog();
+		},
+		
+		fillInTemplate: function(){
+			// dojo.event.connect(this.domNode, "onclick", this, "killEvent");
+		},
+
+		hide: function(){
+			// workaround for FF focus going into outer space
+			if (this.focusElement) { 
+				dojo.byId(this.focusElement).focus(); 
+				dojo.byId(this.focusElement).blur();
+			}
+			
+			if(this.timer){
+				clearInterval(this.timer);
+			}
+
+			this.bg.style.display = "none";
+			this.bg.style.width = this.bg.style.height = "1px";
+
+			dojo.widget.html.Dialog.superclass.hide.call(this);
+
+			if (this._scrollConnected){
+				this._scrollConnected = false;
+				dojo.event.disconnect(window, "onscroll", this, "onScroll");
+			}
+		},
+		
+		setTimerNode: function(node){
+			this.timerNode = node;
+		},
+
+		setCloseControl: function(node) {
+			this.closeNode = node;
+			dojo.event.connect(node, "onclick", this, "hide");
+		},
+
+		setShowControl: function(node) {
+			dojo.event.connect(node, "onclick", this, "show");
+		},
+		
+		onTick: function(){
+			if(this.timer){
+				this.timeRemaining -= 100;
+				if(this.lifetime - this.timeRemaining >= this.blockDuration){
+					dojo.event.connect(this.bg, "onclick", this, "hide");
+					if(this.closeNode){
+						this.closeNode.style.visibility = "visible";
+					}
+				}
+				if(!this.timeRemaining){
+					clearInterval(this.timer);
+					this.hide();
+				}else if(this.timerNode){
+					this.timerNode.innerHTML = Math.ceil(this.timeRemaining/1000);
+				}
+			}
+		},
+
+		onScroll: function(){
+			this.placeDialog();
+			this.domNode.style.display = "block";
+		},
+
+		// Called when the browser window's size is changed
+		checkSize: function() {
+			if(this.isShowing()){
+				this.sizeBackground();
+				this.placeDialog();
+				this.domNode.style.display="block";
+				this.onResized();
+			}
+		},
+		
+		killEvent: function(evt){
+			evt.preventDefault();
+			evt.stopPropagation();
+		}
+
+	}
+);

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/DomWidget.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/DomWidget.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/DomWidget.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/DomWidget.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,593 @@
+/*
+	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.widget.DomWidget");
+
+dojo.require("dojo.event.*");
+dojo.require("dojo.widget.Widget");
+dojo.require("dojo.dom");
+dojo.require("dojo.xml.Parse");
+dojo.require("dojo.uri.*");
+dojo.require("dojo.lang.func");
+dojo.require("dojo.lang.extras");
+
+dojo.widget._cssFiles = {};
+dojo.widget._cssStrings = {};
+dojo.widget._templateCache = {};
+
+dojo.widget.defaultStrings = {
+	dojoRoot: dojo.hostenv.getBaseScriptUri(),
+	baseScriptUri: dojo.hostenv.getBaseScriptUri()
+};
+
+dojo.widget.buildFromTemplate = function() {
+	dojo.lang.forward("fillFromTemplateCache");
+}
+
+// static method to build from a template w/ or w/o a real widget in place
+dojo.widget.fillFromTemplateCache = function(obj, templatePath, templateCssPath, templateString, avoidCache){
+	// dojo.debug("avoidCache:", avoidCache);
+	var tpath = templatePath || obj.templatePath;
+	var cpath = templateCssPath || obj.templateCssPath;
+
+	// DEPRECATED: use Uri objects, not strings
+	if (tpath && !(tpath instanceof dojo.uri.Uri)) {
+		tpath = dojo.uri.dojoUri(tpath);
+		dojo.deprecated("templatePath should be of type dojo.uri.Uri", null, "0.4");
+	}
+	if (cpath && !(cpath instanceof dojo.uri.Uri)) {
+		cpath = dojo.uri.dojoUri(cpath);
+		dojo.deprecated("templateCssPath should be of type dojo.uri.Uri", null, "0.4");
+	}
+	
+	var tmplts = dojo.widget._templateCache;
+	if(!obj["widgetType"]) { // don't have a real template here
+		do {
+			var dummyName = "__dummyTemplate__" + dojo.widget._templateCache.dummyCount++;
+		} while(tmplts[dummyName]);
+		obj.widgetType = dummyName;
+	}
+	var wt = obj.widgetType;
+
+	if(cpath && !dojo.widget._cssFiles[cpath.toString()]){
+		if((!obj.templateCssString)&&(cpath)){
+			obj.templateCssString = dojo.hostenv.getText(cpath);
+			obj.templateCssPath = null;
+		}
+		if((obj["templateCssString"])&&(!obj.templateCssString["loaded"])){
+			dojo.style.insertCssText(obj.templateCssString, null, cpath);
+			if(!obj.templateCssString){ obj.templateCssString = ""; }
+			obj.templateCssString.loaded = true;
+		}
+		dojo.widget._cssFiles[cpath.toString()] = true;
+	}
+
+	var ts = tmplts[wt];
+	if(!ts){
+		tmplts[wt] = { "string": null, "node": null };
+		if(avoidCache){
+			ts = {};
+		}else{
+			ts = tmplts[wt];
+		}
+	}
+	if((!obj.templateString)&&(!avoidCache)){
+		obj.templateString = templateString || ts["string"];
+	}
+	if((!obj.templateNode)&&(!avoidCache)){
+		obj.templateNode = ts["node"];
+	}
+	if((!obj.templateNode)&&(!obj.templateString)&&(tpath)){
+		// fetch a text fragment and assign it to templateString
+		// NOTE: we rely on blocking IO here!
+		var tstring = dojo.hostenv.getText(tpath);
+		if(tstring){
+			// strip <?xml ...?> declarations so that external SVG and XML
+			// documents can be added to a document without worry
+			tstring = tstring.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, "");
+			var matches = tstring.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
+			if(matches){
+				tstring = matches[1];
+			}
+		}else{
+			tstring = "";
+		}
+		obj.templateString = tstring;
+		if(!avoidCache){
+			tmplts[wt]["string"] = tstring;
+		}
+	}
+	if((!ts["string"])&&(!avoidCache)){
+		ts.string = obj.templateString;
+	}
+}
+dojo.widget._templateCache.dummyCount = 0;
+
+dojo.widget.attachProperties = ["dojoAttachPoint", "id"];
+dojo.widget.eventAttachProperty = "dojoAttachEvent";
+dojo.widget.onBuildProperty = "dojoOnBuild";
+dojo.widget.waiNames  = ["waiRole", "waiState"];
+dojo.widget.wai = {
+	waiRole: { 	name: "waiRole", 
+				namespace: "http://www.w3.org/TR/xhtml2", 
+				alias: "x2",
+				prefix: "wairole:",
+				nsName: "role"
+	},
+	waiState: { name: "waiState", 
+				namespace: "http://www.w3.org/2005/07/aaa" , 
+				alias: "aaa",
+				prefix: "",
+				nsName: "state"
+	},
+	setAttr: function(node, attr, value){
+		if(dojo.render.html.ie){
+			node.setAttribute(this[attr].alias+":"+this[attr].nsName, this[attr].prefix+value);
+		}else{
+			node.setAttributeNS(this[attr].namespace, this[attr].nsName, this[attr].prefix+value);
+		}
+	}
+};
+
+dojo.widget.attachTemplateNodes = function(rootNode, targetObj, events){
+	// FIXME: this method is still taking WAAAY too long. We need ways of optimizing:
+	//	a.) what we are looking for on each node
+	//	b.) the nodes that are subject to interrogation (use xpath instead?)
+	//	c.) how expensive event assignment is (less eval(), more connect())
+	// var start = new Date();
+	var elementNodeType = dojo.dom.ELEMENT_NODE;
+
+	function trim(str){
+		return str.replace(/^\s+|\s+$/g, "");
+	}
+
+	if(!rootNode){ 
+		rootNode = targetObj.domNode;
+	}
+
+	if(rootNode.nodeType != elementNodeType){
+		return;
+	}
+	// alert(events.length);
+
+	var nodes = rootNode.all || rootNode.getElementsByTagName("*");
+	var _this = targetObj;
+	for(var x=-1; x<nodes.length; x++){
+		var baseNode = (x == -1) ? rootNode : nodes[x];
+		// FIXME: is this going to have capitalization problems?  Could use getAttribute(name, 0); to get attributes case-insensitve
+		var attachPoint = [];
+		for(var y=0; y<this.attachProperties.length; y++){
+			var tmpAttachPoint = baseNode.getAttribute(this.attachProperties[y]);
+			if(tmpAttachPoint){
+				attachPoint = tmpAttachPoint.split(";");
+				for(var z=0; z<attachPoint.length; z++){
+					if(dojo.lang.isArray(targetObj[attachPoint[z]])){
+						targetObj[attachPoint[z]].push(baseNode);
+					}else{
+						targetObj[attachPoint[z]]=baseNode;
+					}
+				}
+				break;
+			}
+		}
+		// continue;
+
+		// FIXME: we need to put this into some kind of lookup structure
+		// instead of direct assignment
+		var tmpltPoint = baseNode.getAttribute(this.templateProperty);
+		if(tmpltPoint){
+			targetObj[tmpltPoint]=baseNode;
+		}
+
+		dojo.lang.forEach(dojo.widget.waiNames, function(name){
+			var wai = dojo.widget.wai[name];
+			var val = baseNode.getAttribute(wai.name);
+			if(val){
+				dojo.widget.wai.setAttr(baseNode, wai.name, val);
+			}
+		}, this);
+
+		var attachEvent = baseNode.getAttribute(this.eventAttachProperty);
+		if(attachEvent){
+			// NOTE: we want to support attributes that have the form
+			// "domEvent: nativeEvent; ..."
+			var evts = attachEvent.split(";");
+			for(var y=0; y<evts.length; y++){
+				if((!evts[y])||(!evts[y].length)){ continue; }
+				var thisFunc = null;
+				var tevt = trim(evts[y]);
+				if(evts[y].indexOf(":") >= 0){
+					// oh, if only JS had tuple assignment
+					var funcNameArr = tevt.split(":");
+					tevt = trim(funcNameArr[0]);
+					thisFunc = trim(funcNameArr[1]);
+				}
+				if(!thisFunc){
+					thisFunc = tevt;
+				}
+
+				var tf = function(){ 
+					var ntf = new String(thisFunc);
+					return function(evt){
+						if(_this[ntf]){
+							_this[ntf](dojo.event.browser.fixEvent(evt, this));
+						}
+					};
+				}();
+				dojo.event.browser.addListener(baseNode, tevt, tf, false, true);
+				// dojo.event.browser.addListener(baseNode, tevt, dojo.lang.hitch(_this, thisFunc));
+			}
+		}
+
+		for(var y=0; y<events.length; y++){
+			//alert(events[x]);
+			var evtVal = baseNode.getAttribute(events[y]);
+			if((evtVal)&&(evtVal.length)){
+				var thisFunc = null;
+				var domEvt = events[y].substr(4); // clober the "dojo" prefix
+				thisFunc = trim(evtVal);
+				var funcs = [thisFunc];
+				if(thisFunc.indexOf(";")>=0){
+					funcs = dojo.lang.map(thisFunc.split(";"), trim);
+				}
+				for(var z=0; z<funcs.length; z++){
+					if(!funcs[z].length){ continue; }
+					var tf = function(){ 
+						var ntf = new String(funcs[z]);
+						return function(evt){
+							if(_this[ntf]){
+								_this[ntf](dojo.event.browser.fixEvent(evt, this));
+							}
+						}
+					}();
+					dojo.event.browser.addListener(baseNode, domEvt, tf, false, true);
+					// dojo.event.browser.addListener(baseNode, domEvt, dojo.lang.hitch(_this, funcs[z]));
+				}
+			}
+		}
+
+		var onBuild = baseNode.getAttribute(this.onBuildProperty);
+		if(onBuild){
+			eval("var node = baseNode; var widget = targetObj; "+onBuild);
+		}
+	}
+
+}
+
+dojo.widget.getDojoEventsFromStr = function(str){
+	// var lstr = str.toLowerCase();
+	var re = /(dojoOn([a-z]+)(\s?))=/gi;
+	var evts = str ? str.match(re)||[] : [];
+	var ret = [];
+	var lem = {};
+	for(var x=0; x<evts.length; x++){
+		if(evts[x].legth < 1){ continue; }
+		var cm = evts[x].replace(/\s/, "");
+		cm = (cm.slice(0, cm.length-1));
+		if(!lem[cm]){
+			lem[cm] = true;
+			ret.push(cm);
+		}
+	}
+	return ret;
+}
+
+/*
+dojo.widget.buildAndAttachTemplate = function(obj, templatePath, templateCssPath, templateString, targetObj) {
+	this.buildFromTemplate(obj, templatePath, templateCssPath, templateString);
+	var node = dojo.dom.createNodesFromText(obj.templateString, true)[0];
+	this.attachTemplateNodes(node, targetObj||obj, dojo.widget.getDojoEventsFromStr(templateString));
+	return node;
+}
+*/
+
+dojo.declare("dojo.widget.DomWidget", dojo.widget.Widget, {
+	initializer: function() {
+		if((arguments.length>0)&&(typeof arguments[0] == "object")){
+			this.create(arguments[0]);
+		}
+	},
+								 
+	templateNode: null,
+	templateString: null,
+	templateCssString: null,
+	preventClobber: false,
+	domNode: null, // this is our visible representation of the widget!
+	containerNode: null, // holds child elements
+
+	// Process the given child widget, inserting it's dom node as a child of our dom node
+	// FIXME: should we support addition at an index in the children arr and
+	// order the display accordingly? Right now we always append.
+	addChild: function(widget, overrideContainerNode, pos, ref, insertIndex){
+		if(!this.isContainer){ // we aren't allowed to contain other widgets, it seems
+			dojo.debug("dojo.widget.DomWidget.addChild() attempted on non-container widget");
+			return null;
+		}else{
+			this.addWidgetAsDirectChild(widget, overrideContainerNode, pos, ref, insertIndex);
+			this.registerChild(widget, insertIndex);
+		}
+		return widget;
+	},
+	
+	addWidgetAsDirectChild: function(widget, overrideContainerNode, pos, ref, insertIndex){
+		if((!this.containerNode)&&(!overrideContainerNode)){
+			this.containerNode = this.domNode;
+		}
+		var cn = (overrideContainerNode) ? overrideContainerNode : this.containerNode;
+		if(!pos){ pos = "after"; }
+		if(!ref){ 
+			// if(!cn){ cn = document.body; }
+			if(!cn){ cn = document.body; }
+			ref = cn.lastChild; 
+		}
+		if(!insertIndex) { insertIndex = 0; }
+		widget.domNode.setAttribute("dojoinsertionindex", insertIndex);
+
+		// insert the child widget domNode directly underneath my domNode, in the
+		// specified position (by default, append to end)
+		if(!ref){
+			cn.appendChild(widget.domNode);
+		}else{
+			// FIXME: was this meant to be the (ugly hack) way to support insert @ index?
+			//dojo.dom[pos](widget.domNode, ref, insertIndex);
+
+			// CAL: this appears to be the intended way to insert a node at a given position...
+			if (pos == 'insertAtIndex'){
+				// dojo.debug("idx:", insertIndex, "isLast:", ref === cn.lastChild);
+				dojo.dom.insertAtIndex(widget.domNode, ref.parentNode, insertIndex);
+			}else{
+				// dojo.debug("pos:", pos, "isLast:", ref === cn.lastChild);
+				if((pos == "after")&&(ref === cn.lastChild)){
+					cn.appendChild(widget.domNode);
+				}else{
+					dojo.dom.insertAtPosition(widget.domNode, cn, pos);
+				}
+			}
+		}
+	},
+
+	// Record that given widget descends from me
+	registerChild: function(widget, insertionIndex){
+
+		// we need to insert the child at the right point in the parent's 
+		// 'children' array, based on the insertionIndex
+
+		widget.dojoInsertionIndex = insertionIndex;
+
+		var idx = -1;
+		for(var i=0; i<this.children.length; i++){
+			if (this.children[i].dojoInsertionIndex < insertionIndex){
+				idx = i;
+			}
+		}
+
+		this.children.splice(idx+1, 0, widget);
+
+		widget.parent = this;
+		widget.addedTo(this);
+		
+		// If this widget was created programatically, then it was erroneously added
+		// to dojo.widget.manager.topWidgets.  Fix that here.
+		delete dojo.widget.manager.topWidgets[widget.widgetId];
+	},
+
+	removeChild: function(widget){
+		// detach child domNode from parent domNode
+		dojo.dom.removeNode(widget.domNode);
+
+		// remove child widget from parent widget
+		return dojo.widget.DomWidget.superclass.removeChild.call(this, widget);
+	},
+
+	getFragNodeRef: function(frag){
+		if( !frag || !frag["dojo:"+this.widgetType.toLowerCase()] ){
+			dojo.raise("Error: no frag for widget type " + this.widgetType +
+				", id " + this.widgetId + " (maybe a widget has set it's type incorrectly)");
+		}
+		return (frag ? frag["dojo:"+this.widgetType.toLowerCase()]["nodeRef"] : null);
+	},
+	
+	// Replace source domNode with generated dom structure, and register
+	// widget with parent.
+	postInitialize: function(args, frag, parentComp){
+		var sourceNodeRef = this.getFragNodeRef(frag);
+		// Stick my generated dom into the output tree
+		//alert(this.widgetId + ": replacing " + sourceNodeRef + " with " + this.domNode.innerHTML);
+		if (parentComp && (parentComp.snarfChildDomOutput || !sourceNodeRef)){
+			// Add my generated dom as a direct child of my parent widget
+			// This is important for generated widgets, and also cases where I am generating an
+			// <li> node that can't be inserted back into the original DOM tree
+			parentComp.addWidgetAsDirectChild(this, "", "insertAtIndex", "",  args["dojoinsertionindex"], sourceNodeRef);
+		} else if (sourceNodeRef){
+			// Do in-place replacement of the my source node with my generated dom
+			if(this.domNode && (this.domNode !== sourceNodeRef)){
+				var oldNode = sourceNodeRef.parentNode.replaceChild(this.domNode, sourceNodeRef);
+			}
+		}
+
+		// Register myself with my parent, or with the widget manager if
+		// I have no parent
+		// TODO: the code below erroneously adds all programatically generated widgets
+		// to topWidgets (since we don't know who the parent is until after creation finishes)
+		if ( parentComp ) {
+			parentComp.registerChild(this, args.dojoinsertionindex);
+		} else {
+			dojo.widget.manager.topWidgets[this.widgetId]=this;
+		}
+
+		// Expand my children widgets
+		if(this.isContainer){
+			//alert("recurse from " + this.widgetId);
+			// build any sub-components with us as the parent
+			var fragParser = dojo.widget.getParser();
+			fragParser.createSubComponents(frag, this);
+		}
+	},
+
+	// method over-ride
+	buildRendering: function(args, frag){
+		// DOM widgets construct themselves from a template
+		var ts = dojo.widget._templateCache[this.widgetType];
+		if(	
+			(!this.preventClobber)&&(
+				(this.templatePath)||
+				(this.templateNode)||
+				(
+					(this["templateString"])&&(this.templateString.length) 
+				)||
+				(
+					(typeof ts != "undefined")&&( (ts["string"])||(ts["node"]) )
+				)
+			)
+		){
+			// if it looks like we can build the thing from a template, do it!
+			this.buildFromTemplate(args, frag);
+		}else{
+			// otherwise, assign the DOM node that was the source of the widget
+			// parsing to be the root node
+			this.domNode = this.getFragNodeRef(frag);
+		}
+		this.fillInTemplate(args, frag); 	// this is where individual widgets
+											// will handle population of data
+											// from properties, remote data
+											// sets, etc.
+	},
+
+	buildFromTemplate: function(args, frag){
+		// var start = new Date();
+		// copy template properties if they're already set in the templates object
+		// dojo.debug("buildFromTemplate:", this);
+		var avoidCache = false;
+		if(args["templatecsspath"]){
+			args["templateCssPath"] = args["templatecsspath"];
+		}
+		if(args["templatepath"]){
+			avoidCache = true;
+			args["templatePath"] = args["templatepath"];
+		}
+		dojo.widget.fillFromTemplateCache(	this, 
+											args["templatePath"], 
+											args["templateCssPath"],
+											null,
+											avoidCache);
+		var ts = dojo.widget._templateCache[this.widgetType];
+		if((ts)&&(!avoidCache)){
+			if(!this.templateString.length){
+				this.templateString = ts["string"];
+			}
+			if(!this.templateNode){
+				this.templateNode = ts["node"];
+			}
+		}
+		var matches = false;
+		var node = null;
+		// var tstr = new String(this.templateString); 
+		var tstr = this.templateString; 
+		// attempt to clone a template node, if there is one
+		if((!this.templateNode)&&(this.templateString)){
+			matches = this.templateString.match(/\$\{([^\}]+)\}/g);
+			if(matches) {
+				// if we do property replacement, don't create a templateNode
+				// to clone from.
+				var hash = this.strings || {};
+				// FIXME: should this hash of default replacements be cached in
+				// templateString?
+				for(var key in dojo.widget.defaultStrings) {
+					if(dojo.lang.isUndefined(hash[key])) {
+						hash[key] = dojo.widget.defaultStrings[key];
+					}
+				}
+				// FIXME: this is a lot of string munging. Can we make it faster?
+				for(var i = 0; i < matches.length; i++) {
+					var key = matches[i];
+					key = key.substring(2, key.length-1);
+					var kval = (key.substring(0, 5) == "this.") ? dojo.lang.getObjPathValue(key.substring(5), this) : hash[key];
+					var value;
+					if((kval)||(dojo.lang.isString(kval))){
+						value = (dojo.lang.isFunction(kval)) ? kval.call(this, key, this.templateString) : kval;
+						tstr = tstr.replace(matches[i], value);
+					}
+				}
+			}else{
+				// otherwise, we are required to instantiate a copy of the template
+				// string if one is provided.
+				
+				// FIXME: need to be able to distinguish here what should be done
+				// or provide a generic interface across all DOM implementations
+				// FIMXE: this breaks if the template has whitespace as its first 
+				// characters
+				// node = this.createNodesFromText(this.templateString, true);
+				// this.templateNode = node[0].cloneNode(true); // we're optimistic here
+				this.templateNode = this.createNodesFromText(this.templateString, true)[0];
+				if(!avoidCache){
+					ts.node = this.templateNode;
+				}
+			}
+		}
+		if((!this.templateNode)&&(!matches)){ 
+			dojo.debug("weren't able to create template!");
+			return false;
+		}else if(!matches){
+			node = this.templateNode.cloneNode(true);
+			if(!node){ return false; }
+		}else{
+			node = this.createNodesFromText(tstr, true)[0];
+		}
+
+		// recurse through the node, looking for, and attaching to, our
+		// attachment points which should be defined on the template node.
+
+		this.domNode = node;
+		// dojo.profile.start("attachTemplateNodes");
+		this.attachTemplateNodes(this.domNode, this);
+		// dojo.profile.end("attachTemplateNodes");
+		
+		// relocate source contents to templated container node
+		// this.containerNode must be able to receive children, or exceptions will be thrown
+		if (this.isContainer && this.containerNode){
+			var src = this.getFragNodeRef(frag);
+			if (src){
+				dojo.dom.moveChildren(src, this.containerNode);
+			}
+		}
+	},
+
+	attachTemplateNodes: function(baseNode, targetObj){
+		if(!targetObj){ targetObj = this; }
+		return dojo.widget.attachTemplateNodes(baseNode, targetObj, 
+					dojo.widget.getDojoEventsFromStr(this.templateString));
+	},
+
+	fillInTemplate: function(){
+		// dojo.unimplemented("dojo.widget.DomWidget.fillInTemplate");
+	},
+	
+	// method over-ride
+	destroyRendering: function(){
+		try{
+			delete this.domNode;
+		}catch(e){ /* squelch! */ }
+	},
+
+	// FIXME: method over-ride
+	cleanUp: function(){},
+	
+	getContainerHeight: function(){
+		dojo.unimplemented("dojo.widget.DomWidget.getContainerHeight");
+	},
+
+	getContainerWidth: function(){
+		dojo.unimplemented("dojo.widget.DomWidget.getContainerWidth");
+	},
+
+	createNodesFromText: function(){
+		dojo.unimplemented("dojo.widget.DomWidget.createNodesFromText");
+	}
+});

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