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

svn commit: r453979 [7/8] - in /tapestry/tapestry4/trunk/tapestry-framework/src/js: dojo/ dojo/src/ dojo/src/collections/ dojo/src/data/ dojo/src/data/csv/ dojo/src/date/ dojo/src/debug/ dojo/src/event/ dojo/src/gfx/ dojo/src/html/ dojo/src/i18n/ dojo/...

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/charting/engine/__package__.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/charting/engine/__package__.js?view=auto&rev=453979
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/charting/engine/__package__.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/charting/engine/__package__.js Sat Oct  7 11:22:33 2006
@@ -0,0 +1,11 @@
+/*
+	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.charting.engine.*");

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/charting/engine/svg/PlotArea.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/charting/engine/svg/PlotArea.js?view=auto&rev=453979
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/charting/engine/svg/PlotArea.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/charting/engine/svg/PlotArea.js Sat Oct  7 11:22:33 2006
@@ -0,0 +1,212 @@
+/*
+	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.charting.engine.svg.PlotArea");
+dojo.require("dojo.lang.common");
+dojo.require("dojo.svg");
+
+dojo.extend(dojo.widget.charting.engine.PlotArea, {
+	initializePlot: function(plot){
+		//	summary
+		//	Initialize the plot node for data rendering.
+		plot.destroy();
+		plot.dataNode = document.createElementNS(dojo.svg.xmlns.svg, "g");
+		plot.dataNode.setAttribute("id", plot.getId());
+		return plot.dataNode;	//	SVGElement
+	},
+	initializeAxis: function(axisObject){
+		//	summary
+		//	Initialize the passed axis descriptor.  Note that this should always
+		//	be the result of this.getAxes, and not the axis directly!
+		function createLabel(label, x, y, anchor){
+			var text = document.createElementNS(dojo.svg.xmlns.svg, "text");
+			text.setAttribute("x", x);
+			text.setAttribute("y", y);
+			text.setAttribute("style", "text-anchor:"+anchor+";font-size:"+textSize+"px;fill:#000;");
+			text.appendChild(document.createTextNode(label));
+			return text;
+		};
+
+		var area = this.getArea();
+		var stroke = 1;
+		var style = "stroke:#000;stroke-width:"+stroke+"px;";
+		var axis = axisObject.axis;
+		var textSize=10;
+
+		//	figure out the origin value.
+		if(isNaN(axis.origin)){
+			if(axis.origin.toLowerCase() == "max"){ 
+				axis.origin = axisObject.drawAgainst.range[(axisObject.plane=="y")?"upper":"lower"]; 
+			}
+			else if (axis.origin.toLowerCase() == "min"){ 
+				axis.origin = axisObject.drawAgainst.range[(axisObject.plane=="y")?"lower":"upper"]; 
+			}
+			else { axis.origin=0; }
+		}
+
+		//	get the origin plot point.
+		var coord = axisObject.drawAgainst.getCoord(axis.origin, this, axisObject.plot);
+		
+		var group = document.createElementNS(dojo.svg.xmlns.svg, "g");
+		group.setAttribute("id", axis.getId());	//	need a handle if we have to kill parts of the axis def.
+		var line = document.createElementNS(dojo.svg.xmlns.svg, "line");
+		if(axisObject.plane == "x"){
+			line.setAttribute("y1", coord);
+			line.setAttribute("y2", coord);
+			line.setAttribute("x1", area.left-stroke);
+			line.setAttribute("x2", area.right+stroke);
+			line.setAttribute("style", style);
+
+			//	set up the labels
+			if(axis.showLabels){
+				//	the way we treat nLabels is to include the min/max points of the axis.
+				//	always do the max point.
+				var y = coord+textSize+2;
+				var g = document.createElementNS(dojo.svg.xmlns.svg, "g");
+				g.setAttribute("id", axis.getId()+"-labels");
+				g.appendChild(createLabel(Math.round(axis.range.upper),(area.right-(textSize/2)),y, "middle"));
+				if(axis.nLabels > 1){
+					g.appendChild(createLabel(Math.round(axis.range.lower), area.left, y, "middle"));
+				}
+				var n = axis.nLabels-2;
+				if(n>0){
+					var length = area.right-area.left;
+					var step = length/(n+1);
+					var axisRange = axis.range.upper-axis.range.lower;
+					for(var i=1; i<=n; i++){
+						g.appendChild(createLabel(Math.round(axis.range.lower+(i*(axisRange/(n+1)))), area.left+(i*step), y, "middle"));
+						if(axis.showLines){
+							var l=document.createElementNS(dojo.svg.xmlns.svg, "line");
+							l.setAttribute("style","stroke:#999;stroke-width:0.5pt;stroke-dasharray:3,5;");
+							l.setAttribute("y1",area.top);
+							l.setAttribute("y2",area.bottom);
+							l.setAttribute("x1",area.left+(i*step));
+							l.setAttribute("x2",area.left+(i*step));
+							g.appendChild(l);
+						}
+						if(axis.showTicks){
+							var l=document.createElementNS(dojo.svg.xmlns.svg, "line");
+							l.setAttribute("style","stroke:#000;stroke-width:1pt;");
+							l.setAttribute("y1",coord);
+							l.setAttribute("y2",coord+3);
+							l.setAttribute("x1",area.left+(i*step));
+							l.setAttribute("x2",area.left+(i*step));
+							g.appendChild(l);
+						}
+					}
+				}
+				group.appendChild(g);
+			}
+		} else {
+			line.setAttribute("x1", coord);
+			line.setAttribute("x2", coord);
+			line.setAttribute("y1", area.top);
+			line.setAttribute("y2", area.bottom);
+			line.setAttribute("style", style);
+
+			//	set up the labels
+			if(axis.showLabels){
+				//	the way we treat nLabels is to include the min/max points of the axis.
+				//	always do the max point.
+				var isMax = axis.origin == axisObject.drawAgainst.range.upper;
+				var x = coord + (isMax?4:-4);
+				var anchor = isMax?"start":"end";
+				var g = document.createElementNS(dojo.svg.xmlns.svg, "g");
+				g.setAttribute("id", axis.getId()+"-labels");
+				g.appendChild(createLabel(Math.round(axis.range.upper), x, (area.top+(textSize/2)), anchor));
+				if(axis.nLabels > 1){
+					g.appendChild(createLabel(Math.round(axis.range.lower), x, area.bottom, anchor));
+				}
+				var n = axis.nLabels-2;
+				if(n>0){
+					var length = area.bottom-area.top;
+					var step = length/(n+1);
+					var axisRange = axis.range.upper-axis.range.lower;
+					for(var i=1; i<=n; i++){
+						g.appendChild(createLabel(Math.round(axis.range.upper-(i*(axisRange/(n+1)))), x, area.top+(i*step)+(textSize/2)-2, anchor));
+						if(axis.showLines){
+							var l=document.createElementNS(dojo.svg.xmlns.svg, "line");
+							l.setAttribute("style","stroke:#999;stroke-width:0.5pt;stroke-dasharray:3,5;");
+							l.setAttribute("y1",area.top+(i*step));
+							l.setAttribute("y2",area.top+(i*step));
+							l.setAttribute("x1",area.left);
+							l.setAttribute("x2",area.right);
+							g.appendChild(l);
+						}
+						if(axis.showTicks){
+							var l=document.createElementNS(dojo.svg.xmlns.svg, "line");
+							l.setAttribute("style","stroke:#999;stroke-width:1");
+							l.setAttribute("y1",area.top+(i*step));
+							l.setAttribute("y2",area.top+(i*step));
+							l.setAttribute("x1",coord-2);
+							l.setAttribute("x2",coord+2);
+							g.appendChild(l);
+						}
+					}
+				}
+				group.appendChild(g);
+			}
+		}
+		group.appendChild(line);
+		return group;
+	},
+
+	initialize: function(){
+		this.destroy();	//	kill everything first.
+		
+		//	start with the background
+		this.nodes.main = document.createElement("div");
+
+		this.nodes.area = document.createElementNS(dojo.svg.xmlns.svg, "svg");
+		this.nodes.area.setAttribute("id", this.getId());
+		this.nodes.area.setAttribute("width", this.size.width);
+		this.nodes.area.setAttribute("height", this.size.height);
+		this.nodes.main.appendChild(this.nodes.area);
+
+		var area=this.getArea();
+		var defs = document.createElementNS(dojo.svg.xmlns.svg, "defs");
+		var clip = document.createElementNS(dojo.svg.xmlns.svg, "clipPath");
+		clip.setAttribute("id",this.getId()+"-clip");
+		var rect = document.createElementNS(dojo.svg.xmlns.svg, "rect");		
+		rect.setAttribute("x", area.left);
+		rect.setAttribute("y", area.top);
+		rect.setAttribute("width", area.right-area.left);
+		rect.setAttribute("height", area.bottom-area.top);
+		clip.appendChild(rect);
+		defs.appendChild(clip);
+		this.nodes.area.appendChild(defs);
+		
+		this.nodes.background = document.createElementNS(dojo.svg.xmlns.svg, "rect");
+		this.nodes.background.setAttribute("id", this.getId()+"-background");
+		this.nodes.background.setAttribute("width", this.size.width);
+		this.nodes.background.setAttribute("height", this.size.height);
+		this.nodes.background.setAttribute("fill", "#fff");
+		this.nodes.area.appendChild(this.nodes.background);
+
+		this.nodes.plots = document.createElementNS(dojo.svg.xmlns.svg, "g");
+		this.nodes.plots.setAttribute("id", this.getId()+"-plots");
+		this.nodes.plots.setAttribute("style","clip-path:url(#"+this.getId()+"-clip);");
+		this.nodes.area.appendChild(this.nodes.plots);
+
+		for(var i=0; i<this.plots.length; i++){
+			this.nodes.plots.appendChild(this.initializePlot(this.plots[i]));
+		}
+
+		//	do the axes
+		this.nodes.axes = document.createElementNS(dojo.svg.xmlns.svg, "g");
+		this.nodes.axes.setAttribute("id", this.getId()+"-axes");
+		this.nodes.area.appendChild(this.nodes.axes);
+		var axes = this.getAxes();
+		for(var p in axes){
+			this.nodes.axes.appendChild(this.initializeAxis(axes[p]));
+		}
+		return this.nodes.main;
+	}
+});

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/charting/engine/svg/Plotters.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/charting/engine/svg/Plotters.js?view=auto&rev=453979
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/charting/engine/svg/Plotters.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/charting/engine/svg/Plotters.js Sat Oct  7 11:22:33 2006
@@ -0,0 +1,246 @@
+/*
+	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.charting.engine.svg.Plotters");
+dojo.require("dojo.lang.common");
+dojo.require("dojo.svg");
+
+dojo.require('dojo.json');
+
+//	Mixin the SVG-specific plotter object.
+dojo.mixin(dojo.widget.charting.engine.Plotters, {
+	/*********************************************************
+	 *	Grouped plotters: need all series on a plot at once.
+	 *********************************************************/
+	Bar: function(
+		/* dojo.widget.charting.engine.PlotArea */plotarea,
+		/* dojo.widget.charting.engine.Plot */plot,
+		/* object? */kwArgs,
+		/* function? */applyTo
+	){
+		var area = plotarea.getArea();
+		var group = document.createElementNS(dojo.svg.xmlns.svg, "g");
+		
+		//	calculate the width of each bar.
+		var space = 4;
+		var n = plot.series.length;
+		var width = ((area.right-area.left)-(space*(n-1)))/n;
+		var yOrigin = plot.axisY.getCoord(plot.axisX.origin, plotarea, plot);
+		for(var i=0; i<n; i++){
+			var series = plot.series[i];
+			var data = series.data.evaluate(kwArgs);
+			var x = area.left+(width*i)+(space*i);
+			var value = data[data.length-1].y;
+
+			var yA = yOrigin;
+			var y = plot.axisY.getCoord(value, plotarea, plot);
+			var h = Math.abs(yA-y);
+			if(value < plot.axisX.origin){
+				yA = y;
+				y = yOrigin;
+			}
+			
+			var bar=document.createElementNS(dojo.svg.xmlns.svg, "rect");
+			bar.setAttribute("fill", data[data.length-1].series.color);
+			bar.setAttribute("stroke-width", "0");
+			bar.setAttribute("x", x);
+			bar.setAttribute("y", y);
+			bar.setAttribute("width", width);
+			bar.setAttribute("height", h);
+			bar.setAttribute("fill-opacity", "0.65");
+			if(applyTo){ applyTo(bar, data[data.length-1].src); }
+			group.appendChild(bar);
+		}
+		return group;
+	},
+
+	/*********************************************************
+	 *	Single plotters: one series at a time.
+	 *********************************************************/
+	Line: function(
+		/* array */data, 
+		/* dojo.widget.charting.engine.PlotArea */plotarea,
+		/* dojo.widget.charting.engine.Plot */plot,
+		/* function? */applyTo
+	){
+		var tension = 3;
+		var area = plotarea.getArea();
+		var line = document.createElementNS(dojo.svg.xmlns.svg, "g");
+		var path = document.createElementNS(dojo.svg.xmlns.svg, "path");
+		line.appendChild(path);
+
+		path.setAttribute("fill", "none");
+		path.setAttribute("stroke", data[0].series.color);
+		path.setAttribute("stroke-width" , "2");
+		path.setAttribute("stroke-opacity", "0.85");
+		if(data[0].series.label != null){
+			path.setAttribute("title", data[0].series.label);
+		}
+
+		var cmd=[];
+		for(var i=0; i<data.length; i++){
+			var x = plot.axisX.getCoord(data[i].x, plotarea, plot);
+			var y = plot.axisY.getCoord(data[i].y, plotarea, plot);
+			var dx = area.left + 1;
+			var dy = area.bottom;
+			if(i>0){
+				dx = x - plot.axisX.getCoord(data[i-1].x, plotarea, plot);
+				dy = plot.axisY.getCoord(data[i-1].y, plotarea, plot);
+			}
+
+			if(i==0){ cmd.push("M"); }
+			else {
+				cmd.push("C");
+				var cx = x-(tension-1) * (dx/tension);
+				cmd.push(cx + "," + dy);
+				cx = x - (dx/tension);
+				cmd.push(cx + "," + y);
+			}
+			cmd.push(x+","+y);
+			
+			//	points on the line
+			var c=document.createElementNS(dojo.svg.xmlns.svg, "circle");
+			c.setAttribute("cx",x);
+			c.setAttribute("cy",y);
+			c.setAttribute("r","3");
+			c.setAttribute("fill", data[i].series.color);
+			c.setAttribute("fill-opacity", "0.65");
+			c.setAttribute("stroke-width", "1");
+			c.setAttribute("stroke-opacity", "0.85");
+			line.appendChild(c);
+			if(applyTo){ applyTo(c, data[i].src); }
+		}
+		path.setAttribute("d", cmd.join(" "));
+		return line;
+	},
+	Area: function(
+		/* array */data, 
+		/* dojo.widget.charting.engine.PlotArea */plotarea,
+		/* dojo.widget.charting.engine.Plot */plot,
+		/* function? */applyTo
+	){
+		var tension = 3;
+		var area = plotarea.getArea();
+		var line = document.createElementNS(dojo.svg.xmlns.svg, "g");
+		var path = document.createElementNS(dojo.svg.xmlns.svg, "path");
+		line.appendChild(path);
+
+		path.setAttribute("fill", data[0].series.color);
+		path.setAttribute("fill-opacity", "0.4");
+		path.setAttribute("stroke", data[0].series.color);
+		path.setAttribute("stroke-width" , "1");
+		path.setAttribute("stroke-opacity", "0.85");
+		if(data[0].series.label != null){
+			path.setAttribute("title", data[0].series.label);
+		}
+
+		var cmd=[];
+		for(var i=0; i<data.length; i++){
+			var x = plot.axisX.getCoord(data[i].x, plotarea, plot);
+			var y = plot.axisY.getCoord(data[i].y, plotarea, plot);
+			var dx = area.left + 1;
+			var dy = area.bottom;
+			if(i>0){
+				dx = x - plot.axisX.getCoord(data[i-1].x, plotarea, plot);
+				dy = plot.axisY.getCoord(data[i-1].y, plotarea, plot);
+			}
+
+			if(i==0){ cmd.push("M"); }
+			else {
+				cmd.push("C");
+				var cx = x-(tension-1) * (dx/tension);
+				cmd.push(cx + "," + dy);
+				cx = x - (dx/tension);
+				cmd.push(cx + "," + y);
+			}
+			cmd.push(x+","+y);
+			
+			//	points on the line
+			var c=document.createElementNS(dojo.svg.xmlns.svg, "circle");
+			c.setAttribute("cx",x);
+			c.setAttribute("cy",y);
+			c.setAttribute("r","3");
+			c.setAttribute("fill", data[i].series.color);
+			c.setAttribute("fill-opacity", "0.65");
+			c.setAttribute("stroke-width", "1");
+			c.setAttribute("stroke-opacity", "0.85");
+			line.appendChild(c);
+			if(applyTo){ applyTo(c, data[i].src); }
+		}
+		//	finish it off
+		cmd.push("L");
+		cmd.push(x + "," + plot.axisY.getCoord(plot.axisX.origin, plotarea, plot));
+		cmd.push("L");
+		cmd.push(plot.axisX.getCoord(data[0].x, plotarea, plot) + "," +  plot.axisY.getCoord(plot.axisX.origin, plotarea, plot));
+		cmd.push("Z");
+		path.setAttribute("d", cmd.join(" "));
+		return line;
+	},
+	Scatter: function(
+		/* array */data, 
+		/* dojo.widget.charting.engine.PlotArea */plotarea,
+		/* dojo.widget.charting.engine.Plot */plot,
+		/* function? */applyTo
+	){
+		var r=7;
+		var group = document.createElementNS(dojo.svg.xmlns.svg, "g");
+		for (var i=0; i<data.length; i++){
+			var x = plot.axisX.getCoord(data[i].x, plotarea, plot);
+			var y = plot.axisY.getCoord(data[i].y, plotarea, plot);
+			var point = document.createElementNS(dojo.svg.xmlns.svg, "path");
+			point.setAttribute("fill", data[i].series.color);
+			point.setAttribute("stroke-width", "0");
+			point.setAttribute("d",
+				"M " + x + "," + (y-r) + " " +
+				"Q " + x + "," + y + " " + (x+r) + "," + y + " " +
+				"Q " + x + "," + y + " " + x + "," + (y+r) + " " +
+				"Q " + x + "," + y + " " + (x-r) + "," + y + " " +
+				"Q " + x + "," + y + " " + x + "," + (y-r) + " " +
+				"Z"
+			);
+			if(applyTo){ applyTo(point, data[i].src); }
+			group.appendChild(point);
+		}
+		return group;
+	},
+	Bubble: function(
+		/* array */data, 
+		/* dojo.widget.charting.engine.PlotArea */plotarea,
+		/* dojo.widget.charting.engine.Plot */plot,
+		/* function? */applyTo
+	){
+		//	we will expect an additional binding to "size" here.  And it will be raw, no factors.
+		var group = document.createElementNS(dojo.svg.xmlns.svg, "g");
+		var sizeFactor=1;
+		for (var i=0; i<data.length; i++){
+			var x = plot.axisX.getCoord(data[i].x, plotarea, plot);
+			var y = plot.axisY.getCoord(data[i].y, plotarea, plot);
+			if(i==0){
+				//	figure out the size factor, start with the axis with the greater range.
+				var raw = data[i].size;
+				var dy = plot.axisY.getCoord(data[i].y + raw, plotarea, plot)-y;
+				sizeFactor = dy/raw;
+			}
+			if(sizeFactor<1) { sizeFactor = 1; }
+			var point = document.createElementNS(dojo.svg.xmlns.svg, "circle");
+			point.setAttribute("fill", data[i].series.color);
+			point.setAttribute("fill-opacity", "0.8");
+			point.setAttribute("stroke", data[i].series.color);
+			point.setAttribute("stroke-width", "1");
+			point.setAttribute("cx",x);
+			point.setAttribute("cy",y);
+			point.setAttribute("r", (data[i].size/2)*sizeFactor);
+			if(applyTo){ applyTo(point, data[i].src); }
+			group.appendChild(point);
+		}
+		return group;
+	}
+});
+dojo.widget.charting.engine.Plotters["Default"] = dojo.widget.charting.engine.Plotters.Line;

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/charting/engine/vml/PlotArea.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/charting/engine/vml/PlotArea.js?view=auto&rev=453979
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/charting/engine/vml/PlotArea.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/charting/engine/vml/PlotArea.js Sat Oct  7 11:22:33 2006
@@ -0,0 +1,255 @@
+/*
+	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.charting.engine.vml.PlotArea");
+dojo.require("dojo.lang.common");
+
+dojo.extend(dojo.widget.charting.engine.PlotArea, {
+	initializePlot: function(plot){
+		//	summary
+		//	Initialize the plot node for data rendering.
+		plot.destroy();
+		plot.dataNode = document.createElement("div");
+		plot.dataNode.id  = plot.getId();
+		return plot.dataNode;	//	HTMLElement
+	},
+	initializeAxis: function(axisObject){
+		function createLabel(label, x, y, anchor){
+			var text = document.createElement("div");
+			var s=text.style;
+			text.innerHTML=label;
+			s.fontSize=textSize+"px";
+			s.fontFamily="sans-serif";
+			s.position="absolute";
+			s.top = y+"px";
+			if(anchor == "center"){
+				s.left = x + "px";
+				s.textAlign="center";
+			} else if (anchor == "left"){
+				s.left = x + "px";
+				s.textAlign="left";
+			} else if (anchor == "right"){
+				s.right = x + "px";
+				s.textAlign="right";
+			}
+			return text;
+		}
+
+		var area = this.getArea();
+		var axis = axisObject.axis;
+		var stroke = 1;
+		var textSize=10;
+
+		//	figure out the origin value.
+		if(isNaN(axis.origin)){
+			if(axis.origin.toLowerCase() == "max"){ 
+				axis.origin = axisObject.drawAgainst.range[(axisObject.plane=="y")?"upper":"lower"]; 
+			}
+			else if (axis.origin.toLowerCase() == "min"){ 
+				axis.origin = axisObject.drawAgainst.range[(axisObject.plane=="y")?"lower":"upper"]; 
+			}
+			else { axis.origin=0; }
+		}
+
+		//	get the origin plot point.
+		var coord = axisObject.drawAgainst.getCoord(axis.origin, this, axisObject.plot);
+		
+		var group = document.createElement("div");
+		group.id = axis.getId();	//	need a handle if we have to kill parts of the axis def.
+		var line = document.createElement("v:line");
+		if(axisObject.plane == "x"){
+			line.setAttribute("from", area.left+"px,"+coord+"px");
+			line.setAttribute("to", area.right+"px,"+coord+"px");
+			line.setAttribute("strokecolor", "#000");
+			line.setAttribute("strokeweight", stroke+"px");
+			var s=line.style;
+			s.position="absolute";
+			s.top="0px";
+			s.left="0px";
+			s.antialias="false";
+
+			//	set up the labels
+			if(axis.showLabels){
+				//	the way we treat nLabels is to include the min/max points of the axis.
+				//	always do the max point.
+				var y = coord + Math.floor(textSize/2);
+				var g = document.createElement("div");
+				g.setAttribute("id", axis.getId()+"-labels");
+				g.appendChild(createLabel(Math.round(axis.range.upper), area.right - textSize, y, "center"));
+				if(axis.nLabels > 1){
+					g.appendChild(createLabel(Math.round(axis.range.lower), area.left, y, "center"));
+				}
+				var n = axis.nLabels-2;
+				if(n>0){
+					var length = area.right-area.left;
+					var step = length/(n+1);
+					var axisRange = axis.range.upper-axis.range.lower;
+					for(var i=1; i<=n; i++){
+						var lb=Math.round(axis.range.lower+(i*(axisRange/(n+1))))+"";
+						g.appendChild(createLabel(lb, area.left+(i*step)-Math.floor(textSize/2), y, "center"));
+						if(axis.showLines){
+							var l=document.createElement("v:line");
+							var str=document.createElement("v:stroke");
+							str.dashstyle="dot";
+							l.appendChild(str);
+							l.setAttribute("from", (area.left+(i*step))+"px,"+area.top+"px");
+							l.setAttribute("to", (area.left+(i*step))+"px,"+area.bottom+"px");
+							l.setAttribute("strokecolor", "#666");
+							l.setAttribute("strokeweight", stroke+"px");
+							var s=line.style;
+							s.position="absolute";
+							s.top="0px";
+							s.left="0px";
+							s.antialias="false";
+							g.appendChild(l);
+						}
+						if(axis.showTicks){
+							var l=document.createElement("v:line");
+							l.setAttribute("from", (area.left+(i*step))+"px,"+coord+"px");
+							l.setAttribute("to", (area.left+(i*step))+"px,"+(coord+3)+"px");
+							l.setAttribute("strokecolor", "#000");
+							l.setAttribute("strokeweight", stroke+"px");
+							var s=line.style;
+							s.position="absolute";
+							s.top="0px";
+							s.left="0px";
+							s.antialias="false";
+							g.appendChild(l);
+						}
+					}
+				}
+				group.appendChild(g);
+			}
+		} else {
+			line.setAttribute("from", coord+"px,"+area.top+"px");
+			line.setAttribute("to", coord+"px,"+area.bottom+"px");
+			line.setAttribute("strokecolor", "#000");
+			line.setAttribute("strokeweight", stroke+"px");
+			var s=line.style;
+			s.position="absolute";
+			s.top="0px";
+			s.left="0px";
+			s.antialias="false";
+			
+			//	set up the labels
+			if(axis.showLabels){
+				//	the way we treat nLabels is to include the min/max points of the axis.
+				//	always do the max point.
+				var isMax = axis.origin == axisObject.drawAgainst.range.upper;
+				var x = coord+4;
+				var anchor = "left";
+				if(!isMax){
+					x = area.right-coord+textSize+2;
+					if(coord == area.left) x+=textSize*2;
+					anchor="right";
+				}
+				var g = document.createElement("div");
+				g.setAttribute("id", axis.getId()+"-labels");
+				g.appendChild(createLabel(Math.round(axis.range.upper), x, (area.top-(textSize/2)), anchor));
+				if(axis.nLabels > 1){
+					g.appendChild(createLabel(Math.round(axis.range.lower), x, (area.bottom-textSize), anchor));
+				}
+				var n = axis.nLabels-2;
+				if(n>0){
+					var length = area.bottom-area.top;
+					var step = length/(n+1);
+					var axisRange = axis.range.upper-axis.range.lower;
+					for(var i=1; i<=n; i++){
+						var lb = Math.round(axis.range.upper-(i*(axisRange/(n+1))));
+						g.appendChild(createLabel(lb, x, area.top+(i*step)-Math.ceil(textSize/2), anchor));
+						if(axis.showLines){
+							var l=document.createElement("v:line");
+							var str=document.createElement("v:stroke");
+							str.dashstyle="dot";
+							l.appendChild(str);
+							l.setAttribute("from", area.left+"px,"+(area.top+(i*step))+"px");
+							l.setAttribute("to", area.right+"px,"+(area.top+(i*step))+"px");
+							l.setAttribute("strokecolor", "#666");
+							l.setAttribute("strokeweight", stroke+"px");
+							var s=line.style;
+							s.position="absolute";
+							s.top="0px";
+							s.left="0px";
+							s.antialias="false";
+							g.appendChild(l);
+						}
+						if(axis.showTicks){
+							var l=document.createElement("v:line");
+							l.setAttribute("from", (coord-2)+"px,"+(area.top+(i*step))+"px");
+							l.setAttribute("to", (coord+2)+"px,"+(area.top+(i*step))+"px");
+							l.setAttribute("strokecolor", "#000");
+							l.setAttribute("strokeweight", stroke+"px");
+							var s=line.style;
+							s.position="absolute";
+							s.top="0px";
+							s.left="0px";
+							s.antialias="false";
+							g.appendChild(l);
+						}
+					}
+				}
+				group.appendChild(g);
+			}
+		}
+		group.appendChild(line);
+		return group;
+	},
+	initialize:function(){
+		this.destroy();	//	kill everything first.
+		var main = this.nodes.main = document.createElement("div");
+		
+		//	start with the background
+		var area = this.nodes.area = document.createElement("div");
+		area.id = this.getId();
+		area.style.width=this.size.width+"px";
+		area.style.height=this.size.height+"px";
+		area.style.position="absolute";
+		main.appendChild(area);
+	
+		var bg = this.nodes.background = document.createElement("div");
+		bg.id = this.getId()+"-background";
+		bg.style.width=this.size.width+"px";
+		bg.style.height=this.size.height+"px";
+		bg.style.position="absolute";
+		bg.style.top="0px";
+		bg.style.left="0px";
+		bg.style.backgroundColor="#fff";
+		area.appendChild(bg);
+
+		//	the plot group
+		var a=this.getArea();
+		var plots = this.nodes.plots = document.createElement("div");
+		plots.id = this.getId()+"-plots";
+		plots.style.width=this.size.width+"px";
+		plots.style.height=this.size.height+"px";
+		plots.style.position="absolute";
+		plots.style.top="0px";
+		plots.style.left="0px";
+		plots.style.clip="rect("
+			+ a.top+" "
+			+ a.right+" "
+			+ a.bottom+" "
+			+ a.left
+			+")";
+		area.appendChild(plots);
+		for(var i=0; i<this.plots.length; i++){
+			plots.appendChild(this.initializePlot(this.plots[i]));
+		}
+
+		var axes = this.nodes.axes = document.createElement("div");
+		axes.id = this.getId() + "-axes";
+		area.appendChild(axes);
+		var ax = this.getAxes();
+		for(var p in ax){
+			axes.appendChild(this.initializeAxis(ax[p]));
+		}
+		return main;
+	}
+});

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/charting/engine/vml/Plotters.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/charting/engine/vml/Plotters.js?view=auto&rev=453979
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/charting/engine/vml/Plotters.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/charting/engine/vml/Plotters.js Sat Oct  7 11:22:33 2006
@@ -0,0 +1,318 @@
+/*
+	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.charting.engine.vml.Plotters");
+dojo.require("dojo.lang.common");
+
+dojo.mixin(dojo.widget.charting.engine.Plotters, {
+	/*********************************************************
+	 *	Grouped plotters: need all series on a plot at once.
+	 *********************************************************/
+	Bar: function(
+		/* dojo.widget.charting.engine.PlotArea */plotarea,
+		/* dojo.widget.charting.engine.Plot */plot,
+		/* object? */kwArgs,
+		/* function? */applyTo
+	){
+		var area = plotarea.getArea();
+		var group = document.createElement("div");
+		group.style.position="absolute";
+		group.style.top="0px";
+		group.style.left="0px";
+		group.style.width=plotarea.size.width+"px";
+		group.style.height=plotarea.size.height+"px";
+		
+		//	calculate the width of each bar.
+		var space = 4;
+		var n = plot.series.length;
+		var width = Math.round(((area.right-area.left)-(space*(n-1)))/n);
+		var yOrigin = plot.axisY.getCoord(plot.axisX.origin, plotarea, plot);
+		for(var i=0; i<n; i++){
+			var series = plot.series[i];
+			var data = series.data.evaluate(kwArgs);
+			var x = area.left+(width*i)+(space*i);
+			var value = data[data.length-1].y;
+
+			var yA = yOrigin;
+			var y = plot.axisY.getCoord(value, plotarea, plot);
+			var h = Math.abs(yA-y);
+			if(value < plot.axisX.origin){
+				yA = y;
+				y = yOrigin;
+			}
+			
+			var bar=document.createElement("v:rect");
+			bar.style.position="absolute";
+			bar.style.top=y+1+"px";
+			bar.style.left=x+"px";
+			bar.style.width=width+"px";
+			bar.style.height=h+"px";
+			bar.setAttribute("fillColor", data[data.length-1].series.color);
+			bar.setAttribute("stroked", "false");
+			bar.style.antialias="false";
+			var fill=document.createElement("v:fill");
+			fill.setAttribute("opacity", "0.65");
+			bar.appendChild(fill);
+			group.appendChild(bar);
+		}
+		return group;
+	},
+
+	/*********************************************************
+	 *	Single plotters: one series at a time.
+	 *********************************************************/
+	Line: function(
+		/* array */data, 
+		/* dojo.widget.charting.engine.PlotArea */plotarea,
+		/* dojo.widget.charting.engine.Plot */plot,
+		/* function? */applyTo
+	){
+		var tension = 3;
+		var area = plotarea.getArea();
+		var group=document.createElement("div");
+		group.style.position="absolute";
+		group.style.top="0px";
+		group.style.left="0px";
+		group.style.width=plotarea.size.width+"px";
+		group.style.height=plotarea.size.height+"px";
+
+		var path=document.createElement("v:shape");
+		path.setAttribute("strokeweight", "2px");
+		path.setAttribute("strokecolor", data[0].series.color);
+		path.setAttribute("fillcolor", "none");
+		path.setAttribute("filled", "false");
+		path.setAttribute("coordsize", (area.right-area.left) + "," + (area.bottom-area.top));
+		path.style.position="absolute";
+		path.style.top="0px";
+		path.style.left="0px";
+		path.style.width=area.right-area.left+"px";
+		path.style.height=area.bottom-area.top+"px";
+		var stroke=document.createElement("v:stroke");
+		stroke.setAttribute("opacity", "0.8");
+		path.appendChild(stroke);
+
+		var cmd = [];
+		var r=3;
+		for(var i=0; i<data.length; i++){
+			var x = Math.round(plot.axisX.getCoord(data[i].x, plotarea, plot));
+			var y = Math.round(plot.axisY.getCoord(data[i].y, plotarea, plot));
+
+			if (i==0){
+				cmd.push("m");
+				cmd.push(x+","+y);
+			}else{
+				var lastx = Math.round(plot.axisX.getCoord(data[i-1].x, plotarea, plot));
+				var lasty = Math.round(plot.axisY.getCoord(data[i-1].y, plotarea, plot));
+				var dx=x-lastx;
+				var dy=y-lasty;
+				
+				cmd.push("c");
+				var cx=Math.round((x-(tension-1)*(dx/tension)));
+				cmd.push(cx+","+lasty);
+				cx=Math.round((x-(dx/tension)));
+				cmd.push(cx+","+y);
+				cmd.push(x+","+y);
+			}
+
+			//	add the circle.
+			var c = document.createElement("v:oval");
+			c.setAttribute("strokeweight", "1px");
+			c.setAttribute("strokecolor", data[i].series.color);
+			c.setAttribute("fillcolor", data[i].series.color);
+			var str=document.createElement("v:stroke");
+			str.setAttribute("opacity","0.8");
+			c.appendChild(str);
+			str=document.createElement("v:fill");
+			str.setAttribute("opacity","0.6");
+			c.appendChild(str);
+			var s=c.style;
+			s.position="absolute";
+			s.top=(y-r)+"px";
+			s.left=(x-r)+"px";
+			s.width=(r*2)+"px";
+			s.height=(r*2)+"px";
+			group.appendChild(c);
+			if(applyTo){ applyTo(c, data[i].src); }
+		}
+		path.setAttribute("path", cmd.join(" ")+" e");
+		group.appendChild(path);
+		return group;
+	},
+	Area: function(
+		/* array */data, 
+		/* dojo.widget.charting.engine.PlotArea */plotarea,
+		/* dojo.widget.charting.engine.Plot */plot,
+		/* function? */applyTo
+	){
+		var tension = 3;
+		var area = plotarea.getArea();
+		var group=document.createElement("div");
+		group.style.position="absolute";
+		group.style.top="0px";
+		group.style.left="0px";
+		group.style.width=plotarea.size.width+"px";
+		group.style.height=plotarea.size.height+"px";
+
+		var path=document.createElement("v:shape");
+		path.setAttribute("strokeweight", "1px");
+		path.setAttribute("strokecolor", data[0].series.color);
+		path.setAttribute("fillcolor", data[0].series.color);
+		path.setAttribute("coordsize", (area.right-area.left) + "," + (area.bottom-area.top));
+		path.style.position="absolute";
+		path.style.top="0px";
+		path.style.left="0px";
+		path.style.width=area.right-area.left+"px";
+		path.style.height=area.bottom-area.top+"px";
+		var stroke=document.createElement("v:stroke");
+		stroke.setAttribute("opacity", "0.8");
+		path.appendChild(stroke);
+		var fill=document.createElement("v:fill");
+		fill.setAttribute("opacity", "0.4");
+		path.appendChild(fill);
+
+		var cmd = [];
+		var r=3;
+		for(var i=0; i<data.length; i++){
+			var x = Math.round(plot.axisX.getCoord(data[i].x, plotarea, plot));
+			var y = Math.round(plot.axisY.getCoord(data[i].y, plotarea, plot));
+
+			if (i==0){
+				cmd.push("m");
+				cmd.push(x+","+y);
+			}else{
+				var lastx = Math.round(plot.axisX.getCoord(data[i-1].x, plotarea, plot));
+				var lasty = Math.round(plot.axisY.getCoord(data[i-1].y, plotarea, plot));
+				var dx=x-lastx;
+				var dy=y-lasty;
+				
+				cmd.push("c");
+				var cx=Math.round((x-(tension-1)*(dx/tension)));
+				cmd.push(cx+","+lasty);
+				cx=Math.round((x-(dx/tension)));
+				cmd.push(cx+","+y);
+				cmd.push(x+","+y);
+			}
+
+			//	add the circle.
+			var c = document.createElement("v:oval");
+			c.setAttribute("strokeweight", "1px");
+			c.setAttribute("strokecolor", data[i].series.color);
+			c.setAttribute("fillcolor", data[i].series.color);
+			var str=document.createElement("v:stroke");
+			str.setAttribute("opacity","0.8");
+			c.appendChild(str);
+			str=document.createElement("v:fill");
+			str.setAttribute("opacity","0.6");
+			c.appendChild(str);
+			var s=c.style;
+			s.position="absolute";
+			s.top=(y-r)+"px";
+			s.left=(x-r)+"px";
+			s.width=(r*2)+"px";
+			s.height=(r*2)+"px";
+			group.appendChild(c);
+			if(applyTo){ applyTo(c, data[i].src); }
+		}
+		cmd.push("l");
+		cmd.push(x + "," + Math.round(plot.axisY.getCoord(plot.axisX.origin, plotarea, plot)));
+		cmd.push("l");
+		cmd.push(Math.round(plot.axisX.getCoord(data[0].x, plotarea, plot)) + "," +  Math.round(plot.axisY.getCoord(plot.axisX.origin, plotarea, plot)));
+		path.setAttribute("path", cmd.join(" ")+" e");
+		group.appendChild(path);
+		return group;
+	},
+	Scatter: function(
+		/* array */data, 
+		/* dojo.widget.charting.engine.PlotArea */plotarea,
+		/* dojo.widget.charting.engine.Plot */plot,
+		/* function? */applyTo
+	){
+		var r=6;
+		var mod=r/2;
+
+		var area = plotarea.getArea();
+		var group=document.createElement("div");
+		group.style.position="absolute";
+		group.style.top="0px";
+		group.style.left="0px";
+		group.style.width=plotarea.size.width+"px";
+		group.style.height=plotarea.size.height+"px";
+
+		for(var i=0; i<data.length; i++){
+			var x = Math.round(plot.axisX.getCoord(data[i].x, plotarea, plot));
+			var y = Math.round(plot.axisY.getCoord(data[i].y, plotarea, plot));
+
+			var point = document.createElement("v:rect");
+			point.setAttribute("strokecolor", data[i].series.color);
+			point.setAttribute("fillcolor", data[i].series.color);
+			var fill=document.createElement("v:fill");
+			fill.setAttribute("opacity","0.6");
+			point.appendChild(fill);
+
+			var s=point.style;
+			s.position="absolute";
+			s.rotation="45";
+			s.top=(y-mod)+"px";
+			s.left=(x-mod)+"px";
+			s.width=r+"px";
+			s.height=r+"px";
+			group.appendChild(point);
+			if(applyTo){ applyTo(point, data[i].src); }
+		}
+		return group;
+	},
+	Bubble: function(
+		/* array */data, 
+		/* dojo.widget.charting.engine.PlotArea */plotarea,
+		/* dojo.widget.charting.engine.Plot */plot,
+		/* function? */applyTo
+	){
+		var sizeFactor=1;
+		var area = plotarea.getArea();
+		var group=document.createElement("div");
+		group.style.position="absolute";
+		group.style.top="0px";
+		group.style.left="0px";
+		group.style.width=plotarea.size.width+"px";
+		group.style.height=plotarea.size.height+"px";
+
+		for(var i=0; i<data.length; i++){
+			var x = Math.round(plot.axisX.getCoord(data[i].x, plotarea, plot));
+			var y = Math.round(plot.axisY.getCoord(data[i].y, plotarea, plot));
+			if(i==0){
+				//	figure out the size factor, start with the axis with the greater range.
+				var raw = data[i].size;
+				var dy = plot.axisY.getCoord(data[i].y + raw, plotarea, plot)-y;
+				sizeFactor = dy/raw;
+			}
+			if(sizeFactor<1) { sizeFactor = 1; }
+			var r = (data[i].size/2)*sizeFactor;
+
+			var point = document.createElement("v:oval");
+			point.setAttribute("strokecolor", data[i].series.color);
+			point.setAttribute("fillcolor", data[i].series.color);
+			var fill=document.createElement("v:fill");
+			fill.setAttribute("opacity","0.6");
+			point.appendChild(fill);
+
+			var s=point.style;
+			s.position="absolute";
+			s.rotation="45";
+			s.top=(y-r)+"px";
+			s.left=(x-r)+"px";
+			s.width=(r*2)+"px";
+			s.height=(r*2)+"px";
+			group.appendChild(point);
+			if(applyTo){ applyTo(point, data[i].src); }
+		}
+		return group;
+	}
+});
+dojo.widget.charting.engine.Plotters["Default"] = dojo.widget.charting.engine.Plotters.Line;

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/svg/Chart.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/svg/Chart.js?view=diff&rev=453979&r1=453978&r2=453979
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/svg/Chart.js (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/svg/Chart.js Sat Oct  7 11:22:33 2006
@@ -23,6 +23,8 @@
 	"dojo.widget.svg.Chart",
 	[dojo.widget.HtmlWidget, dojo.widget.Chart],
 	function(){
+		//	summary
+		//	initializes the SVG version of Chart.
 		this.templatePath=null;
 		this.templateCssPath=null;
 		this._isInitialize=false;
@@ -127,7 +129,8 @@
 			return { rangeX:bRangeX, rangeY:bRangeY };
 		},
 		setAxesPlot:function(/* HTMLElement */table){
-			//	where to plot the axes
+			//	summary
+			//	figure out where to plot the axes
 			if (table.getAttribute("axisAt")){
 				var p=table.getAttribute("axisAt");
 				if (p.indexOf(",")>-1) p=p.split(",");
@@ -156,7 +159,8 @@
 			}
 		},
 		drawVectorNode:function(){
-			// ok, lets create the chart itself.
+			//	summary
+			//	Draws the main canvas for the chart
 			dojo.svg.g.suspend();		
 			if(this.vectorNode) this.destroy();
 			this.vectorNode=document.createElementNS(dojo.svg.xmlns.svg, "svg");
@@ -165,7 +169,8 @@
 			dojo.svg.g.resume();
 		},
 		drawPlotArea:function(){
-			//	set up the clip path for the plot area.
+			//	summary
+			//	Draws the plot area for the chart
 			dojo.svg.g.suspend();		
 			if(this.plotArea){
 				this.plotArea.parentNode.removeChild(this.plotArea);
@@ -196,7 +201,8 @@
 			dojo.svg.g.resume();
 		},
 		drawDataGroup:function(){
-			//	data group
+			//	summary
+			//	Draws the data group for the chart
 			dojo.svg.g.suspend();		
 			if(this.dataGroup){
 				this.dataGroup.parentNode.removeChild(this.dataGroup);
@@ -208,6 +214,8 @@
 			dojo.svg.g.resume();
 		},
 		drawAxes:function(){
+			//	summary
+			//	Draws the axes for the chart
 			dojo.svg.g.suspend();		
 			if(this.axisGroup){
 				this.axisGroup.parentNode.removeChild(this.axisGroup);
@@ -273,7 +281,8 @@
 		},
 
 		init:function(){
-			//	get the width and the height.
+			//	summary
+			//	Initialize the chart
 			if(!this.properties.width || !this.properties.height){
 				var box=dojo.html.getContentBox(this.domNode);
 				if(!this.properties.width){
@@ -296,12 +305,16 @@
 			this._isInitialized=true;
 		},
 		destroy:function(){
+			//	summary
+			//	Node cleanup
 			while(this.domNode.childNodes.length>0){
 				this.domNode.removeChild(this.domNode.childNodes.item(0));
 			}
 			this.vectorNode=this.plotArea=this.dataGroup=this.axisGroup=null;
 		},
 		render:function(){
+			//	summary
+			//	Draws the data on the chart
 			dojo.svg.g.suspend();
 			
 			if (this.dataGroup){
@@ -319,7 +332,8 @@
 			dojo.svg.g.resume();
 		},
 		postCreate:function(){
-			//	begin by grabbing the table, and reading it in.
+			//	summary
+			//	Parse any data if included with the chart, and kick off the rendering.
 			var table=this.domNode.getElementsByTagName("table")[0];
 			if (table){
 				var ranges=this.parseProperties(table);
@@ -347,11 +361,15 @@
 );
 
 dojo.widget.svg.Chart.Plotter=new function(){
+	//	summary
+	//	Singleton for plotting series of data.
 	var self=this;
 	var plotters = {};
 	var types=dojo.widget.Chart.PlotTypes;
 	
-	this.getX=function(value, chart){
+	this.getX=function(/* string||number */value, /* dojo.widget.Chart */chart){
+		//	summary
+		//	Calculate the x coord on the passed chart for the passed value
 		var v=parseFloat(value);
 		var min=chart.properties.axes.x.range.min;
 		var max=chart.properties.axes.x.range.max;
@@ -361,9 +379,11 @@
 		var xmin=chart.properties.padding.left;
 		var xmax=chart.properties.width-chart.properties.padding.right;
 		var x=(v*((xmax-xmin)/max))+xmin;
-		return x;
+		return x;	// float
 	};
-	this.getY=function(value, chart){
+	this.getY=function(/* string||number */value, /* dojo.widget.Chart */chart){
+		//	summary
+		//	Calculate the y coord on the passed chart for the passed value
 		var v=parseFloat(value);
 		var max=chart.properties.axes.y.range.max;
 		var min=chart.properties.axes.y.range.min;
@@ -374,24 +394,30 @@
 		var ymin=chart.properties.height-chart.properties.padding.bottom;
 		var ymax=chart.properties.padding.top;
 		var y=(((ymin-ymax)/(max-min))*(max-v))+ymax;
-		return y;
+		return y;	// float
 	};
 
-	this.addPlotter=function(name, func){
+	this.addPlotter=function(/* string */name, /* function */func){
+		//	summary
+		//	add a custom plotter function to this object.
 		plotters[name]=func;
 	};
-	this.plot=function(series, chart){
-		if (series.values.length==0) return;
+	this.plot=function(/* dojo.widget.Chart.DataSeries */series, /* dojo.widget.Chart */chart){
+		//	summary
+		//	plot the passed series.
+		if (series.values.length==0) return;	//	void
 		if (series.plotType && plotters[series.plotType]){
-			return plotters[series.plotType](series, chart);
+			return plotters[series.plotType](series, chart);	//	void
 		}
 		else if (chart.plotType && plotters[chart.plotType]){
-			return plotters[chart.plotType](series, chart);
+			return plotters[chart.plotType](series, chart);		//	void
 		}
 	};
 
 	//	plotting
-	plotters["bar"]=function(series, chart){
+	plotters["bar"]=function(/* dojo.widget.Chart.DataSeries */series, /* dojo.widget.Chart */chart){
+		//	summary
+		//	plot the passed series as a set of bars.
 		var space=1;
 		var lastW = 0;
 		for (var i=0; i<series.values.length; i++){
@@ -426,7 +452,9 @@
 			chart.dataGroup.appendChild(bar);
 		}
 	};
-	plotters["line"]=function(series, chart){
+	plotters["line"]=function(/* dojo.widget.Chart.DataSeries */series, /* dojo.widget.Chart */chart){
+		//	summary
+		//	plot the passed series as a line with tensioning
 		var tension=1.5;
 		var line = document.createElementNS(dojo.svg.xmlns.svg, "path");
 		line.setAttribute("fill", "none");
@@ -460,7 +488,9 @@
 		}
 		line.setAttribute("d", path.join(" "));
 	};
-	plotters["area"]=function(series, chart){
+	plotters["area"]=function(/* dojo.widget.Chart.DataSeries */series, /* dojo.widget.Chart */chart){
+		//	summary
+		//	plot the passed series as an area with tensioning.
 		var tension=1.5;
 		var line = document.createElementNS(dojo.svg.xmlns.svg, "path");
 		line.setAttribute("fill", series.color);
@@ -501,7 +531,9 @@
 		path.push("Z");
 		line.setAttribute("d", path.join(" "));
 	},
-	plotters["scatter"]=function(series, chart){
+	plotters["scatter"]=function(/* dojo.widget.Chart.DataSeries */series, /* dojo.widget.Chart */chart){
+		//	summary
+		//	plot the passed series as a scatter chart
 		var r=7;
 		for (var i=0; i<series.values.length; i++){
 			var x=self.getX(series.values[i].x, chart);
@@ -521,7 +553,9 @@
 			chart.dataGroup.appendChild(point);
 		}
 	};
-	plotters["bubble"]=function(series, chart){
+	plotters["bubble"]=function(/* dojo.widget.Chart.DataSeries */series, /* dojo.widget.Chart */chart){
+		//	summary
+		//	plot the passed series as a series of bubbles (scatter with 3rd dimension)
 		//	added param for series[n].value: size
 		var minR=1;
 		

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/AccordionPane.css
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/AccordionPane.css?view=diff&rev=453979&r1=453978&r2=453979
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/AccordionPane.css (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/AccordionPane.css Sat Oct  7 11:22:33 2006
@@ -1,13 +1,5 @@
-.dojoAccordionPane {
-	border: thick ridge #232323;
-}
-
-.dojoAccordionPane-selected {
-	border: thick ridge #336699;
-}
-
 .dojoAccordionPane .label {
-	border-bottom: thick ridge #232323;
+	border: thick ridge gray;
 	background: gray;
 	color: #fff;
 	font-weight: bold;
@@ -15,7 +7,7 @@
 
 .dojoAccordionPane-selected .label {
 	background: #336699;
-	border-bottom: thick ridge #336699;
+	border: thick ridge #336699;
 }
 
 .dojoAccordionPane .label :hover {

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/Checkbox.css
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/Checkbox.css?view=diff&rev=453979&r1=453978&r2=453979
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/Checkbox.css (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/Checkbox.css Sat Oct  7 11:22:33 2006
@@ -1,27 +1,26 @@
 .dojoHtmlCheckbox {
 	border: 0px;
-	width: 20px;
-	height: 20px;
-	display: -moz-inline-box;
-	display: inline-block;
-	margin-right: 5px;
+	width: 16px;
+	height: 16px;
+	margin: 2px;
+	vertical-align: middle;
 }
 
 .dojoHtmlCheckboxOn {
 	background: url(check.gif) 0px 0px;
 }
 .dojoHtmlCheckboxOff {
-	background: url(check.gif) -20px 0px;
+	background: url(check.gif) -16px 0px;
 }
 .dojoHtmlCheckboxDisabledOn {
-	background: url(check.gif) -40px 0px;
+	background: url(check.gif) -32px 0px;
 }
 .dojoHtmlCheckboxDisabledOff {
-	background: url(check.gif) -60px 0px;
+	background: url(check.gif) -48px 0px;
 }
 .dojoHtmlCheckboxOnHover {
-	background: url(check.gif) -80px 0px;
+	background: url(check.gif) -64px 0px;
 }
 .dojoHtmlCheckboxOffHover {
-	background: url(check.gif) -100px 0px;
+	background: url(check.gif) -80px 0px;
 }

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/Checkbox.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/Checkbox.html?view=diff&rev=453979&r1=453978&r2=453979
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/Checkbox.html (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/Checkbox.html Sat Oct  7 11:22:33 2006
@@ -1,5 +1,5 @@
-<span class='dojoHtmlCheckbox' tabIndex="${this.tabIndex}"  dojoAttachEvent="mouseOver; mouseOut; onKey; onClick: _onClick;" waiRole="checkbox" id="${this.id}">
-	<input type="checkbox" name="${this.name}" style="display: none" ${this.checkedStr} value="${this.value}"
+<span style="display: inline-block;" tabIndex="${this.tabIndex}" waiRole="checkbox" id="${this.id}">
+	<img dojoAttachPoint="imageNode" class="dojoHtmlCheckbox" src="${dojoRoot}src/widget/templates/images/blank.gif" alt="" />
+	<input type="checkbox" name="${this.name}" style="display: none" value="${this.value}"
 		dojoAttachPoint="inputNode">
-	&nbsp;
-</span>
+</span>
\ No newline at end of file

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/CheckboxA11y.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/CheckboxA11y.html?view=diff&rev=453979&r1=453978&r2=453979
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/CheckboxA11y.html (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/CheckboxA11y.html Sat Oct  7 11:22:33 2006
@@ -1,4 +1,4 @@
 <span class='dojoHtmlCheckbox'>
-	<input type="checkbox" name="${this.name}" tabIndex="${this.tabIndex}" ${this.disabledStr} id="${this.id}" ${this.checkedStr} value="${this.value}"
+	<input type="checkbox" name="${this.name}" tabIndex="${this.tabIndex}" id="${this.id}" value="${this.value}"
 		 dojoAttachEvent="onClick: _onClick;" dojoAttachPoint="inputNode"> 
 </span>

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/ComboBox.css
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/ComboBox.css?view=diff&rev=453979&r1=453978&r2=453979
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/ComboBox.css (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/ComboBox.css Sat Oct  7 11:22:33 2006
@@ -1,25 +1,39 @@
-/* the table holding the input and the button */
+.dojoComboBoxOuter {
+	border: 0px !important;
+	margin: 0px !important;
+	padding: 0px !important;
+	background: transparent !important;
+	white-space: nowrap !important;
+}
+
 .dojoComboBox {
-	border: 1px solid #afafaf;
+	border: 1px inset #afafaf;
+	margin: 0px;
 	padding: 0px;
-	line-height: 0px;
-	display: inline;	/* for IE and safari */
+	vertical-align: middle !important;
+	float: none !important;
+	position: static !important;
+	display: inline !important;
 }
 
-.dj_gecko .dojoComboBox {
-	display: -moz-inline-box;
+/* the input box */
+input.dojoComboBox {
+	border-right-width: 0px !important; 
+	margin-right: 0px !important;
+	padding-right: 0px !important;
 }
 
-.dj_opera .dojoComboBox {
-	display: inline-table;
+/* the down arrow */
+img.dojoComboBox {
+	border-left-width: 0px !important;
+	padding-left: 0px !important;
+	margin-left: 0px !important;
 }
 
-/* the input box */
-input.dojoComboBoxInput {
-	/* font-size: 0.8em; */
-	border: 0px;
-	margin: 0px;
-	padding: 0px;
+/* IE vertical-alignment calculations can be off by +-1 but these margins are collapsed away */
+.dj_ie img.dojoComboBox {
+	margin-top: 1px; 
+	margin-bottom: 1px; 
 }
 
 /* the drop down */

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/ComboBox.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/ComboBox.html?view=diff&rev=453979&r1=453978&r2=453979
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/ComboBox.html (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/ComboBox.html Sat Oct  7 11:22:33 2006
@@ -1,25 +1,16 @@
-<span>
-	<input style="display:none"  tabindex="-1" name="" value="" 
-		dojoAttachPoint="comboBoxValue">
-	<input style="display:none"  tabindex="-1" name="" value="" 
-		dojoAttachPoint="comboBoxSelectionValue">
-	<table class="dojoComboBox"
-		cellpadding="0"
-		cellspacing="0"
-		border="0"
-		dojoAttachPoint="cbTableNode">
-		<tr>
-			<td><input type="text" autocomplete="off" class="dojoComboBoxInput"
-					dojoAttachEvent="key:_handleKeyEvents; keyUp: onKeyUp; compositionEnd; onResize"
-					dojoAttachPoint="textInputNode"></td>
-			<td><img border="0" 
-					hspace="0"
-					vspace="0"
-					class="dojoComboArrow"
-					dojoAttachPoint="downArrowNode"
-					dojoAttachEvent="onMouseUp: handleArrowClick;"
-					src="${this.buttonSrc}"
-					style="width: ${this.initialButtonSize}; height: ${this.initialButtonSize};"></td>
-		</tr>
-	</table>
-</span>
+<span _="whitespace and CR's between tags adds &nbsp; in FF"
+	class="dojoComboBoxOuter"
+	><input style="display:none"  tabindex="-1" name="" value="" 
+		dojoAttachPoint="comboBoxValue"
+	><input style="display:none"  tabindex="-1" name="" value="" 
+		dojoAttachPoint="comboBoxSelectionValue"
+	><input type="text" autocomplete="off" class="dojoComboBox"
+		dojoAttachEvent="key:_handleKeyEvents; keyUp: onKeyUp; compositionEnd; onResize;"
+		dojoAttachPoint="textInputNode"
+	><img hspace="0"
+		vspace="0"
+		class="dojoComboBox"
+		dojoAttachPoint="downArrowNode"
+		dojoAttachEvent="onMouseUp: handleArrowClick; onResize;"
+		src="${this.buttonSrc}"
+></span>

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/EditorToolbar.css
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/EditorToolbar.css?view=diff&rev=453979&r1=453978&r2=453979
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/EditorToolbar.css (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/EditorToolbar.css Sat Oct  7 11:22:33 2006
@@ -58,12 +58,9 @@
 	height: 18px;
 	display: block;
 	/* background-color: white; */
-	/* border: 1px solid white; */
-	/* border: 1px solid #a6a7a3; */
-	padding-right: 3px;
 	cursor: pointer;
-	border: 1px solid transparent;
-	_border: none;
+	padding: 1px 4px 1px 1px; /* almost the same as a transparent border */
+	border: 0px;
 }
 
 .dojoE2TBIcon {
@@ -82,12 +79,14 @@
 }
 
 .ToolbarButtonLatched {
-    border: #316ac5 1px solid;
+    border: #316ac5 1px solid; !important;
+    padding: 0px 3px 0px 0px; !important; /* make room for border */
     background-color: #c1d2ee;
 }
 
 .ToolbarButtonHighlighted {
-    border: #316ac5 1px solid;
+    border: #316ac5 1px solid; !important;
+    padding: 0px 3px 0px 0px; !important; /* make room for border */
     background-color: #dff1ff;
 }
 

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/ProgressBar.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/ProgressBar.html?view=diff&rev=453979&r1=453978&r2=453979
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/ProgressBar.html (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/ProgressBar.html Sat Oct  7 11:22:33 2006
@@ -1,5 +1,5 @@
 <div dojoAttachPoint="containerNode" style="position:relative;overflow:hidden">
 	<div style="position:absolute;display:none;width:100%;text-align:center" dojoAttachPoint="backPercentLabel" class="dojoBackPercentLabel"></div>
-	<div style="position:absolute;overflow:hidden;width:100%;height:105%" dojoAttachPoint="internalProgress">
+	<div style="position:absolute;overflow:hidden;width:100%;height:100%" dojoAttachPoint="internalProgress">
 	<div style="position:absolute;display:none;width:100%;text-align:center" dojoAttachPoint="frontPercentLabel" class="dojoFrontPercentLabel"></div></div>
 </div>

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/check.gif
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/templates/check.gif?view=diff&rev=453979&r1=453978&r2=453979
==============================================================================
Binary files - no diff available.

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/CurrencyTextbox.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/CurrencyTextbox.js?view=auto&rev=453979
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/CurrencyTextbox.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/CurrencyTextbox.js Sat Oct  7 11:22:33 2006
@@ -0,0 +1,64 @@
+/*
+	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.validate.CurrencyTextbox");
+
+dojo.require("dojo.widget.validate.IntegerTextbox");
+dojo.require("dojo.validate.us");
+
+/*
+  ****** CurrencyTextbox ******
+
+  A subclass that extends IntegerTextbox.
+  Over-rides isValid/isInRange to test if input denotes a monetary value .
+  Has 5 new properties that can be specified as attributes in the markup.
+
+  @attr fractional      The decimal places (e.g. for cents).  Can be true or false, optional if omitted.
+  @attr symbol     A currency symbol such as Yen "???", Pound "???", or the Euro "???". Default is "$".
+  @attr separator  Default is "," instead of no separator as in IntegerTextbox.
+  @attr min  Minimum signed value.  Default is -Infinity
+  @attr max  Maximum signed value.  Default is +Infinity
+*/
+dojo.widget.defineWidget(
+	"dojo.widget.validate.CurrencyTextbox",
+	dojo.widget.validate.IntegerTextbox,
+	{
+		mixInProperties: function(localProperties, frag) {
+			// First initialize properties in super-class.
+			dojo.widget.validate.CurrencyTextbox.superclass.mixInProperties.apply(this, arguments);
+	
+			// Get properties from markup attributes, and assign to flags object.
+			if ( localProperties.fractional ) { 
+				this.flags.fractional = ( localProperties.fractional == "true" );
+			} else if ( localProperties.cents ) {
+				dojo.deprecated("dojo.widget.validate.IntegerTextbox", "use fractional attr instead of cents", "0.5");
+				this.flags.fractional = ( localProperties.cents == "true" );
+			}
+			if ( localProperties.symbol ) { 
+				this.flags.symbol = localProperties.symbol;
+			}
+			if(localProperties.min){ 
+				this.flags.min = parseFloat(localProperties.min);
+			}
+			if(localProperties.max){ 
+				this.flags.max = parseFloat(localProperties.max);
+			}
+		},
+
+		// Over-ride for currency validation
+		isValid: function() { 
+			return dojo.validate.isCurrency(this.textbox.value, this.flags);
+		},
+		isInRange: function() { 
+			return dojo.validate.isInRange(this.textbox.value, this.flags);
+		}
+
+	}
+);

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/DateTextbox.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/DateTextbox.js?view=auto&rev=453979
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/DateTextbox.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/DateTextbox.js Sat Oct  7 11:22:33 2006
@@ -0,0 +1,98 @@
+/*
+	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.validate.DateTextbox");
+
+dojo.require("dojo.widget.validate.ValidationTextbox");
+dojo.require("dojo.date.format");
+dojo.require("dojo.validate.datetime");
+
+//TODO: combine date and time widgets?
+dojo.widget.defineWidget(
+	"dojo.widget.validate.DateTextbox",
+	dojo.widget.validate.ValidationTextbox,
+	{
+		// summary: A TextBox which tests for a valid date
+		// format: Deprecated. Style as described in v0.3 in dojo.validate.  Default is  "MM/DD/YYYY".
+
+		// pattern used in display of formatted date.  See dojo.date.format.
+		displayFormat: "",
+		// type of format appropriate to locale.  see dojo.date.format
+		formatLength: "short",
+//TODO: add date, saveFormat attributes like DropdownDatePicker?
+
+		mixInProperties: function(/*Object*/localProperties){
+			// summary: see dojo.widget.Widget
+
+			// First initialize properties in super-class.
+			dojo.widget.validate.DateTextbox.superclass.mixInProperties.apply(this, arguments);
+	
+			// Get properties from markup attributes, and assign to flags object.
+			if(localProperties.format){ 
+				this.flags.format = localProperties.format;
+			}
+		},
+
+		isValid: function(){ 
+			// summary: see dojo.widget.validate.ValidationTextbox
+
+			if(this.flags.format){
+				dojo.deprecated("dojo.widget.validate.DateTextbox", "format attribute is deprecated; use displayFormat or formatLength instead", "0.5");
+				return dojo.validate.isValidDate(this.textbox.value, this.flags.format);
+			}
+
+			return dojo.date.parse(this.textbox.value, {formatLength:this.formatLength, selector:'dateOnly', locale:this.lang, datePattern: this.displayFormat});
+		}
+	}
+);
+
+dojo.widget.defineWidget(
+	"dojo.widget.validate.TimeTextbox",
+	dojo.widget.validate.ValidationTextbox,
+	{
+		// summary: A TextBox which tests for a valid time
+		// format: Deprecated. Described in v0.3 in dojo.validate.  Default is  "h:mm:ss t".
+		// amSymbol: Deprecated. Used with format. The symbol used for AM.  Default is "AM" or "am".
+		// pmSymbol: Deprecated. Used with format. The symbol used for PM.  Default is "PM" or "pm".
+
+		// pattern used in display of formatted date.  See dojo.date.format.
+		displayFormat: "",
+		// type of format appropriate to locale.  see dojo.date.format
+		formatLength: "short",
+
+		mixInProperties: function(/*Object*/localProperties){
+			// summary: see dojo.widget.Widget
+
+			// First initialize properties in super-class.
+			dojo.widget.validate.TimeTextbox.superclass.mixInProperties.apply(this, arguments);
+	
+			// Get properties from markup attributes, and assign to flags object.
+			if(localProperties.format){ 
+				this.flags.format = localProperties.format;
+			}
+			if(localProperties.amsymbol){ 
+				this.flags.amSymbol = localProperties.amsymbol;
+			}
+			if(localProperties.pmsymbol){ 
+				this.flags.pmSymbol = localProperties.pmsymbol;
+			}
+		},
+
+		isValid: function(){ 
+			// summary: see dojo.widget.validate.ValidationTextbox
+			if(this.flags.format){
+				dojo.deprecated("dojo.widget.validate.TimeTextbox", "format attribute is deprecated; use displayFormat or formatLength instead", "0.5");
+				return dojo.validate.isValidTime(this.textbox.value, this.flags);
+			}
+
+			return dojo.date.parse(this.textbox.value, {formatLength:this.formatLength, selector:'timeOnly', locale:this.lang, timePattern: this.displayFormat});
+		}
+	}
+);

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/IntegerTextbox.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/IntegerTextbox.js?view=auto&rev=453979
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/IntegerTextbox.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/IntegerTextbox.js Sat Oct  7 11:22:33 2006
@@ -0,0 +1,65 @@
+/*
+	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.validate.IntegerTextbox");
+
+dojo.require("dojo.widget.validate.ValidationTextbox");
+
+/*
+  ****** IntegerTextbox ******
+
+  A subclass of ValidationTextbox.
+  Over-rides isValid/isInRange to test for integer input.
+  Has 4 new properties that can be specified as attributes in the markup.
+
+  @attr signed     The leading plus-or-minus sign. Can be true or false, default is either.
+  @attr separator  The character used as the thousands separator.  Default is no separator.
+  @attr min  Minimum signed value.  Default is -Infinity
+  @attr max  Maximum signed value.  Default is +Infinity
+*/
+dojo.widget.defineWidget(
+	"dojo.widget.validate.IntegerTextbox",
+	dojo.widget.validate.ValidationTextbox,
+	{
+		mixInProperties: function(localProperties, frag) {
+			// First initialize properties in super-class.
+			dojo.widget.validate.IntegerTextbox.superclass.mixInProperties.apply(this, arguments);
+	
+			// Get properties from markup attributes, and assign to flags object.
+			if((localProperties.signed == "true")||
+				(localProperties.signed == "always")){
+				this.flags.signed = true;
+			}else if((localProperties.signed == "false")||
+					(localProperties.signed == "never")){
+				this.flags.signed = false;
+				this.flags.min = 0;
+			}else{
+				this.flags.signed = [ true, false ]; // optional
+			}
+			if(localProperties.separator){ 
+				this.flags.separator = localProperties.separator;
+			}
+			if(localProperties.min){ 
+				this.flags.min = parseInt(localProperties.min);
+			}
+			if(localProperties.max){ 
+				this.flags.max = parseInt(localProperties.max);
+			}
+		},
+
+		// Over-ride for integer validation
+		isValid: function() { 
+			return dojo.validate.isInteger(this.textbox.value, this.flags);
+		},
+		isInRange: function() { 
+			return dojo.validate.isInRange(this.textbox.value, this.flags);
+		}
+	}
+);

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/InternetTextbox.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/InternetTextbox.js?view=auto&rev=453979
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/InternetTextbox.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/InternetTextbox.js Sat Oct  7 11:22:33 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.widget.validate.InternetTextbox");
+
+dojo.require("dojo.widget.validate.ValidationTextbox");
+dojo.require("dojo.validate.web");
+
+dojo.widget.defineWidget(
+	"dojo.widget.validate.IpAddressTextbox",
+	dojo.widget.validate.ValidationTextbox,
+	{
+		// summary:  A Textbox which tests for a valid IP address
+		// description:  Can specify formats for ipv4 or ipv6 as attributes in the markup.
+		//
+		// allowDottedDecimal  true or false, default is true.
+		// allowDottedHex      true or false, default is true.
+		// allowDottedOctal    true or false, default is true.
+		// allowDecimal        true or false, default is true.
+		// allowHex            true or false, default is true.
+		// allowIPv6           true or false, default is true.
+		// allowHybrid         true or false, default is true.
+
+		mixInProperties: function(/*Object*/localProperties){
+			// summary: see dojo.widget.Widget
+
+			// First initialize properties in super-class.
+			dojo.widget.validate.IpAddressTextbox.superclass.mixInProperties.apply(this, arguments);
+
+			// Get properties from markup attributes, and assign to flags object.
+			if(localProperties.allowdotteddecimal){ 
+				this.flags.allowDottedDecimal = (localProperties.allowdotteddecimal == "true");
+			}
+			if(localProperties.allowdottedhex){ 
+				this.flags.allowDottedHex = (localProperties.allowdottedhex == "true");
+			}
+			if(localProperties.allowdottedoctal){ 
+				this.flags.allowDottedOctal = (localProperties.allowdottedoctal == "true");
+			}
+			if(localProperties.allowdecimal){ 
+				this.flags.allowDecimal = (localProperties.allowdecimal == "true");
+			}
+			if(localProperties.allowhex){ 
+				this.flags.allowHex = (localProperties.allowhex == "true");
+			}
+			if(localProperties.allowipv6){ 
+				this.flags.allowIPv6 = (localProperties.allowipv6 == "true");
+			}
+			if(localProperties.allowhybrid){ 
+				this.flags.allowHybrid = (localProperties.allowhybrid == "true");
+			}
+		},
+
+		isValid: function(){ 
+			// summary: see dojo.widget.validate.ValidationTextbox
+			return dojo.validate.isIpAddress(this.textbox.value, this.flags);
+		}
+	}
+);
+
+dojo.widget.defineWidget(
+	"dojo.widget.validate.UrlTextbox",
+	dojo.widget.validate.IpAddressTextbox,
+	{
+		// summary:  A Textbox which tests for a valid URL
+		// scheme        Can be true or false.  If omitted the scheme is optional.
+		// allowIP       Allow an IP address for hostname.  Default is true.
+		// allowLocal    Allow the host to be "localhost".  Default is false.
+		// allowCC       Allow 2 letter country code domains.  Default is true.
+		// allowGeneric  Allow generic domains.  Can be true or false, default is true.
+
+		mixInProperties: function(/*Object*/localProperties){
+			// summary: see dojo.widget.Widget
+
+			// First initialize properties in super-class.
+			dojo.widget.validate.UrlTextbox.superclass.mixInProperties.apply(this, arguments);
+
+			// Get properties from markup attributes, and assign to flags object.
+			if ( localProperties.scheme ) { 
+				this.flags.scheme = ( localProperties.scheme == "true" );
+			}
+			if ( localProperties.allowip ) { 
+				this.flags.allowIP = ( localProperties.allowip == "true" );
+			}
+			if ( localProperties.allowlocal ) { 
+				this.flags.allowLocal = ( localProperties.allowlocal == "true" );
+			}
+			if ( localProperties.allowcc ) { 
+				this.flags.allowCC = ( localProperties.allowcc == "true" );
+			}
+			if ( localProperties.allowgeneric ) { 
+				this.flags.allowGeneric = ( localProperties.allowgeneric == "true" );
+			}
+		},
+
+		isValid: function(){ 
+			// summary: see dojo.widget.validate.ValidationTextbox
+			return dojo.validate.isUrl(this.textbox.value, this.flags);
+		}
+	}
+);
+
+//FIXME: DOC: need more consistent explanation on whether attributes are inherited from the parent.  Some make sense, some don't?
+
+dojo.widget.defineWidget(
+	"dojo.widget.validate.EmailTextbox",
+	dojo.widget.validate.UrlTextbox,
+	{
+		// summary:  A Textbox which tests for a valid email address
+		// description:
+		//  Can use all markup attributes/properties of UrlTextbox except scheme.
+		//
+		// allowCruft: Allow address like <ma...@yahoo.com>.  Default is false.
+
+		mixInProperties: function(/*Object*/localProperties){
+			// summary: see dojo.widget.Widget
+
+			// First initialize properties in super-class.
+			dojo.widget.validate.EmailTextbox.superclass.mixInProperties.apply(this, arguments);
+	
+			// Get properties from markup attributes, and assign to flags object.
+			if(localProperties.allowcruft){ 
+				this.flags.allowCruft = (localProperties.allowcruft == "true");
+			}
+		},
+
+		isValid: function(){
+			// summary: see dojo.widget.validate.ValidationTextbox
+			return dojo.validate.isEmailAddress(this.textbox.value, this.flags);
+		}
+	}
+);
+
+//TODO: perhaps combine with EmailTextbox?
+dojo.widget.defineWidget(
+	"dojo.widget.validate.EmailListTextbox",
+	dojo.widget.validate.EmailTextbox,
+	{
+		// summary:  A Textbox which tests for a list of valid email addresses
+		//
+		// listSeparator:  The character used to separate email addresses.  
+		//    Default is ";", ",", "\n" or " "
+
+		mixInProperties: function(/*Object*/localProperties){
+			// summary: see dojo.widget.Widget
+
+			// First initialize properties in super-class.
+			dojo.widget.validate.EmailListTextbox.superclass.mixInProperties.apply(this, arguments);
+	
+			// Get properties from markup attributes, and assign to flags object.
+			if(localProperties.listseparator){ 
+				this.flags.listSeparator = localProperties.listseparator;
+			}
+		},
+
+		isValid: function(){
+			// summary: see dojo.widget.validate.ValidationTextbox
+			return dojo.validate.isEmailAddressList(this.textbox.value, this.flags);
+		}
+	}
+);

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/RealNumberTextbox.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/RealNumberTextbox.js?view=auto&rev=453979
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/RealNumberTextbox.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/RealNumberTextbox.js Sat Oct  7 11:22:33 2006
@@ -0,0 +1,72 @@
+/*
+	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.validate.RealNumberTextbox");
+
+dojo.require("dojo.widget.validate.IntegerTextbox");
+
+/*
+  ****** RealNumberTextbox ******
+
+  A subclass that extends IntegerTextbox.
+  Over-rides isValid/isInRange to test for real number input.
+  Has 5 new properties that can be specified as attributes in the markup.
+
+  @attr places    The exact number of decimal places.  If omitted, it's unlimited and optional.
+  @attr exponent  Can be true or false.  If omitted the exponential part is optional.
+  @attr eSigned   Is the exponent signed?  Can be true or false, if omitted the sign is optional.
+  @attr min  Minimum signed value.  Default is -Infinity
+  @attr max  Maximum signed value.  Default is +Infinity
+*/
+dojo.widget.defineWidget(
+	"dojo.widget.validate.RealNumberTextbox",
+	dojo.widget.validate.IntegerTextbox,
+	{
+		mixInProperties: function(localProperties, frag) {
+			// First initialize properties in super-class.
+			dojo.widget.validate.RealNumberTextbox.superclass.mixInProperties.apply(this, arguments);
+	
+			// Get properties from markup attributes, and assign to flags object.
+			if ( localProperties.places ) { 
+				this.flags.places = Number( localProperties.places );
+			}
+			if((localProperties.exponent == "true")||
+				(localProperties.exponent == "always")){
+				this.flags.exponent = true;
+			}else if((localProperties.exponent == "false")||(localProperties.exponent == "never")){
+				this.flags.exponent = false;
+			}else{
+				this.flags.exponent = [ true, false ]; // optional
+			}
+			if((localProperties.esigned == "true")||(localProperties.esigned == "always")){
+				this.flags.eSigned = true;
+			}else if((localProperties.esigned == "false")||(localProperties.esigned == "never")){
+				this.flags.eSigned = false;
+			}else{
+				this.flags.eSigned = [ true, false ]; // optional
+			}
+			if(localProperties.min){ 
+				this.flags.min = parseFloat(localProperties.min);
+			}
+			if(localProperties.max){ 
+				this.flags.max = parseFloat(localProperties.max);
+			}
+		},
+
+		// Over-ride for real number validation
+		isValid: function() { 
+			return dojo.validate.isRealNumber(this.textbox.value, this.flags);
+		},
+		isInRange: function() { 
+			return dojo.validate.isInRange(this.textbox.value, this.flags);
+		}
+
+	}
+);

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/RegexpTextbox.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/RegexpTextbox.js?view=auto&rev=453979
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/RegexpTextbox.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/RegexpTextbox.js Sat Oct  7 11:22:33 2006
@@ -0,0 +1,48 @@
+/*
+	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.validate.RegexpTextbox");
+
+dojo.require("dojo.widget.validate.ValidationTextbox");
+
+/*
+  ****** RegexpTextbox ******
+
+  A subclass of ValidationTextbox.
+  Over-rides isValid to test input based on a regular expression.
+  Has a new property that can be specified as attributes in the markup. 
+
+  @attr regexp     The regular expression string to use
+  @attr flags      Flags to pass to the regular expression (e.g. 'i', 'g', etc)
+*/
+dojo.widget.defineWidget(
+	"dojo.widget.validate.RegexpTextbox",
+	dojo.widget.validate.ValidationTextbox,
+	{
+	    mixInProperties: function(localProperties, frag) {
+	        // First initialize properties in super-class.
+	        dojo.widget.validate.RegexpTextbox.superclass.mixInProperties.apply(this, arguments);
+
+	        // Get properties from markup attibutes, and assign to flags object.
+	        if ( localProperties.regexp ) {
+	            this.flags.regexp = localProperties.regexp;
+	        }
+	        if ( localProperties.flags ) {
+	            this.flags.flags = localProperties.flags;
+	        }
+	    },
+
+	    // Over-ride for integer validation
+	    isValid: function() {
+	        var regexp = new RegExp(this.flags.regexp, this.flags.flags);
+	        return regexp.test(this.textbox.value);
+	    }
+	}
+);

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/Textbox.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/Textbox.js?view=auto&rev=453979
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/Textbox.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/Textbox.js Sat Oct  7 11:22:33 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.widget.validate.Textbox");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.widget.Manager");
+dojo.require("dojo.widget.Parse");
+dojo.require("dojo.xml.Parse");
+dojo.require("dojo.lang.array");
+dojo.require("dojo.lang.common");
+
+dojo.require("dojo.i18n.common");
+dojo.requireLocalization("dojo.widget", "validate");
+
+/*
+  ****** Textbox ******
+
+  This widget is a generic textbox field.
+  Serves as a base class to derive more specialized functionality in subclasses.
+  Has the following properties that can be specified as attributes in the markup.
+
+  @attr id         The textbox id attribute.
+  @attr className  The textbox class attribute.
+  @attr name       The textbox name attribute.
+  @attr value      The textbox value attribute.
+  @attr trim       Removes leading and trailing whitespace if true.  Default is false.
+  @attr uppercase  Converts all characters to uppercase if true.  Default is false.
+  @attr lowercase  Converts all characters to lowercase if true.  Default is false.
+  @attr ucFirst    Converts the first character of each word to uppercase if true.
+  @attr lowercase  Removes all characters that are not digits if true.  Default is false.
+*/
+dojo.widget.defineWidget(
+	"dojo.widget.validate.Textbox",
+	dojo.widget.HtmlWidget,
+	{
+		// default values for new subclass properties
+		className: "",
+		name: "",
+		value: "",
+		type: "",
+		trim: false,
+		uppercase: false,
+		lowercase: false,
+		ucFirst: false,
+		digit: false,
+		htmlfloat: "none",
+
+		templatePath: dojo.uri.dojoUri("src/widget/templates/Textbox.html"),
+	
+		// our DOM nodes
+		textbox: null,
+	
+		// Apply various filters to textbox value
+		filter: function() { 
+			if (this.trim) {
+				this.textbox.value = this.textbox.value.replace(/(^\s*|\s*$)/g, "");
+			} 
+			if (this.uppercase) {
+				this.textbox.value = this.textbox.value.toUpperCase();
+			} 
+			if (this.lowercase) {
+				this.textbox.value = this.textbox.value.toLowerCase();
+			} 
+			if (this.ucFirst) {
+				this.textbox.value = this.textbox.value.replace(/\b\w+\b/g, 
+					function(word) { return word.substring(0,1).toUpperCase() + word.substring(1).toLowerCase(); });
+			} 
+			if (this.digit) {
+				this.textbox.value = this.textbox.value.replace(/\D/g, "");
+			} 
+		},
+	
+		// event handlers, you can over-ride these in your own subclasses
+		onfocus: function() {},
+		onblur: function() { this.filter(); },
+	
+		// All functions below are called by create from dojo.widget.Widget
+		mixInProperties: function(localProperties, frag) {
+			dojo.widget.validate.Textbox.superclass.mixInProperties.apply(this, arguments);
+			if ( localProperties["class"] ) { 
+				this.className = localProperties["class"];
+			}
+		}
+	}
+);

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/UsTextbox.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/UsTextbox.js?view=auto&rev=453979
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/UsTextbox.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/validate/UsTextbox.js Sat Oct  7 11:22:33 2006
@@ -0,0 +1,88 @@
+/*
+	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.validate.UsTextbox");
+
+dojo.require("dojo.widget.validate.ValidationTextbox");
+dojo.require("dojo.validate.us");
+
+dojo.widget.defineWidget(
+	"dojo.widget.validate.UsStateTextbox",
+	dojo.widget.validate.ValidationTextbox,
+	{
+		// summary: a Textbox which tests for a United States state abbreviation
+		// allowTerritories  Allow Guam, Puerto Rico, etc.  Default is true.
+		// allowMilitary     Allow military 'states', e.g. Armed Forces Europe (AE). Default is true.
+
+		mixInProperties: function(/*Object*/localProperties){
+			// summary: see dojo.widget.Widget
+
+			// Initialize properties in super-class.
+			dojo.widget.validate.UsStateTextbox.superclass.mixInProperties.apply(this, arguments);
+
+			// Get properties from markup attributes, and assign to flags object.
+			if(localProperties.allowterritories){
+				this.flags.allowTerritories = (localProperties.allowterritories == "true");
+			}
+			if(localProperties.allowmilitary){
+				this.flags.allowMilitary = (localProperties.allowmilitary == "true");
+			}
+		},
+
+		isValid: function(){
+			// summary: see dojo.widget.validate.ValidationTextbox
+			return dojo.validate.us.isState(this.textbox.value, this.flags);
+		}
+	}
+);
+
+/*
+  ****** UsZipTextbox ******
+
+  A subclass of ValidationTextbox.
+  Over-rides isValid to test if input is a US zip code.
+  Validates zip-5 and zip-5 plus 4.
+*/
+dojo.widget.defineWidget(
+	"dojo.widget.validate.UsZipTextbox",
+	dojo.widget.validate.ValidationTextbox,
+	{
+		// summary: a Textbox which tests for a United States postal code
+		isValid: function(){
+			// summary: see dojo.widget.validate.ValidationTextbox
+			return dojo.validate.us.isZipCode(this.textbox.value);
+		}
+	}
+);
+
+dojo.widget.defineWidget(
+	"dojo.widget.validate.UsSocialSecurityNumberTextbox",
+	dojo.widget.validate.ValidationTextbox,
+	{
+		// summary: a Textbox which tests for a United States Social Security number
+		isValid: function(){
+			// summary: see dojo.widget.validate.ValidationTextbox
+			return dojo.validate.us.isSocialSecurityNumber(this.textbox.value);
+		}
+	}
+);
+
+dojo.widget.defineWidget(
+	"dojo.widget.validate.UsPhoneNumberTextbox",
+	dojo.widget.validate.ValidationTextbox,
+	{
+		// summary: a Textbox which tests for a United States 10-digit telephone number, extension is optional.
+
+		isValid: function(){
+			// summary: see dojo.widget.validate.ValidationTextbox
+			return dojo.validate.us.isPhoneNumber(this.textbox.value);
+		}
+	}
+);

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