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 [14/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/s...

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/GoogleMap.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/GoogleMap.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/GoogleMap.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/GoogleMap.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,198 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.widget.html.GoogleMap");
+dojo.require("dojo.event.*");
+dojo.require("dojo.html");
+dojo.require("dojo.math");
+dojo.require("dojo.uri.Uri");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.widget.GoogleMap");
+
+(function(){
+	var gkey = djConfig["gMapKey"]||djConfig["googleMapKey"];
+
+	//	the Google API key mechanism sucks.  We're hardcoding here for love and affection but I don't like it.
+	var uri=new dojo.uri.Uri(window.location.href);
+	if(uri.host=="www.dojotoolkit.org"){
+		gkey="ABQIAAAACUNdgv_7FGOmUslbm9l6_hRqjp7ri2mNiOEYqetD3xnFHpt5rBSjszDd1sdufPyQKUTyCf_YxoIxvw";
+	}
+	else if(uri.host=="blog.dojotoolkit.org"){
+		gkey="ABQIAAAACUNdgv_7FGOmUslbm9l6_hSkep6Av1xaMhVn3yCLkorJeXeLARQ6fammI_P3qSGleTJhoI5_1JmP_Q";
+	}
+	else if(uri.host=="archive.dojotoolkit.org"){
+		gkey="ABQIAAAACUNdgv_7FGOmUslbm9l6_hTaQpDt0dyGLIHbXMPTzg1kWeAfwRTwZNyrUfbfxYE9yIvRivEjcXoDTg";
+	}
+	else if(uri.host=="dojotoolkit.org"){
+		gkey="ABQIAAAACUNdgv_7FGOmUslbm9l6_hSaOaO_TgJ5c3mtQFnk5JO2zD5dZBRZk-ieqVs7BORREYNzAERmcJoEjQ";
+	}
+
+	if(!dojo.hostenv.post_load_){
+		var tag = "<scr"+"ipt src='http://maps.google.com/maps?file=api&amp;v=2&amp;key="+gkey+"'></scri"+"pt>";
+		if(!dj_global["GMap2"]){ // prevent multi-inclusion
+			document.write(tag);
+		}
+	}else{
+		dojo.debug("cannot initialize map system after the page has been loaded! Please either manually include the script block provided by Google in your page or require() the GoogleMap widget before onload has fired");
+	}
+})();
+
+dojo.widget.html.GoogleMap=function(){
+	dojo.widget.HtmlWidget.call(this);
+	dojo.widget.GoogleMap.call(this);
+
+	var gm=dojo.widget.GoogleMap;
+
+	this.map=null;
+	this.data=[];
+	this.datasrc="";
+	// FIXME: this is pehraps the stupidest way to specify this enum I can think of
+	this.controls=[gm.Controls.LargeMap,gm.Controls.Scale,gm.Controls.MapType];
+};
+dojo.inherits(dojo.widget.html.GoogleMap, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.html.GoogleMap, {
+	templatePath:null,
+	templateCssPath:null,
+
+	setControls:function(){
+		var c=dojo.widget.GoogleMap.Controls;
+		for(var i=0; i<this.controls.length; i++){
+			var type=this.controls[i];
+			switch(type){
+				case c.LargeMap:{
+					this.map.addControl(new GLargeMapControl());
+					break;
+				}
+				case c.SmallMap:{
+					this.map.addControl(new GSmallMapControl());
+					break;
+				}
+				case c.SmallZoom:{
+					this.map.addControl(new GSmallZoomControl());
+					break;
+				}
+				case c.Scale:{
+					this.map.addControl(new GScaleControl());
+					break;
+				}
+				case c.MapType:{
+					this.map.addControl(new GMapTypeControl());
+					break;
+				}
+				case c.Overview:{
+					this.map.addControl(new GOverviewMapControl());
+					break;
+				}
+				default:{
+					break;
+				}
+			}
+		}
+	},
+	
+	findCenter:function(bounds){
+		var clat=(bounds.getNorthEast().lat()+bounds.getSouthWest().lat())/2;
+		var clng=(bounds.getNorthEast().lng()+bounds.getSouthWest().lng())/2;
+		return (new GLatLng(clat,clng));
+	},
+
+	createPinpoint:function(pt,overlay){
+		var m=new GMarker(pt);
+		if(overlay){
+			GEvent.addListener(m,"click",function(){
+				m.openInfoWindowHtml("<div>"+overlay+"</div>");
+			});
+		}
+		return m;
+	},
+
+	parse:function(table){
+		this.data=[];
+
+		//	get the column indices
+		var h=table.getElementsByTagName("thead")[0];
+		if(!h){
+			return;
+		}
+
+		var a=[];
+		var cols=h.getElementsByTagName("td");
+		if(cols.length==0){
+			cols=h.getElementsByTagName("th");
+		}
+		for(var i=0; i<cols.length; i++){
+			var c=cols[i].innerHTML.toLowerCase();
+			if(c=="long") c="lng";
+			a.push(c);
+		}
+		
+		//	parse the data
+		var b=table.getElementsByTagName("tbody")[0];
+		if(!b){
+			return;
+		}
+		for(var i=0; i<b.childNodes.length; i++){
+			if(!(b.childNodes[i].nodeName&&b.childNodes[i].nodeName.toLowerCase()=="tr")){
+				continue;
+			}
+			var cells=b.childNodes[i].getElementsByTagName("td");
+			var o={};
+			for(var j=0; j<a.length; j++){
+				var col=a[j];
+				if(col=="lat"||col=="lng"){
+					o[col]=parseFloat(cells[j].innerHTML);					
+				}else{
+					o[col]=cells[j].innerHTML;
+				}
+			}
+			this.data.push(o);
+		}
+	},
+	render:function(){
+		var bounds=new GLatLngBounds();
+		var d=this.data;
+		var pts=[];
+		for(var i=0; i<d.length; i++){
+			bounds.extend(new GLatLng(d[i].lat,d[i].lng));
+		}
+
+		this.map.setCenter(this.findCenter(bounds), this.map.getBoundsZoomLevel(bounds));
+
+		for(var i=0; i<this.data.length; i++){
+			var p=new GLatLng(this.data[i].lat,this.data[i].lng);
+			var d=this.data[i].description||null;
+			var m=this.createPinpoint(p,d);
+			this.map.addOverlay(m);
+		}
+	},
+	
+
+	initialize:function(args, frag){
+		if(!GMap2){
+			dojo.raise("dojo.widget.GoogleMap: The Google Map script must be included (with a proper API key) in order to use this widget.");
+		}
+		if(this.datasrc){
+			this.parse(dojo.byId(this.datasrc));
+		}
+		else if(this.domNode.getElementsByTagName("table")[0]){
+			this.parse(this.domNode.getElementsByTagName("table")[0]);
+		}
+	},
+	postCreate:function(){
+		//	clean the domNode before creating the map.
+		while(this.domNode.childNodes.length>0){
+			this.domNode.removeChild(this.domNode.childNodes[0]);
+		}
+		this.map=new GMap2(this.domNode);
+		this.render();
+		this.setControls();
+	}
+});

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/LinkPane.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/LinkPane.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/LinkPane.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/LinkPane.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,54 @@
+/*
+	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.LinkPane");
+dojo.provide("dojo.widget.html.LinkPane");
+
+//
+// a div that loads from a URL.  (Similar to an iframe, but
+// it's in the same environment as the main window)
+//
+
+dojo.require("dojo.widget.LinkPane");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.event.*");
+dojo.require("dojo.io.*");
+dojo.require("dojo.widget.ContentPane");
+dojo.require("dojo.html");
+dojo.require("dojo.style");
+dojo.require("dojo.dom");
+dojo.require("dojo.string");
+
+
+dojo.widget.html.LinkPane = function(){
+	dojo.widget.html.ContentPane.call(this);
+}
+
+dojo.inherits(dojo.widget.html.LinkPane, dojo.widget.html.ContentPane);
+
+dojo.lang.extend(dojo.widget.html.LinkPane, {
+	widgetType: "LinkPane",
+
+	// I'm using a template because the user may specify the input as
+	// <a href="foo.html">label</a>, in which case we need to get rid of the
+	// <a> because we don't want a link.
+	templateString: '<div class="dojoLinkPane"></div>',
+
+	fillInTemplate: function(args, frag){
+		var source = this.getFragNodeRef(frag);
+
+		// If user has specified node contents, they become the label
+		// (the link must be plain text)
+		this.label += source.innerHTML;
+
+		var source = this.getFragNodeRef(frag);
+		dojo.html.copyStyle(this.domNode, source);
+	}
+});

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/Slider.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/Slider.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/Slider.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/Slider.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,445 @@
+/*
+	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
+*/
+
+/**
+ * Slider Widget.
+ * 
+ * The slider widget comes in three forms:
+ *  1. Base Slider widget which supports movement in x and y dimensions
+ *  2. Vertical Slider (SliderVertical) widget which supports movement
+ *     only in the y dimension.
+ *  3. Horizontal Slider (SliderHorizontal) widget which supports movement
+ *     only in the x dimension.
+ *
+ * The key objects in the widget are:
+ *  - a container div which displays a bar in the background (Slider object)
+ *  - a handle inside the container div, which represents the value
+ *    (sliderHandle DOM node)
+ *  - the object which moves the handle (handleMove is of type 
+ *    SliderDragMoveSource)
+ *
+ * The values for the slider are calculated by grouping pixels together, 
+ * based on the number of values to be represented by the slider.
+ * The number of pixels in a group is called the valueSize
+ *  e.g. if slider is 150 pixels long, and is representing the values
+ *       0,1,...10 then pixels are grouped into lots of 15 (valueSize), where:
+ *         value 0 maps to pixels  0 -  7
+ *               1                 8 - 22
+ *               2                23 - 37 etc.
+ * The accuracy of the slider is limited to the number of pixels
+ * (i.e tiles > pixels will result in the slider not being able to
+ *  represent some values).
+ *
+ * Technical Notes:
+ *  - 3 widgets exist because the framework caches the template in
+ *    dojo.widget.fillFromTemplateCache (which ignores the changed URI)
+ *
+ * Todo:
+ *  - Setting of initial value currently doesn't work, because the one or
+ *    more of the offsets, constraints or containing block are not set and
+ *    are required to set the valueSize is not set before fillInTemplate
+ *    is called.
+ *  - Issues with dragging handle when page has been scrolled
+ *  - 
+ *
+ * References (aka sources of inspiration):
+ *  - http://dojotoolkit.org/docs/fast_widget_authoring.html
+ *  - http://dojotoolkit.org/docs/dojo_event_system.html
+ * 
+ * @author Marcel Linnenfelser (m.linnen@synflag.de)
+ * @author Mathew Pole (mathew.pole@ebor.com)
+ *
+ * $Id: $
+ */
+
+// tell the package system what functionality is provided in this module (file)
+// (note that the package system works on modules, not the classes)
+dojo.provide("dojo.widget.html.Slider");
+
+// load dependencies
+dojo.require("dojo.fx.*");
+dojo.require("dojo.event.*");
+dojo.require("dojo.lang.*");
+dojo.require("dojo.animation.Timer");
+dojo.require("dojo.dnd.*");
+// dojo.dnd.* doesn't include this package, because it's not in __package__.js
+dojo.require("dojo.dnd.HtmlDragMove");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.style");
+
+
+/**
+ * Define the two dimensional slider widget class.
+ */
+dojo.widget.defineWidget (
+	"dojo.widget.html.Slider",
+	dojo.widget.HtmlWidget,
+	{
+		// over-ride some defaults
+		isContainer: false, // or true? - not sure
+		widgetType: "Slider",
+
+		// useful properties (specified as attributes in the html tag)
+		// number of values to be represented by slider in the horizontal direction
+		valuesX: 10,
+		// number of values to be represented by slider in the vertical direction
+		valuesY: 10,
+		// can values be changed on the x (horizontal) axis?
+		isEnableX: true,
+		// can values be changed on the y (vertical) axis?
+		isEnableY: true,
+		// value size (pixels) in the x dimension
+		valueSizeX: 0.0,
+		// value size (pixels) in the y dimension
+		valueSizeY: 0.0,
+		// initial value in the x dimension
+		initialValueX: 0,
+		// initial value in the y dimension
+		initialValueY: 0,
+
+		// do we allow the user to click on the slider to set the position?
+		// (note: dojo's infrastructor will convert attribute to a boolean)
+		clickSelect: true,
+		// should the handle snap to the grid or remain where it was dragged to?
+		// (note: dojo's infrastructor will convert attribute to a boolean)
+		snapToGrid: false,
+
+		templateCssPath: dojo.uri.dojoUri ("src/widget/templates/HtmlSlider.css"),
+		templatePath: dojo.uri.dojoUri ("src/widget/templates/HtmlSlider.html"),
+
+		// our DOM nodes
+		sliderHandle: null,
+
+		// private attributes
+		// This is set to true when a drag is started, so that it is not confused
+		// with a click
+		isDragInProgress: false,
+
+
+		// This function is called when the template is loaded
+		fillInTemplate: function () 
+		{
+			// dojo.debug ("fillInTemplate - className = " + this.domNode.className);
+
+			// setup drag-n-drop for the sliderHandle
+			this.handleMove = new dojo.widget.html.SliderDragMoveSource (this.sliderHandle);
+			this.handleMove.setParent (this);
+			
+			//var dragMove = new dojo.dnd.HtmlDragMoveSource(this.sliderHandle);
+
+			// keep the slider handle inside it's parent container
+			this.handleMove.constrainToContainer = true;
+		
+			if (this.clickSelect) {
+				dojo.event.connect (this.domNode, "onclick", this, "setPosition");
+			} 
+
+			dojo.debug ("fillInTemplate - this.initialValueX = " + this.isEnableX + " " + this.initialValueX);
+			if (this.isEnableX && this.initialValueX > 0) {
+				dojo.debug ("*");
+				this.setValueX (this.initialValueX);
+			}
+			if (this.isEnableY && this.initialValueY > 0) {
+				this.setValueY (this.initialValueY);
+			}
+		},
+
+
+		// Move the handle (in the x dimension) to the specified value
+		setValueX: function (value) {
+			if (0.0 == this.valueSizeX) {
+				this.valueSizeX = this.handleMove.calcValueSizeX ();
+			}
+			if (value > this.valuesX) {
+				value = this.valuesX;
+			}
+			else if (value < 0) {
+				value = 0;
+			}
+			//dojo.debug ("value = " + value, ", valueSizeX = " + this.valueSizeX);
+			this.handleMove.domNode.style.left = (value * this.valueSizeX) + "px";
+		},
+
+
+		// Get the number of the value that matches the position of the handle
+		getValueX: function () {
+			if (0.0 == this.valueSizeX) {
+				this.valueSizeX = this.handleMove.calcValueSizeX ();
+			}
+			return Math.round (dojo.style.getPixelValue (this.handleMove.domNode, "left") / this.valueSizeX);
+		},
+
+
+		// set the slider to a particular value
+		setValueY: function (value) {
+			if (0.0 == this.valueSizeY) {
+				this.valueSizeY = this.handleMove.calcValueSizeY ();
+			}
+			if (value > this.valuesY) {
+				value = this.valuesY;
+			}
+			else if (value < 0) {
+				value = 0;
+			}
+
+			this.handleMove.domNode.style.top = (value * this.valueSizeY) + "px";
+		},
+
+
+		// Get the number of the value that the matches the position of the handle
+		getValueY: function () {
+			if (0.0 == this.valueSizeY) {
+				this.valueSizeY = this.handleMove.calcValueSizeY ();
+			}
+			return Math.round (dojo.style.getPixelValue (this.handleMove.domNode, "top") / this.valueSizeY);
+		},
+
+
+		// set the position of the handle
+		setPosition: function (e) {
+			//dojo.debug ("Slider#setPosition - e.clientX = " + e.clientX
+			//            + ", e.clientY = " + e.clientY);
+			if (this.isDragInProgress) {
+				this.isDragInProgress = false;
+			}
+
+			var offset = dojo.html.getScrollOffset();
+			var parent = dojo.style.getAbsolutePosition(this.domNode, true);
+			
+			if (this.isEnableX) {
+				var x = offset.x + e.clientX - parent.x;
+				if (x > this.domNode.offsetWidth) {
+					x = this.domNode.offsetWidth;
+				}
+				if (this.snapToGrid && x > 0) {
+					if (0.0 == this.valueSizeX) {
+						this.valueSizeX = this.handleMove.calcValueSizeX ();
+					}
+					x = this.valueSizeX * (Math.round (x / this.valueSizeX));
+				}
+				this.handleMove.domNode.style.left = x + "px";
+			}
+			if (this.isEnableY) {
+				var y = offset.y + e.clientY - parent.y;
+				if (y > this.domNode.offsetHeight) {
+					y = this.domNode.offsetHeight;
+				}
+				if (this.snapToGrid && y > 0) {
+					if (0.0 == this.valueSizeY) {
+						this.valueSizeY = this.handleMove.calcValueSizeY ();
+					}
+					y = this.valueSizeY * (Math.round (y / this.valueSizeY));
+				}
+				this.handleMove.domNode.style.top = y + "px";
+			}
+		}
+	}
+);
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/**
+ * Define the horizontal slider widget class.
+ */
+dojo.widget.defineWidget (
+	"dojo.widget.html.SliderHorizontal",
+	dojo.widget.html.Slider,
+	{
+		widgetType: "SliderHorizontal",
+
+		valuesY: 0,
+		isEnableY: false,
+		templatePath: dojo.uri.dojoUri ("src/widget/templates/HtmlSliderHorizontal.html"),
+
+		// wrapper for getValueX
+		getValue: function () {
+			return this.getValueX ();
+		},
+
+		// wrapper for setValueX
+		setValue: function (value) {
+			this.setValueX (value);
+		}
+	}
+);
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/**
+ * Define the vertical slider widget class.
+ */
+dojo.widget.defineWidget (
+	"dojo.widget.html.SliderVertical",
+	dojo.widget.html.Slider,
+	{
+		widgetType: "SliderVertical",
+
+		valuesX: 0,
+		isEnableX: false,
+		templatePath: dojo.uri.dojoUri ("src/widget/templates/HtmlSliderVertical.html"),
+
+		// wrapper for getValueY
+		getValue: function () {
+			return this.getValueY ();
+		},
+
+		// wrapper for setValueY
+		setValue: function (value) {
+			this.setValueY (value);
+		}
+	}
+);
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/**
+ * This class extends the HtmlDragMoveSource class to provide
+ * features for the slider handle.
+ */
+dojo.declare (
+	"dojo.widget.html.SliderDragMoveSource",
+	dojo.dnd.HtmlDragMoveSource,
+{
+	isDragInProgress: false,
+	slider: null,
+
+
+	/** Setup the handle for drag
+	 *  Extends dojo.dnd.HtmlDragMoveSource by creating a SliderDragMoveSource */
+	onDragStart: function (e) {
+		this.isDragInProgress = true;
+		this.constrainToContainer = true;
+
+		var dragObj = this.createDragMoveObject ();
+		var constraints = null;
+
+
+		dojo.event.connect (dragObj, "onDragMove", this, "onDragMove");
+
+		return dragObj;
+	},
+
+
+	onDragMove: function (e) {
+		// placeholder to enable event connection
+	},
+
+
+	createDragMoveObject: function () {
+		//dojo.debug ("SliderDragMoveSource#createDragMoveObject - " + this.slider);
+		var dragObj = new dojo.widget.html.SliderDragMoveObject (this.dragObject, this.type);
+		dragObj.slider = this.slider;
+
+		// this code copied from dojo.dnd.HtmlDragSource#onDragStart
+		if (this.dragClass) { 
+			dragObj.dragClass = this.dragClass; 
+		}
+		if (this.constrainToContainer) {
+			dragObj.constrainTo(this.constrainingContainer || this.domNode.parentNode);
+		}
+		return dragObj;
+	},
+
+
+	setParent: function (slider) {
+		this.slider = slider;
+	},
+
+	
+	calcValueSizeX: function () {
+		var dragObj = this.createDragMoveObject ();
+		dragObj.containingBlockPosition = dragObj.domNode.offsetParent ? 
+		dojo.style.getAbsolutePosition(dragObj.domNode.offsetParent) : {x:0, y:0};
+		dojo.debug ("constrainingBlockPosition.x = " + dragObj.containingBlockPosition.x
+								+ ", .y = " + dragObj.containingBlockPosition.y);
+		
+		var constraints = dragObj.getConstraints ();
+		dojo.debug ("calcValueSizeX = (" + constraints.maxX
+								+ " - " + constraints.minX + ") / " + this.slider.valuesX);
+		return (constraints.maxX - constraints.minX) / this.slider.valuesX;
+	},
+
+	
+	calcValueSizeY: function () {
+		var dragObj = this.createDragMoveObject ();
+		dragObj.containingBlockPosition = dragObj.domNode.offsetParent ? 
+		dojo.style.getAbsolutePosition(dragObj.domNode.offsetParent) : {x:0, y:0};
+		dojo.debug ("constrainingBlockPosition.x = " + dragObj.containingBlockPosition.x
+								+ ", .y = " + dragObj.containingBlockPosition.y);
+		var constraints = dragObj.getConstraints ();
+		return (constraints.maxY - constraints.minY) / this.slider.valuesY;
+	}
+});
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/**
+ * This class extends the HtmlDragMoveObject class to provide
+ * features for the slider handle.
+ */
+dojo.declare (
+	"dojo.widget.html.SliderDragMoveObject",
+	dojo.dnd.HtmlDragMoveObject,
+{
+	// reference to dojo.widget.html.Slider
+	slider: null,
+
+	/** Moves the node to follow the mouse.
+	 *  Extends functon HtmlDragObject by adding functionality to snap handle
+	 *  to a discrete value */
+	onDragMove: function (e) {
+		if (this.slider.isEnableX && 0.0 == this.slider.valueSizeX) {
+			this.slider.valueSizeX = (this.constraints.maxX - this.constraints.minX) / this.slider.valuesX;
+		}
+		if (this.slider.isEnableY && 0.0 == this.slider.valueSizeY) {
+			this.slider.valueSizeY = (this.constraints.maxY - this.constraints.minY) / this.slider.valuesY;
+		}
+
+		this.updateDragOffset ();
+
+		var x = this.dragOffset.x + e.pageX;
+		var y = this.dragOffset.y + e.pageY;
+
+		if (this.constrainToContainer) {
+			if (x < this.constraints.minX) { x = this.constraints.minX; }
+			if (y < this.constraints.minY) { y = this.constraints.minY; }
+			if (x > this.constraints.maxX) { x = this.constraints.maxX; }
+			if (y > this.constraints.maxY) { y = this.constraints.maxY; }
+		}
+
+		if (this.slider.isEnableX) {
+			var selectedValue = 0;
+			if (x > 0) {
+				selectedValue = Math.round (x / this.slider.valueSizeX);
+			}
+			// dojo.debug ("x = " + x + ", valueSize = " + valueSize 
+			//             + ", selectedValue = " + selectedValue);
+			x = (selectedValue * this.slider.valueSizeX);
+		}
+
+		if (this.slider.isEnableY) {
+			var selectedValue = 0;
+			if (y > 0) {
+				selectedValue = Math.round (y / this.slider.valueSizeY);
+			}
+			y = (selectedValue * this.slider.valueSizeY);
+		}
+
+		this.setAbsolutePosition (x, y);
+	}
+});

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/SortableTable.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/SortableTable.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/SortableTable.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/SortableTable.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,582 @@
+/*
+	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.html.SortableTable");
+dojo.require("dojo.lang");
+dojo.require("dojo.date");
+dojo.require("dojo.html");
+dojo.require("dojo.event.*");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.widget.SortableTable");
+
+dojo.widget.html.SortableTable=function(){
+	//	summary
+	//	Constructor for the SortableTable widget
+	dojo.widget.SortableTable.call(this);
+	dojo.widget.HtmlWidget.call(this);
+
+	this.headClass="";
+	this.tbodyClass="";
+	this.headerClass="";
+	this.headerSortUpClass="selected";
+	this.headerSortDownClass="selected";
+	this.rowClass="";
+	this.rowAlternateClass="alt";
+	this.rowSelectedClass="selected";
+	this.columnSelected="sorted-column";
+};
+dojo.inherits(dojo.widget.html.SortableTable, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.html.SortableTable, {
+	templatePath:null,
+	templateCssPath:null,
+
+	getTypeFromString:function(/* string */ s){
+		//	summary
+		//	Find the constructor that matches param s by searching through the entire object tree.
+		var parts=s.split("."),i=0,obj=dj_global; 
+		do{obj=obj[parts[i++]];}while(i<parts.length&&obj); 
+		return(obj!=dj_global)?obj:null;	//	function
+	},
+	compare:function(/* object */ o1, /* object */ o2){
+		//	summary
+		//	Compare two objects using a shallow property compare
+		for(var p in o1){
+			if(!(p in o2)) return false;	//	boolean
+			if(o1[p].valueOf()!=o2[p].valueOf()) return false;	//	boolean
+		}
+		return true;	// boolean
+	},
+	isSelected:function(/* object */ o){
+		//	summary
+		//	checked to see if the passed object is in the current selection.
+		for(var i=0;i<this.selected.length;i++){
+			if(this.compare(this.selected[i],o)){
+				return true; // boolean
+			}
+		}
+		return false;	// boolean
+	},
+	removeFromSelected:function(/* object */ o){
+		//	summary
+		//	remove the passed object from the current selection.
+		var idx=-1;
+		for(var i=0;i<this.selected.length;i++){
+			if(this.compare(this.selected[i],o)){
+				idx=i;
+				break;
+			}
+		}
+		if(idx>=0){
+			this.selected.splice(idx,1);
+		}
+	},
+	getSelection:function(){
+		//	summary
+		//	return the array of currently selected objects (JSON format)
+		return this.selected;	//	array
+	},
+	getValue:function(){
+		//	summary
+		//	return a comma-delimited list of selected valueFields.
+		var a=[];
+		for(var i=0;i<this.selected.length;i++){
+			if (this.selected[i][this.valueField]){
+				a.push(this.selected[i][this.valueField]);
+			}
+		}
+		return a.join();	//	string
+	},
+	reset:function(){
+		//	summary
+		//	completely resets the internal representations.
+		this.columns=[];
+		this.data=[];
+		this.resetSelections(this.domNode.getElementsByTagName("tbody")[0]);
+	},
+	resetSelections:function(/* HTMLTableBodyElement */ body){
+		this.selected=[];
+		var idx=0;
+		var rows=body.getElementsByTagName("tr");
+		for(var i=0; i<rows.length; i++){
+			if(rows[i].parentNode==body){
+				rows[i].removeAttribute("selected");
+				if(this.enableAlternateRows&&idx%2==1){
+					rows[i].className=this.rowAlternateClass;
+				}else{
+					rows[i].className="";
+				}
+				idx++;
+			}
+		}
+	},
+
+	getObjectFromRow:function(/* HTMLTableRowElement */ row){
+		//	summary
+		//	creates a JSON object based on the passed row
+		var cells=row.getElementsByTagName("td");
+		var o={};
+		for(var i=0; i<this.columns.length;i++){
+			if(this.columns[i].sortType=="__markup__"){
+				//	FIXME: should we parse this instead?  Because if the user may not get back the markup they put in...
+				o[this.columns[i].getField()]=cells[i].innerHTML;
+			}else{
+				var text=dojo.html.renderedTextContent(cells[i]);
+				var val=new (this.columns[i].getType())(text);
+				o[this.columns[i].getField()]=val;
+			}
+		}
+		if(dojo.html.hasAttribute(row,"value")){
+			o[this.valueField]=dojo.html.getAttribute(row,"value");
+		}
+		return o;	//	object
+	},
+	setSelectionByRow:function(/* HTMLTableElementRow */ row){
+		//	summary
+		//	create the selection object based on the passed row, makes sure it's unique.
+		//	note that you need to call render manually (because of multi-select operations)
+		var o=this.getObjectFromRow(row);
+		var b=false;
+		for(var i=0;i<this.selected.length;i++){
+			if(this.compare(this.selected[i], o)){
+				b=true;
+				break;
+			}
+		}
+		if(!b){
+			this.selected.push(o);
+		}
+	},
+
+	parseColumns:function(/* HTMLTableHeadElement */ node){
+		//	summary
+		//	parses the passed element to create column objects
+		this.reset();
+		var row=node.getElementsByTagName("tr")[0];
+		var cells=row.getElementsByTagName("td");
+		if (cells.length==0) cells=row.getElementsByTagName("th");
+		for(var i=0; i<cells.length; i++){
+			var o={
+				field:null,
+				format:null,
+				noSort:false,
+				sortType:"String",
+				dataType:String,
+				sortFunction:null,
+				label:null,
+				align:"left",
+				valign:"middle",
+				getField:function(){ return this.field||this.label; },
+				getType:function(){ return this.dataType; }
+			};
+			//	presentation attributes
+			if(dojo.html.hasAttribute(cells[i], "align")){
+				o.align=dojo.html.getAttribute(cells[i],"align");
+			}
+			if(dojo.html.hasAttribute(cells[i], "valign")){
+				o.valign=dojo.html.getAttribute(cells[i],"valign");
+			}
+
+			//	sorting features.
+			if(dojo.html.hasAttribute(cells[i], "nosort")){
+				o.noSort=dojo.html.getAttribute(cells[i],"nosort")=="true";
+			}
+			if(dojo.html.hasAttribute(cells[i], "sortusing")){
+				var trans=dojo.html.getAttribute(cells[i],"sortusing");
+				var f=this.getTypeFromString(trans);
+				if (f!=null && f!=window && typeof(f)=="function") 
+					o.sortFunction=f;
+			}
+
+			if(dojo.html.hasAttribute(cells[i], "field")){
+				o.field=dojo.html.getAttribute(cells[i],"field");
+			}
+			if(dojo.html.hasAttribute(cells[i], "format")){
+				o.format=dojo.html.getAttribute(cells[i],"format");
+			}
+			if(dojo.html.hasAttribute(cells[i], "dataType")){
+				var sortType=dojo.html.getAttribute(cells[i],"dataType");
+				if(sortType.toLowerCase()=="html"||sortType.toLowerCase()=="markup"){
+					o.sortType="__markup__";	//	always convert to "__markup__"
+					o.noSort=true;
+				}else{
+					var type=this.getTypeFromString(sortType);
+					if(type){
+						o.sortType=sortType;
+						o.dataType=type;
+					}
+				}
+			}
+			o.label=dojo.html.renderedTextContent(cells[i]);
+			this.columns.push(o);
+
+			//	check to see if there's a default sort, and set the properties necessary
+			if(dojo.html.hasAttribute(cells[i], "sort")){
+				this.sortIndex=i;
+				var dir=dojo.html.getAttribute(cells[i], "sort");
+				if(!isNaN(parseInt(dir))){
+					dir=parseInt(dir);
+					this.sortDirection=(dir!=0)?1:0;
+				}else{
+					this.sortDirection=(dir.toLowerCase()=="desc")?1:0;
+				}
+			}
+		}
+	},
+
+	parseData:function(/* array */ data){
+		//	summary
+		//	Parse the passed JSON data structure, and cast based on columns.
+		this.data=[];
+		this.selected=[];
+		for(var i=0; i<data.length; i++){
+			var o={};	//	new data object.
+			for(var j=0; j<this.columns.length; j++){
+				var field=this.columns[j].getField();
+				if(this.columns[j].sortType=="__markup__"){
+					o[field]=String(data[i][field]);
+				}else{
+					var type=this.columns[j].getType();
+					var val=data[i][field];
+					var t=this.columns[j].sortType.toLowerCase();
+					if(val){
+						o[field]=new type(val);
+					}else{
+						o[field]=new type();	//	let it use the default.
+					}
+				}
+			}
+			//	check for the valueField if not already parsed.
+			if(data[i][this.valueField]&&!o[this.valueField]){
+				o[this.valueField]=data[i][this.valueField];
+			}
+			this.data.push(o);
+		}
+	}, 
+
+	parseDataFromTable:function(/* HTMLTableBodyElement */ tbody){
+		//	summary
+		//	parses the data in the tbody of a table to create a set of objects.
+		//	Will add objects to this.selected if an attribute 'selected="true"' is present on the row.
+		this.data=[];
+		this.selected=[];
+		var rows=tbody.getElementsByTagName("tr");
+		for(var i=0; i<rows.length; i++){
+			if(dojo.html.getAttribute(rows[i],"ignoreIfParsed")=="true"){
+				continue;
+			}
+			var o={};	//	new data object.
+			var cells=rows[i].getElementsByTagName("td");
+			for(var j=0; j<this.columns.length; j++){
+				var field=this.columns[j].getField();
+				if(this.columns[j].sortType=="__markup__"){
+					//	FIXME: parse this?
+					o[field]=cells[j].innerHTML;
+				}else{
+					var type=this.columns[j].getType();
+					var val=dojo.html.renderedTextContent(cells[j]); //	should be the same index as the column.
+					if (val) o[field]=new type(val);
+					else o[field]=new type();	//	let it use the default.
+				}
+			}
+			if(dojo.html.hasAttribute(rows[i],"value")&&!o[this.valueField]){
+				o[this.valueField]=dojo.html.getAttribute(rows[i],"value");
+			}
+			//	FIXME: add code to preserve row attributes in __metadata__ field?
+			this.data.push(o);
+			
+			//	add it to the selections if selected="true" is present.
+			if(dojo.html.getAttribute(rows[i],"selected")=="true"){
+				this.selected.push(o);
+			}
+		}
+	},
+	
+	showSelections:function(){
+		var body=this.domNode.getElementsByTagName("tbody")[0];
+		var rows=body.getElementsByTagName("tr");
+		var idx=0;
+		for(var i=0; i<rows.length; i++){
+			if(rows[i].parentNode==body){
+				if(dojo.html.getAttribute(rows[i],"selected")=="true"){
+					rows[i].className=this.rowSelectedClass;
+				} else {
+					if(this.enableAlternateRows&&idx%2==1){
+						rows[i].className=this.rowAlternateClass;
+					}else{
+						rows[i].className="";
+					}
+				}
+				idx++;
+			}
+		}
+	},
+	render:function(bDontPreserve){
+		//	summary
+		//	renders the table to the browser
+		var data=[];
+		var body=this.domNode.getElementsByTagName("tbody")[0];
+
+		if(!bDontPreserve){
+			//	rebuild data and selection
+			this.parseDataFromTable(body);
+		}
+
+		//	clone this.data for sorting purposes.
+		for(var i=0; i<this.data.length; i++){
+			data.push(this.data[i]);
+		}
+		
+		var col=this.columns[this.sortIndex];
+		if(!col.noSort){
+			var field=col.getField();
+			if(col.sortFunction){
+				var sort=col.sortFunction;
+			}else{
+				var sort=function(a,b){
+					if (a[field]>b[field]) return 1;
+					if (a[field]<b[field]) return -1;
+					return 0;
+				}
+			}
+			data.sort(sort);
+			if(this.sortDirection!=0) data.reverse();
+		}
+
+		//	build the table and pop it in.
+		while(body.childNodes.length>0) body.removeChild(body.childNodes[0]);
+		for(var i=0; i<data.length;i++){
+			var row=document.createElement("tr");
+			dojo.html.disableSelection(row);
+			if (data[i][this.valueField]){
+				row.setAttribute("value",data[i][this.valueField]);
+			}
+			if(this.isSelected(data[i])){
+				row.className=this.rowSelectedClass;
+				row.setAttribute("selected","true");
+			} else {
+				if(this.enableAlternateRows&&i%2==1){
+					row.className=this.rowAlternateClass;
+				}
+			}
+			for(var j=0;j<this.columns.length;j++){
+				var cell=document.createElement("td");
+				cell.setAttribute("align", this.columns[j].align);
+				cell.setAttribute("valign", this.columns[j].valign);
+				dojo.html.disableSelection(cell);
+				if(this.sortIndex==j){
+					cell.className=this.columnSelected;
+				}
+				if(this.columns[j].sortType=="__markup__"){
+					cell.innerHTML=data[i][this.columns[j].getField()];
+					for(var k=0; k<cell.childNodes.length; k++){
+						var node=cell.childNodes[k];
+						if(node&&node.nodeType==dojo.html.ELEMENT_NODE){
+							dojo.html.disableSelection(node);
+						}
+					}
+				}else{
+					if(this.columns[j].getType()==Date){
+						var format=this.defaultDateFormat;
+						if(this.columns[j].format) format=this.columns[j].format;
+						cell.appendChild(document.createTextNode(dojo.date.format(data[i][this.columns[j].getField()], format)));
+					}else{
+						cell.appendChild(document.createTextNode(data[i][this.columns[j].getField()]));
+					}
+				}
+				row.appendChild(cell);
+			}
+			body.appendChild(row);
+			dojo.event.connect(row, "onclick", this, "onUISelect");
+		}
+		
+		//	if minRows exist.
+		var minRows=parseInt(this.minRows);
+		if (!isNaN(minRows) && minRows>0 && data.length<minRows){
+			var mod=0;
+			if(data.length%2==0) mod=1;
+			var nRows=minRows-data.length;
+			for(var i=0; i<nRows; i++){
+				var row=document.createElement("tr");
+				row.setAttribute("ignoreIfParsed","true");
+				if(this.enableAlternateRows&&i%2==mod){
+					row.className=this.rowAlternateClass;
+				}
+				for(var j=0;j<this.columns.length;j++){
+					var cell=document.createElement("td");
+					cell.appendChild(document.createTextNode("\u00A0"));
+					row.appendChild(cell);
+				}
+				body.appendChild(row);
+			}
+		}
+	},
+
+	//	the following the user can override.
+	onSelect:function(/* DomEvent */ e){ 
+		//	summary
+		//	empty function for the user to attach code to, fired by onUISelect
+	},
+	onUISelect:function(/* DomEvent */ e){
+		//	summary
+		//	fired when a user selects a row
+		var row=dojo.html.getParentByType(e.target,"tr");
+		var body=dojo.html.getParentByType(row,"tbody");
+		if(this.enableMultipleSelect){
+			if(e.metaKey||e.ctrlKey){
+				if(this.isSelected(this.getObjectFromRow(row))){
+					this.removeFromSelected(this.getObjectFromRow(row));
+					row.removeAttribute("selected");
+				}else{
+					//	push onto the selection stack.
+					this.setSelectionByRow(row);
+					row.setAttribute("selected","true");
+				}
+			}else if(e.shiftKey){
+				//	the tricky one.  We need to figure out the *last* selected row above, 
+				//	and select all the rows in between.
+				var startRow;
+				var rows=body.getElementsByTagName("tr");
+				//	if there's a selection above, we go with that first. 
+				for(var i=0;i<rows.length;i++){
+					if(rows[i].parentNode==body){
+						if(rows[i]==row) break;
+						if(dojo.html.getAttribute(rows[i],"selected")=="true"){
+							startRow=rows[i];
+						}
+					}
+				}
+				//	if there isn't a selection above, we continue with a selection below.
+				if(!startRow){
+					startRow=row;
+					for(;i<rows.length;i++){
+						if(dojo.html.getAttribute(rows[i],"selected")=="true"){
+							row=rows[i];
+							break;
+						}
+					}
+				}
+				this.resetSelections(body);
+				if(startRow==row){
+					//	this is the only selection
+					row.setAttribute("selected","true");
+					this.setSelectionByRow(row);
+				}else{
+					var doSelect=false;
+					for(var i=0; i<rows.length; i++){
+						if(rows[i].parentNode==body){
+							rows[i].removeAttribute("selected");
+							if(rows[i]==startRow){
+								doSelect=true;
+							}
+							if(doSelect){
+								this.setSelectionByRow(rows[i]);
+								rows[i].setAttribute("selected","true");
+							}
+							if(rows[i]==row){
+								doSelect=false;
+							}
+						}
+					}
+				}
+			}else{
+				//	reset the selection
+				this.resetSelections(body);
+				row.setAttribute("selected","true");
+				this.setSelectionByRow(row);
+			}
+		}else{
+			//	reset the data selection and go.
+			this.resetSelections(body);
+			row.setAttribute("selected","true");
+			this.setSelectionByRow(row);
+		}
+		this.showSelections();
+		this.onSelect(e);
+		e.stopPropagation();
+		e.preventDefault();
+	},
+	onHeaderClick:function(/* DomEvent */ e){
+		//	summary
+		//	Main handler function for each header column click.
+		var oldIndex=this.sortIndex;
+		var oldDirection=this.sortDirection;
+		var source=e.target;
+		var row=dojo.html.getParentByType(source,"tr");
+		var cellTag="td";
+		if(row.getElementsByTagName(cellTag).length==0) cellTag="th";
+
+		var headers=row.getElementsByTagName(cellTag);
+		var header=dojo.html.getParentByType(source,cellTag);
+		
+		for(var i=0; i<headers.length; i++){
+			if(headers[i]==header){
+				if(i!=oldIndex){
+					//	new col.
+					this.sortIndex=i;
+					this.sortDirection=0;
+					headers[i].className=this.headerSortDownClass
+				}else{
+					this.sortDirection=(oldDirection==0)?1:0;
+					if(this.sortDirection==0){
+						headers[i].className=this.headerSortDownClass;
+					}else{
+						headers[i].className=this.headerSortUpClass;
+					}
+				}
+			}else{
+				//	reset the header class.
+				headers[i].className=this.headerClass;
+			}
+		}
+		this.render();
+	},
+
+	postCreate:function(){ 
+		// 	summary
+		//	overridden from HtmlWidget, initializes and renders the widget.
+		var thead=this.domNode.getElementsByTagName("thead")[0];
+		if(this.headClass.length>0){
+			thead.className=this.headClass;
+		}
+
+		//	disable selections
+		dojo.html.disableSelection(this.domNode);
+
+		//	parse the columns.
+		this.parseColumns(thead);
+
+		//	attach header handlers.
+		var header="td";
+		if(thead.getElementsByTagName(header).length==0) header="th";
+		var headers=thead.getElementsByTagName(header);
+		for(var i=0; i<headers.length; i++){
+			if(!this.columns[i].noSort){
+				dojo.event.connect(headers[i], "onclick", this, "onHeaderClick");
+			}
+			if(this.sortIndex==i){
+				if(this.sortDirection==0){
+					headers[i].className=this.headerSortDownClass;
+				}else{
+					headers[i].className=this.headerSortUpClass;
+				}
+			}
+		}
+
+		//	parse the tbody element and re-render it.
+		var tbody=this.domNode.getElementsByTagName("tbody")[0];
+		if (this.tbodyClass.length>0) {
+			tbody.className=this.tbodyClass;
+		}
+
+		this.parseDataFromTable(tbody);
+		this.render(true);
+	}
+});

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/Spinner.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/Spinner.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/Spinner.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/Spinner.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,383 @@
+/*
+	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.html.Spinner");
+dojo.require("dojo.widget.Spinner");
+dojo.require("dojo.widget.Manager.*");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.io.*");
+dojo.require("dojo.lfx.*");
+dojo.require("dojo.dom");
+dojo.require("dojo.html");
+dojo.require("dojo.string");
+dojo.require("dojo.widget.html.stabile");
+
+dojo.widget.html.Spinner = function(){
+	dojo.widget.Spinner.call(this);
+	dojo.widget.HtmlWidget.call(this);
+}
+
+dojo.inherits(dojo.widget.html.Spinner, dojo.widget.HtmlWidget);
+
+// copied from superclass since we can't really over-ride via prototype
+dojo.lang.extend(dojo.widget.html.Spinner, dojo.widget.Spinner.defaults);
+
+dojo.lang.extend(dojo.widget.html.Spinner, {
+
+	name: "", // clone in the name from the DOM node
+	inputNode: null,
+	upArrowNode: null,
+	downArrowNode: null,
+	absNode: null,
+	relNode: null,
+	innerRelNode: null,
+	spacerNode: null,
+	inputWidgetId: "",
+	inputWidget: null,
+	typamaticTimer: null,
+	typamaticFunction: null,
+	defaultTimeout: 500,
+	currentTimeout: this.defaultTimeout,
+	eventCount: 0,
+
+	templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlSpinner.html"),
+	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlSpinner.css"),
+
+	setValue: function(value){
+		this.inputWidget.setValue(value);
+		this.inputWidget.adjustValue(0);
+		dojo.widget.html.stabile.setState(this.widgetId, this.getState(), true);
+	},
+
+	getValue: function(){
+		return this.inputWidget.getValue();
+	},
+
+	getState: function(){
+		return {value: this.getValue()};
+	},
+
+	setState: function(state){
+		this.setValue(state.value);
+	},
+
+	// does the keyboard related stuff
+	_handleKeyEvents: function(evt){
+		var k = dojo.event.browser.keys;
+		var keyCode = evt.keyCode;
+
+		switch(keyCode){
+ 			case k.KEY_DOWN_ARROW:
+				dojo.event.browser.stopEvent(evt);
+				this.downArrowPressed(evt);
+				return;
+			case k.KEY_UP_ARROW:
+				dojo.event.browser.stopEvent(evt);
+				this.upArrowPressed(evt);
+				return;
+		}
+		this.eventCount++;
+
+	},
+
+	onKeyDown: function(evt){
+		// IE needs to stop keyDown others need to stop keyPress
+		if(!document.createEvent){ // only IE
+			this._handleKeyEvents(evt);
+		}
+	},
+
+	onKeyPress: function(evt){
+		if(document.createEvent){ // never IE
+			this._handleKeyEvents(evt);
+		}
+	},
+
+	fillInTemplate: function(args, frag){
+		var source = this.getFragNodeRef(frag);
+		dojo.html.copyStyle(this.domNode, source);
+	},
+
+
+	resizeUpArrow: function(){
+		var newh = dojo.style.getContentBoxHeight(this.inputNode) >> 1;
+		if(newh==0){
+			// need more time to calculate size
+			dojo.lang.setTimeout(this, "resizeUpArrow", 100);
+			return;
+		}
+		var oldh = this.upArrowNode.height;
+		if(oldh==0){
+			// need more time to calculate size
+			dojo.lang.setTimeout(this, "resizeUpArrow", 100);
+			return;
+		}
+		var ratio = newh / oldh;
+		this.upArrowNode.width=Math.floor(this.upArrowNode.width * ratio);
+		this.upArrowNode.height=newh;
+	},
+
+	resizeDownArrow: function(){
+		var newh = dojo.style.getContentBoxHeight(this.inputNode) >> 1;
+		if(newh==0){
+			// need more time to calculate size
+			dojo.lang.setTimeout(this, "resizeDownArrow", 100);
+			return;
+		}
+		var oldh = this.downArrowNode.height;
+		if(oldh==0){
+			// need more time to calculate size
+			dojo.lang.setTimeout(this, "resizeDownArrow", 100);
+			return;
+		}
+		var ratio = newh / oldh;
+		this.downArrowNode.width=Math.floor(this.downArrowNode.width * ratio);
+		this.downArrowNode.height=newh;
+	},
+
+	resizeSpacer: function(){
+		var newh = dojo.style.getContentBoxHeight(this.inputNode) >> 1;
+		if( newh==0 ){
+			// need more time to calculate size
+			dojo.lang.setTimeout(this, "resizeSpacer", 100);
+			return;
+		}
+		var oldh = this.downArrowNode.height;
+		if( oldh==0 ){
+			// need more time to calculate size
+			dojo.lang.setTimeout(this, "resizeSpacer", 100);
+			return;
+		}
+		var ratio = newh / oldh;
+		this.spacerNode.width=Math.floor(this.spacerNode.width * ratio);
+		this.spacerNode.height=newh;
+	},
+
+	_pressButton: function(node){
+		with(node.style){
+			borderRight = "0px";
+			borderBottom = "0px";
+			borderLeft = "1px solid black";
+			borderTop = "1px solid black";
+		}
+	},
+
+	_releaseButton: function(node){
+		with(node.style){
+			borderLeft = "0px";
+			borderTop = "0px";
+			borderRight = "1px solid gray";
+			borderBottom = "1px solid gray";
+		}
+	},
+
+	downArrowPressed: function(evt){
+		if(typeof evt != "number"){
+		    if(this.typamaticTimer != null){
+				if(this.typamaticFunction == this.downArrowPressed){
+					return;
+				}
+		        clearTimeout(this.typamaticTimer);
+		    }
+		    this._releaseButton(this.upArrowNode);
+		    this.eventCount++;
+		    this.typamaticTimer = null;
+		    this.currentTimeout = this.defaultTimeout;
+
+		}else if (evt != this.eventCount){
+		    this._releaseButton(this.downArrowNode);
+		    return;
+		}
+		this._pressButton(this.downArrowNode);
+		this.setCursorX(this.inputWidget.adjustValue(-1,this.getCursorX()));
+		this.typamaticFunction = this.downArrowPressed;
+		this.typamaticTimer = setTimeout( dojo.lang.hitch(this,function(){this.downArrowPressed(this.eventCount);}), this.currentTimeout);
+		this.currentTimeout = Math.round(this.currentTimeout * 90 / 100);
+	},
+
+	upArrowPressed: function(evt){
+		if(typeof evt != "number"){
+		    if(this.typamaticTimer != null){
+				if(this.typamaticFunction == this.upArrowPressed){
+					return;
+				}
+		        clearTimeout(this.typamaticTimer);
+		    }
+		    this._releaseButton(this.downArrowNode);
+		    this.eventCount++;
+		    this.typamaticTimer = null;
+		    this.currentTimeout = this.defaultTimeout;
+		}else if(evt != this.eventCount) {
+		    this._releaseButton(this.upArrowNode);
+		    return;
+		}
+		this._pressButton(this.upArrowNode);
+		this.setCursorX(this.inputWidget.adjustValue(+1,this.getCursorX()));
+		this.typamaticFunction = this.upArrowPressed;
+		this.typamaticTimer = setTimeout( dojo.lang.hitch(this,function(){this.upArrowPressed(this.eventCount);}), this.currentTimeout);
+		this.currentTimeout = Math.round(this.currentTimeout * 90 / 100);
+	},
+
+	arrowReleased: function(evt){
+		this.inputNode.focus();
+		if(evt.keyCode && evt.keyCode != null){
+			var keyCode = evt.keyCode;
+			var k = dojo.event.browser.keys;
+
+			switch(keyCode){
+				case k.KEY_DOWN_ARROW:
+				case k.KEY_UP_ARROW:
+					dojo.event.browser.stopEvent(evt);
+					break;
+			}
+		}
+		this._releaseButton(this.upArrowNode);
+		this._releaseButton(this.downArrowNode);
+		this.eventCount++;
+		if(this.typamaticTimer != null){
+		    clearTimeout(this.typamaticTimer);
+		}
+		this.typamaticTimer = null;
+		this.currentTimeout = this.defaultTimeout;
+	},
+
+	mouseWheeled: function(evt) {
+		var scrollAmount = 0;
+		if(typeof evt.wheelDelta == 'number'){ // IE
+		    scrollAmount = evt.wheelDelta;
+		}else if (typeof evt.detail == 'number'){ // Mozilla+Firefox
+		    scrollAmount = -evt.detail;
+		}
+		if(scrollAmount > 0){
+		    this.upArrowPressed(evt);
+		    this.arrowReleased(evt);
+		}else if (scrollAmount < 0){
+		    this.downArrowPressed(evt);
+		    this.arrowReleased(evt);
+		}
+	},
+
+	getCursorX: function(){
+		var x = -1;
+		try{
+		    this.inputNode.focus();
+		    if (typeof this.inputNode.selectionEnd == "number"){
+				x = this.inputNode.selectionEnd;
+		    }else if (document.selection && document.selection.createRange) {
+				var range = document.selection.createRange().duplicate();
+				if(range.parentElement() == this.inputNode){
+					range.moveStart('textedit', -1);
+					x = range.text.length;
+				}
+		    }
+		}catch(e){ /* squelch! */ }
+		return x;
+	},
+
+	setCursorX: function(x){
+		try{
+			this.inputNode.focus();
+		    if(!x){ x = 0 }
+		    if(typeof this.inputNode.selectionEnd == "number"){
+		        this.inputNode.selectionEnd = x;
+		    }else if(this.inputNode.createTextRange){
+		        var range = this.inputNode.createTextRange();
+		        range.collapse(true);
+		        range.moveEnd('character', x);
+		        range.moveStart('character', x);
+		        range.select();
+		    }
+		}catch(e){ /* squelch! */ }
+	},
+
+	postCreate: function(){
+		this.domNode.style.display="none";
+
+		if((typeof this.inputWidgetId != 'string')||(this.inputWidgetId.length == 0)){
+		    var w=dojo.widget.manager.getAllWidgets();
+		    for(var i=w.length-1; i>=0; i--){
+		        if(w[i].adjustValue){
+					this.inputWidget = w[i];
+					break;
+		        }
+		    }
+		}else{
+		    this.inputWidget = dojo.widget.getWidgetById(this.inputWidgetId);
+		}
+
+		if(typeof this.inputWidget != 'object'){
+			dojo.lang.setTimeout(this, "postCreate", 100); 
+			return;
+		}
+		var widgetNode = this.inputWidget.domNode;
+		var inputNodes = widgetNode.getElementsByTagName('INPUT');
+		this.inputNode = inputNodes[0];
+
+		/*
+		// unlink existing dom nodes from domNode
+		this.downArrowNode = dojo.dom.removeNode(this.downArrowNode);
+		this.upArrowNode = dojo.dom.removeNode(this.upArrowNode);
+		this.spacerNode = dojo.dom.removeNode(this.spacerNode);
+		this.innerRelNode = dojo.dom.removeNode(this.innerRelNode);
+		this.absNode = dojo.dom.removeNode(this.absNode);
+		this.relNode = dojo.dom.removeNode(this.relNode);
+		*/
+
+		// create a disconnected node
+		this.innerRelNode.appendChild(this.upArrowNode);
+		this.innerRelNode.appendChild(this.downArrowNode);
+		this.absNode.appendChild(this.innerRelNode);
+		this.relNode.appendChild(this.absNode);
+		this.relNode.appendChild(this.spacerNode);
+
+		dojo.event.connect(this.inputNode, "onkeypress", this, "onKeyPress");
+		dojo.event.connect(this.inputNode, "onkeydown", this, "onKeyDown");
+		dojo.event.connect(this.inputNode, "onkeyup", this, "arrowReleased");
+		dojo.event.connect(this.downArrowNode, "onmousedown", this, "downArrowPressed");
+		dojo.event.connect(this.downArrowNode, "onmouseup", this, "arrowReleased");
+		dojo.event.connect(this.upArrowNode, "onmousedown", this, "upArrowPressed");
+		dojo.event.connect(this.upArrowNode, "onmouseup", this, "arrowReleased");
+		if(this.inputNode.addEventListener){
+			// FIXME: why not use dojo.event.connect() to DOMMouseScroll here?
+		    this.inputNode.addEventListener('DOMMouseScroll', dojo.lang.hitch(this, "mouseWheeled"), false); // Mozilla + Firefox + Netscape
+		}else{
+		    dojo.event.connect(this.inputNode, "onmousewheel", this, "mouseWheeled"); // IE + Safari
+		}
+
+		this.resizeDownArrow();
+		this.resizeUpArrow();
+		this.resizeSpacer();
+
+		// make sure the disconnected node will fit right next to the INPUT tag w/o any interference
+		dojo.html.copyStyle(this.relNode, this.inputNode);
+		with(this.relNode.style){
+			display = "inline";
+			position = "relative";
+			backgroundColor = "";
+			marginLeft = "-1px";
+			paddingLeft = "0";
+		}
+		this.inputNode.style.marginRight = "0px";
+		this.inputNode.style.paddingRight = "0px";
+
+		// add the disconnected node right after the INPUT tag
+		dojo.dom.insertAfter(this.relNode, this.inputNode, false);
+		this.domNode = dojo.dom.removeNode(this.domNode);
+		// realign the spinner vertically in case there's a slight difference
+		var absOffset = dojo.html.getAbsoluteY(this.relNode,true)-dojo.html.getAbsoluteY(this.absNode,true);
+		this.absNode.style.top = absOffset-dojo.style.getBorderExtent(this.inputNode, "top")+"px";
+
+		var s = dojo.widget.html.stabile.getState(this.widgetId);
+		this.setValue(this.getValue());
+		if(s){
+			this.setState(s);
+		}
+	}
+});

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/TaskBar.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/TaskBar.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/TaskBar.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/TaskBar.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,85 @@
+/*
+	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.html.TaskBar");
+dojo.provide("dojo.widget.html.TaskBarItem");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.FloatingPane");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.event");
+
+// Icon associated w/a floating pane
+dojo.widget.html.TaskBarItem = function(){
+	dojo.widget.TaskBarItem.call(this);
+	dojo.widget.HtmlWidget.call(this);
+}
+dojo.inherits(dojo.widget.html.TaskBarItem, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.html.TaskBarItem, {
+	// constructor arguments
+	iconSrc: '',
+	caption: 'Untitled',
+	window: null,
+	templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlTaskBarItemTemplate.html"),
+	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlTaskBar.css"),
+
+	fillInTemplate: function() {
+		if ( this.iconSrc != '' ) {
+			var img = document.createElement("img");
+			img.src = this.iconSrc;
+			this.domNode.appendChild(img);
+		}
+		this.domNode.appendChild(document.createTextNode(this.caption));
+		dojo.html.disableSelection(this.domNode);
+	},
+
+	postCreate: function() {
+		this.window=dojo.widget.getWidgetById(this.windowId);
+		this.window.explodeSrc = this.domNode;
+		dojo.event.connect(this.window, "destroy", this, "destroy")
+	},
+
+	onClick: function() {
+		this.window.show();
+	}
+});
+
+// Collection of widgets in a bar, like Windows task bar
+dojo.widget.html.TaskBar = function(){
+
+	dojo.widget.html.FloatingPane.call(this);
+	dojo.widget.TaskBar.call(this);
+	this._addChildStack = [];
+}
+
+dojo.inherits(dojo.widget.html.TaskBar, dojo.widget.html.FloatingPane);
+
+dojo.lang.extend(dojo.widget.html.TaskBar, {
+
+	resizable: false,
+	titleBarDisplay: "none",
+
+	addChild: function(child) {
+		if(!this.containerNode){ 
+			this._addChildStack.push(child);
+		}else if(this._addChildStack.length > 0){
+			var oarr = this._addChildStack;
+			this._addChildStack = [];
+			dojo.lang.forEach(oarr, this.addChild, this);
+		}
+		var tbi = dojo.widget.createWidget("TaskBarItem",
+			{	windowId: child.widgetId, 
+				caption: child.title, 
+				iconSrc: child.iconSrc
+			});
+		dojo.widget.html.TaskBar.superclass.addChild.call(this,tbi);
+	}
+});

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/YahooMap.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/YahooMap.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/YahooMap.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/YahooMap.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,180 @@
+/*
+	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.html.YahooMap");
+dojo.require("dojo.event.*");
+dojo.require("dojo.html");
+dojo.require("dojo.math");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.widget.YahooMap");
+
+(function(){
+	var yappid = djConfig["yAppId"]||djConfig["yahooAppId"]||"dojotoolkit";
+	if(!dojo.hostenv.post_load_){
+		if(yappid == "dojotoolkit"){
+			dojo.debug("please provide a unique Yahoo App ID in djConfig.yahooAppId when using the map widget");
+		}
+		var tag = "<scr"+"ipt src='http://api.maps.yahoo.com/ajaxymap?v=3.0&appid="+yappid+"'></scri"+"pt>";
+		if(!dj_global["YMap"]){
+			document.write(tag);
+		}
+	}else{
+		dojo.debug("cannot initialize map system after the page has been loaded! Please either manually include the script block provided by Yahoo in your page or require() the YahooMap widget before onload has fired");
+	}
+})();
+
+dojo.widget.html.YahooMap=function(){
+	dojo.widget.HtmlWidget.call(this);
+	dojo.widget.YahooMap.call(this);
+
+	this.map=null;
+	this.datasrc="";
+	this.data=[];
+	this.width=0;
+	this.height=0;
+	this.controls=["zoomlong","maptype","pan"];
+};
+dojo.inherits(dojo.widget.html.YahooMap, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.html.YahooMap, {
+	widgetType: "YahooMap",
+	templatePath:null,
+	templateCssPath:null,
+
+	findCenter:function(aPts){
+		var start=new YGeoPoint(37,-90);
+		if(aPts.length==0) return start;
+		var minLat,maxLat, minLon, maxLon, cLat, cLon;
+		minLat=maxLat=aPts[0].Lat;
+		minLon=maxLon=aPts[0].Lon;
+		for(var i=0; i<aPts.length; i++){
+			minLat=Math.min(minLat,aPts[i].Lat);
+			maxLat=Math.max(maxLat,aPts[i].Lat);
+			minLon=Math.min(minLon,aPts[i].Lon);
+			maxLon=Math.max(maxLon,aPts[i].Lon);
+		}
+		cLat=dojo.math.round((minLat+maxLat)/2,6);
+		cLon=dojo.math.round((minLon+maxLon)/2,6);
+		return new YGeoPoint(cLat,cLon);
+	},
+	setControls:function(){
+		var c=this.controls;
+		var t=dojo.widget.YahooMap.Controls;
+		for(var i=0; i<c.length; i++){
+			switch(c[i]){
+				case t.MapType:{
+					this.map.addTypeControl();
+					break;
+				}
+				case t.Pan:{
+					this.map.addPanControl();
+					break;
+				}
+				case t.ZoomLong:{
+					this.map.addZoomLong();
+					break;
+				}
+				case t.ZoomShort:{
+					this.map.addZoomShort();
+					break;
+				}
+			}
+		}
+	},
+	
+	parse:function(table){
+		this.data=[];
+
+		//	get the column indices
+		var h=table.getElementsByTagName("thead")[0];
+		if(!h){
+			return;
+		}
+
+		var a=[];
+		var cols=h.getElementsByTagName("td");
+		if(cols.length==0){
+			cols=h.getElementsByTagName("th");
+		}
+		for(var i=0; i<cols.length; i++){
+			var c=cols[i].innerHTML.toLowerCase();
+			if(c=="long") c="lng";
+			a.push(c);
+		}
+		
+		//	parse the data
+		var b=table.getElementsByTagName("tbody")[0];
+		if(!b){
+			return;
+		}
+		for(var i=0; i<b.childNodes.length; i++){
+			if(!(b.childNodes[i].nodeName&&b.childNodes[i].nodeName.toLowerCase()=="tr")){
+				continue;
+			}
+			var cells=b.childNodes[i].getElementsByTagName("td");
+			var o={};
+			for(var j=0; j<a.length; j++){
+				var col=a[j];
+				if(col=="lat"||col=="lng"){
+					o[col]=parseFloat(cells[j].innerHTML);					
+				}else{
+					o[col]=cells[j].innerHTML;
+				}
+			}
+			this.data.push(o);
+		}
+	},
+	render:function(){
+		var pts=[];
+		var d=this.data;
+		for(var i=0; i<d.length; i++){
+			var pt=new YGeoPoint(d[i].lat, d[i].lng);
+			pts.push(pt);
+			var icon=d[i].icon||null;
+			if(icon){
+				icon=new YImage(icon);
+			}
+			var m=new YMarker(pt,icon);
+			if(d[i].description){
+				m.addAutoExpand("<div>"+d[i].description+"</div>");
+			}
+			this.map.addOverlay(m);
+		}
+		var c=this.findCenter(pts);
+		var z=this.map.getZoomLevel(pts);
+		this.map.drawZoomAndCenter(c,z);
+	},
+	
+	initialize:function(args, frag){
+		if(!YMap || !YGeoPoint){
+			dojo.raise("dojo.widget.YahooMap: The Yahoo Map script must be included in order to use this widget.");
+		}
+		if(this.datasrc){
+			this.parse(dojo.byId(this.datasrc));
+		}
+		else if(this.domNode.getElementsByTagName("table")[0]){
+			this.parse(this.domNode.getElementsByTagName("table")[0]);
+		}
+	},
+	postCreate:function(){
+		//	clean the domNode before creating the map.
+		while(this.domNode.childNodes.length>0){
+			this.domNode.removeChild(this.domNode.childNodes[0]);
+		}
+
+		if(this.width>0&&this.height>0){
+			this.map=new YMap(this.domNode, YAHOO_MAP_REG, new YSize(this.width, this.height));
+		}else{
+			this.map=new YMap(this.domNode);
+		}
+		this.setControls();
+		this.render();
+	}
+});

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/svg/Chart.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/svg/Chart.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/svg/Chart.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/svg/Chart.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,531 @@
+/*
+	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.svg.Chart");
+
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.widget.Chart");
+dojo.require("dojo.math");
+dojo.require("dojo.html");
+dojo.require("dojo.svg");
+dojo.require("dojo.graphics.color");
+
+dojo.widget.svg.Chart=function(){
+	dojo.widget.Chart.call(this);
+	dojo.widget.HtmlWidget.call(this);
+};
+dojo.inherits(dojo.widget.svg.Chart, dojo.widget.HtmlWidget);
+dojo.lang.extend(dojo.widget.svg.Chart, {
+	//	widget props
+	templatePath:null,
+	templateCssPath:null,
+
+	//	state
+	_isInitialized:false,
+	hasData:false,
+
+	//	chart props
+	vectorNode:null,
+	plotArea:null,
+	dataGroup:null,
+	axisGroup:null,
+
+	properties:{
+		height:400,	//	defaults, will resize to the domNode.
+		width:600,
+		plotType:null,
+		padding:{
+			top:10,
+			bottom:2,
+			left:60,
+			right:30
+		},
+		axes:{
+			x:{
+				plotAt:0,
+				label:"",
+				unitLabel:"",
+				unitType:Number,
+				nUnitsToShow:10,
+				range:{
+					min:0,
+					max:200
+				}
+			},
+			y:{
+				plotAt:0,
+				label:"",
+				unitLabel:"",
+				unitType:Number,
+				nUnitsToShow:10,
+				range:{
+					min:0,
+					max:200
+				}
+			}
+		}
+	},
+	
+	fillInTemplate:function(args,frag){
+		this.initialize();
+		this.render();
+	},
+	parseData:function(){
+	},
+	initialize:function(){
+		this.parseData();
+	
+		//	begin by grabbing the table, and reading it in.
+		var table=this.domNode.getElementsByTagName("table")[0];
+		if (!table) return;
+		
+		var bRangeX=false;
+		var bRangeY=false;
+		
+		//	properties off the table
+		if (table.getAttribute("width")) this.properties.width=table.getAttribute("width");
+		if (table.getAttribute("height")) this.properties.height=table.getAttribute("height");
+		if (table.getAttribute("plotType")) this.properties.plotType=table.getAttribute("plotType");
+		if (table.getAttribute("padding")){
+			if (table.getAttribute("padding").indexOf(",") > -1)
+				var p=table.getAttribute("padding").split(","); 
+			else var p=table.getAttribute("padding").split(" ");
+			if (p.length==1){
+				var pad=parseFloat(p[0]);
+				this.properties.padding.top=pad;
+				this.properties.padding.right=pad;
+				this.properties.padding.bottom=pad;
+				this.properties.padding.left=pad;
+			} else if(p.length==2){
+				var padV=parseFloat(p[0]);
+				var padH=parseFloat(p[1]);
+				this.properties.padding.top=padV;
+				this.properties.padding.right=padH;
+				this.properties.padding.bottom=padV;
+				this.properties.padding.left=padH;
+			} else if(p.length==4){
+				this.properties.padding.top=parseFloat(p[0]);
+				this.properties.padding.right=parseFloat(p[1]);
+				this.properties.padding.bottom=parseFloat(p[2]);
+				this.properties.padding.left=parseFloat(p[3]);
+			}
+		}
+		if (table.getAttribute("rangeX")){
+			var p=table.getAttribute("rangeX");
+			if (p.indexOf(",")>-1) p=p.split(",");
+			else p=p.split(" ");
+			this.properties.axes.x.range.min=parseFloat(p[0]);
+			this.properties.axes.x.range.max=parseFloat(p[1]);
+			bRangeX=true;
+		}
+		if (table.getAttribute("rangeY")){
+			var p=table.getAttribute("rangeY");
+			if (p.indexOf(",")>-1) p=p.split(",");
+			else p=p.split(" ");
+			this.properties.axes.y.range.min=parseFloat(p[0]);
+			this.properties.axes.y.range.max=parseFloat(p[1]);
+			bRangeY=true;
+		}
+
+		var thead=table.getElementsByTagName("thead")[0];
+		var tbody=table.getElementsByTagName("tbody")[0];
+		if(!(thead&&tbody)) dojo.raise("dojo.widget.Chart: supplied table must define a head and a body.");
+
+		//	set up the series.
+		var columns=thead.getElementsByTagName("tr")[0].getElementsByTagName("th");	//	should be <tr><..>
+		
+		//	assume column 0 == X
+		for (var i=1; i<columns.length; i++){
+			var key="column"+i;
+			var label=columns[i].innerHTML;
+			var plotType=columns[i].getAttribute("plotType")||"line";
+			var color=columns[i].getAttribute("color");
+			var ds=new dojo.widget.Chart.DataSeries(key,label,plotType,color);
+			this.series.push(ds);
+		}
+
+		//	ok, get the values.
+		var rows=tbody.getElementsByTagName("tr");
+		var xMin=Number.MAX_VALUE,xMax=Number.MIN_VALUE;
+		var yMin=Number.MAX_VALUE,yMax=Number.MIN_VALUE;
+		var ignore = [
+			"accesskey","align","bgcolor","class",
+			"colspan","height","id","nowrap",
+			"rowspan","style","tabindex","title",
+			"valign","width"
+		];
+
+		for(var i=0; i<rows.length; i++){
+			var row=rows[i];
+			var cells=row.getElementsByTagName("td");
+			var x=Number.MIN_VALUE;
+			for (var j=0; j<cells.length; j++){
+				if (j==0){
+					x=parseFloat(cells[j].innerHTML);
+					xMin=Math.min(xMin, x);
+					xMax=Math.max(xMax, x);
+				} else {
+					var ds=this.series[j-1];
+					var y=parseFloat(cells[j].innerHTML);
+					yMin=Math.min(yMin,y);
+					yMax=Math.max(yMax,y);
+					var o={x:x, value:y};
+					var attrs=cells[j].attributes;
+					for(var k=0; k<attrs.length; k++){
+						var attr=attrs.item(k);
+						var bIgnore=false;
+						for (var l=0; l<ignore.length; l++){
+							if (attr.nodeName.toLowerCase()==ignore[l]){
+								bIgnore=true;
+								break;
+							}
+						}
+						if(!bIgnore) o[attr.nodeName]=attr.nodeValue;
+					}
+					ds.add(o);
+				}
+			}
+		}
+
+		//	fix the axes
+		if(!bRangeX){
+			this.properties.axes.x.range={min:xMin, max:xMax};
+		}
+		if(!bRangeY){
+			this.properties.axes.y.range={min:yMin, max:yMax};
+		}
+
+		//	where to plot the axes
+		if (table.getAttribute("axisAt")){
+			var p=table.getAttribute("axisAt");
+			if (p.indexOf(",")>-1) p=p.split(",");
+			else p=p.split(" ");
+			
+			//	x axis
+			if (!isNaN(parseFloat(p[0]))){
+				this.properties.axes.x.plotAt=parseFloat(p[0]);
+			} else if (p[0].toLowerCase()=="ymin"){
+				this.properties.axes.x.plotAt=this.properties.axes.y.range.min;
+			} else if (p[0].toLowerCase()=="ymax"){
+				this.properties.axes.x.plotAt=this.properties.axes.y.range.max;
+			}
+
+			// y axis
+			if (!isNaN(parseFloat(p[1]))){
+				this.properties.axes.y.plotAt=parseFloat(p[1]);
+			} else if (p[1].toLowerCase()=="xmin"){
+				this.properties.axes.y.plotAt=this.properties.axes.x.range.min;
+			} else if (p[1].toLowerCase()=="xmax"){
+				this.properties.axes.y.plotAt=this.properties.axes.x.range.max;
+			}
+		} else {
+			this.properties.axes.x.plotAt=this.properties.axes.y.range.min;
+			this.properties.axes.y.plotAt=this.properties.axes.x.range.min;
+		}
+
+		//	table values should be populated, now pop it off.
+		this.domNode.removeChild(table);
+
+		//	get the width and the height.
+//		this.properties.width=dojo.html.getInnerWidth(this.domNode);
+//		this.properties.height=dojo.html.getInnerHeight(this.domNode);
+
+		// ok, lets create the chart itself.
+		dojo.svg.g.suspend();		
+		if(this.vectorNode) this.destroy();
+		this.vectorNode=document.createElementNS(dojo.svg.xmlns.svg, "svg");
+		this.vectorNode.setAttribute("width", this.properties.width);
+		this.vectorNode.setAttribute("height", this.properties.height);
+
+		//	set up the clip path for the plot area.
+		var defs = document.createElementNS(dojo.svg.xmlns.svg, "defs");
+		var clip = document.createElementNS(dojo.svg.xmlns.svg, "clipPath");
+		clip.setAttribute("id","plotClip"+this.widgetId);
+		var rect = document.createElementNS(dojo.svg.xmlns.svg, "rect");		
+		rect.setAttribute("x", this.properties.padding.left);
+		rect.setAttribute("y", this.properties.padding.top);
+		rect.setAttribute("width", this.properties.width-this.properties.padding.left-this.properties.padding.right);
+		rect.setAttribute("height", this.properties.height-this.properties.padding.bottom-this.properties.padding.bottom);
+		clip.appendChild(rect);
+		defs.appendChild(clip);
+		this.vectorNode.appendChild(defs);
+
+		//	the plot background.
+		this.plotArea = document.createElementNS(dojo.svg.xmlns.svg, "g");
+		this.vectorNode.appendChild(this.plotArea);
+		var rect = document.createElementNS(dojo.svg.xmlns.svg, "rect");		
+		rect.setAttribute("x", this.properties.padding.left);
+		rect.setAttribute("y", this.properties.padding.top);
+		rect.setAttribute("width", this.properties.width-this.properties.padding.left-this.properties.padding.right);
+		rect.setAttribute("height", this.properties.height-this.properties.padding.bottom-this.properties.padding.bottom);
+		rect.setAttribute("fill", "#fff");
+		this.plotArea.appendChild(rect);
+
+		//	data group
+		this.dataGroup = document.createElementNS(dojo.svg.xmlns.svg, "g");
+		this.dataGroup.setAttribute("style","clip-path:url(#plotClip"+this.widgetId+");");
+		this.plotArea.appendChild(this.dataGroup);
+
+		//	axis group
+		this.axisGroup = document.createElementNS(dojo.svg.xmlns.svg, "g");
+		this.plotArea.appendChild(this.axisGroup);
+
+		//	x axis
+		var stroke=1;
+		var line = document.createElementNS(dojo.svg.xmlns.svg, "line");
+		var y=dojo.widget.svg.Chart.Plotter.getY(this.properties.axes.x.plotAt, this);
+		line.setAttribute("y1", y);
+		line.setAttribute("y2", y);
+		line.setAttribute("x1",this.properties.padding.left-stroke);
+		line.setAttribute("x2",this.properties.width-this.properties.padding.right);
+		line.setAttribute("style","stroke:#000;stroke-width:"+stroke+";");
+		this.axisGroup.appendChild(line);
+		
+		//	x axis units.
+		//	(min and max)
+		var textSize=10;
+		var text = document.createElementNS(dojo.svg.xmlns.svg, "text");
+		text.setAttribute("x", this.properties.padding.left);
+		text.setAttribute("y", this.properties.height-this.properties.padding.bottom+textSize+2);
+		text.setAttribute("style", "text-anchor:middle;font-size:"+textSize+"px;fill:#000;");
+		text.appendChild(document.createTextNode(dojo.math.round(parseFloat(this.properties.axes.x.range.min),2)));
+		this.axisGroup.appendChild(text);
+		
+		var text = document.createElementNS(dojo.svg.xmlns.svg, "text");
+		text.setAttribute("x", this.properties.width-this.properties.padding.right-(textSize/2));
+		text.setAttribute("y", this.properties.height-this.properties.padding.bottom+textSize+2);
+		text.setAttribute("style", "text-anchor:middle;font-size:"+textSize+"px;fill:#000;");
+		text.appendChild(document.createTextNode(dojo.math.round(parseFloat(this.properties.axes.x.range.max),2)));
+		this.axisGroup.appendChild(text);	
+		
+		//	y axis
+		var line=document.createElementNS(dojo.svg.xmlns.svg, "line");
+		var x=dojo.widget.svg.Chart.Plotter.getX(this.properties.axes.y.plotAt, this);
+		line.setAttribute("x1", x);
+		line.setAttribute("x2", x);
+		line.setAttribute("y1", this.properties.padding.top);
+		line.setAttribute("y2", this.properties.height-this.properties.padding.bottom);
+		line.setAttribute("style", "stroke:#000;stroke-width:"+stroke+";");
+		this.axisGroup.appendChild(line);
+
+		//	y axis units
+		var text = document.createElementNS(dojo.svg.xmlns.svg, "text");
+		text.setAttribute("x", this.properties.padding.left-4);
+		text.setAttribute("y", this.properties.height-this.properties.padding.bottom);
+		text.setAttribute("style", "text-anchor:end;font-size:"+textSize+"px;fill:#000;");
+		text.appendChild(document.createTextNode(dojo.math.round(parseFloat(this.properties.axes.y.range.min),2)));
+		this.axisGroup.appendChild(text);
+		
+		var text = document.createElementNS(dojo.svg.xmlns.svg, "text");
+		text.setAttribute("x", this.properties.padding.left-4);
+		text.setAttribute("y", this.properties.padding.top+(textSize/2));
+		text.setAttribute("style", "text-anchor:end;font-size:"+textSize+"px;fill:#000;");
+		text.appendChild(document.createTextNode(dojo.math.round(parseFloat(this.properties.axes.y.range.max),2)));
+		this.axisGroup.appendChild(text);	
+
+		this.domNode.appendChild(this.vectorNode);
+		dojo.svg.g.resume();
+
+		//	this is last.
+		this.assignColors();
+		this._isInitialized=true;
+	},
+	destroy:function(){
+		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(){
+		dojo.svg.g.suspend();
+		
+		if (this.dataGroup){
+			while(this.dataGroup.childNodes.length>0){
+				this.dataGroup.removeChild(this.dataGroup.childNodes.item(0));
+			}
+		} else {
+			this.initialize();
+		}
+
+		//	the remove/append is an attempt to streamline the rendering, it's totally optional
+//		var p=this.dataGroup.parentNode;
+//		p.removeChild(this.dataGroup);
+		for(var i=0; i<this.series.length; i++){
+			dojo.widget.svg.Chart.Plotter.plot(this.series[i], this);
+		}
+//		p.appendChild(this.dataGroup);
+		
+		dojo.svg.g.resume();
+	}
+});
+
+dojo.widget.svg.Chart.Plotter=new function(){
+	var _this=this;
+	var plotters = {};
+	var types=dojo.widget.Chart.PlotTypes;
+	
+	this.getX=function(value, chart){
+		var v=parseFloat(value);
+		var min=chart.properties.axes.x.range.min;
+		var max=chart.properties.axes.x.range.max;
+		var ofst=0-min;
+		min+=ofst; max+=ofst; v+=ofst;
+
+		var xmin=chart.properties.padding.left;
+		var xmax=chart.properties.width-chart.properties.padding.right;
+		var x=(v*((xmax-xmin)/max))+xmin;
+		return x;
+	};
+	this.getY=function(value, chart){
+		var v=parseFloat(value);
+		var max=chart.properties.axes.y.range.max;
+		var min=chart.properties.axes.y.range.min;
+		var ofst=0;
+		if(min<0)ofst+=Math.abs(min);
+		min+=ofst; max+=ofst; v+=ofst;
+		
+		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;
+	};
+
+	this.addPlotter=function(name, func){
+		plotters[name]=func;
+	};
+	this.plot=function(series, chart){
+		if (series.values.length==0) return;
+		if (series.plotType && plotters[series.plotType]){
+			return plotters[series.plotType](series, chart);
+		}
+		else if (chart.plotType && plotters[chart.plotType]){
+			return plotters[chart.plotType](series, chart);
+		}
+	};
+
+	//	plotting
+	plotters[types.Bar]=function(series, chart){
+		var space=1;
+		var lastW = 0;
+		for (var i=0; i<series.values.length; i++){
+			var x=_this.getX(series.values[i].x, chart);
+			var w;
+			if (i==series.values.length-1){
+				w=lastW;
+			} else{
+				w=_this.getX(series.values[i+1].x, chart)-x-space;
+				lastW=w;
+			}
+			x-=(w/2);
+
+			var yA=_this.getY(chart.properties.axes.x.plotAt, chart);
+			var y=_this.getY(series.values[i].value, chart);
+			var h=Math.abs(yA-y);
+			if (parseFloat(series.values[i].value)<chart.properties.axes.x.plotAt){
+				var oy=yA;
+				yA=y;
+				y=oy;
+			}
+
+			var bar=document.createElementNS(dojo.svg.xmlns.svg, "rect");
+			bar.setAttribute("fill", series.color);
+			bar.setAttribute("title", series.label + ": " + series.values[i].value);
+			bar.setAttribute("stroke-width", "0");
+			bar.setAttribute("x", x);
+			bar.setAttribute("y", y);
+			bar.setAttribute("width", w);
+			bar.setAttribute("height", h);
+			bar.setAttribute("fill-opacity", "0.9");
+			chart.dataGroup.appendChild(bar);
+		}
+	};
+	plotters[types.Line]=function(series, chart){
+		var tension=3;
+		var line = document.createElementNS(dojo.svg.xmlns.svg, "path");
+		line.setAttribute("fill", "none");
+		line.setAttribute("stroke", series.color);
+		line.setAttribute("stroke-width", "2");
+		line.setAttribute("stroke-opacity", "0.85");
+		line.setAttribute("title", series.label);
+		chart.dataGroup.appendChild(line);
+
+		var path = [];
+		for (var i=0; i<series.values.length; i++){
+			var x = _this.getX(series.values[i].x, chart)
+			var y = _this.getY(series.values[i].value, chart);
+
+			var dx = chart.properties.padding.left+1;
+			var dy = chart.properties.height-chart.properties.padding.bottom;
+			if (i>0){
+				dx=x-_this.getX(series.values[i-1].x, chart);
+				dy=_this.getY(series.values[i-1].value, chart);
+			}
+			
+			if (i==0) path.push("M");
+			else {
+				path.push("C");
+				var cx=x-(tension-1)*(dx/tension);
+				path.push(cx+","+dy);
+				cx=x-(dx/tension);
+				path.push(cx+","+y);
+			}
+			path.push(x+","+y);
+		}
+		line.setAttribute("d", path.join(" "));
+	};
+	plotters[types.Scatter]=function(series, chart){
+		var r=7;
+		for (var i=0; i<series.values.length; i++){
+			var x=_this.getX(series.values[i].x, chart);
+			var y=_this.getY(series.values[i].value, chart);
+			var point = document.createElementNS(dojo.svg.xmlns.svg, "path");
+			point.setAttribute("fill", series.color);
+			point.setAttribute("stroke-width", "0");
+			point.setAttribute("title", series.label + ": " + series.values[i].value);
+			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"
+			);
+			chart.dataGroup.appendChild(point);
+		}
+	};
+	plotters[types.Bubble]=function(series, chart){
+		//	added param for series[n].value: size
+		var minR=1;
+		
+		//	do this off the x axis?
+		var min=chart.properties.axes.x.range.min;
+		var max=chart.properties.axes.x.range.max;
+		var ofst=0-min;
+		min+=ofst; max+=ofst;
+
+		var xmin=chart.properties.padding.left;
+		var xmax=chart.properties.width-chart.properties.padding.right;
+		var factor=(max-min)/(xmax-xmin)*25;
+		
+		for (var i=0; i<series.values.length; i++){
+			var size = series.values[i].size;
+			if (isNaN(parseFloat(size))) size=minR;
+			var point=document.createElementNS(dojo.svg.xmlns.svg, "circle");
+			point.setAttribute("stroke-width", 0);
+			point.setAttribute("fill", series.color);
+			point.setAttribute("fill-opacity", "0.8");
+			point.setAttribute("r", (parseFloat(size)*factor)/2);
+			point.setAttribute("cx", _this.getX(series.values[i].x, chart));
+			point.setAttribute("cy", _this.getY(series.values[i].value, chart));
+			point.setAttribute("title", series.label + ": " + series.values[i].value + " (" + size + ")");
+			chart.dataGroup.appendChild(point);
+		}
+	};
+}();

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/templates/DemoEngine.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/templates/DemoEngine.html?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/templates/DemoEngine.html (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/templates/DemoEngine.html Sat Jun 10 06:59:28 2006
@@ -0,0 +1,24 @@
+<div dojoAttachPoint="domNode">
+	<div dojoAttachPoint="navigationNode">
+		<table border="0" cellspacing="0" cellpadding="0">
+			<tr>
+				<td width="1%" valign="top" class="navigationCell"><h1>Categories</h1><div dojoAttachPoint="menuNavigationNode"></div></td>
+				<td width="99%" valign="top">
+					<div dojoAttachPoint="demoNavigationNode">
+					</div>
+				</td>
+			</tr>
+		</table>
+	</div>
+
+	<div dojoAttachPoint="demoContainerNode">
+
+		<div dojoAttachPoint="demoPaneNode">
+		</div>
+
+		<div dojoAttachPoint="demoHeaderNode">
+			<span dojoAttachPoint="collapsedMenuNode" dojoAttachEvent="onclick: expandDemoNavigation"></span>
+			<div dojoAttachPoint="aboutNode">About this Demo</div>
+		</div>
+	</div>
+</div>

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/templates/HslColorPicker.svg
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/templates/HslColorPicker.svg?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/templates/HslColorPicker.svg (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/templates/HslColorPicker.svg Sat Jun 10 06:59:28 2006
@@ -0,0 +1,30 @@
+<svg xmlns="http://www.w3.org/2000/svg"
+	xmlns:xlink="http://www.w3.org/1999/xlink"
+	version="1.1" baseProfile="full" width="170" height="131" xmlns:html="http://www.w3.org/1999/xhtml">
+	<defs>
+	<linearGradient id="colorGradient" dojoAttachPoint="colorGradientNode" x1="0" x2="131" y1="0" y2="0" gradientUnits="userSpaceOnUse">
+		<stop id="leftGradientColor" dojoAttachPoint="leftGradientColorNode" offset="0%" stop-color="#828282"/>
+		<stop id="rightGradientColor" dojoAttachPoint="rightGradientColorNode" offset="100%" stop-color="#053fff"/>
+	</linearGradient>
+	<linearGradient id="verticalGradient" x1="0" x2="0" y1="0" y2="131" gradientUnits="userSpaceOnUse">
+		<stop offset="0%" style="stop-color:#000000;"/>
+		<stop offset="50%" style="stop-color:#000000;stop-opacity:0;"/>
+		<stop offset="50%" style="stop-color:#ffffff;stop-opacity:0;"/>
+		<stop offset="100%" style="stop-color:#ffffff;"/>
+	</linearGradient>
+	<linearGradient id="sliderGradient">
+		<stop offset="0%" style="stop-color:#000000;"/>
+		<stop offset="15%" style="stop-color:#ffffff;"/>
+		<stop offset="30%" style="stop-color:#000000;"/>
+		<stop offset="45%" style="stop-color:#ffffff;"/>
+		<stop offset="60%" style="stop-color:#000000;"/>
+		<stop offset="75%" style="stop-color:#ffffff;"/>
+		<stop offset="90%" style="stop-color:#000000;"/>
+	</linearGradient>
+</defs>
+	<rect x="0" y="0" width="131px" height="131px" fill="url(#colorGradient)"/>
+	<rect x="0" y="0" width="131px" height="131px" style="fill:url(#verticalGradient);"/>
+	<rect id="saturationLightSlider" dojoAttachPoint="saturationLightSliderNode" x="100" y="100" width="5px" height="5px" style="stroke:url(#sliderGradient);stroke-width:1px;fill-opacity:0;"/>
+	<image xlink:href="images/hue.png" dojoAttachPoint="hueNode" x="140px" y="0px" width="21px" height="131px" dojoAttachEvent="onclick: onHueClick;"/>
+	<rect dojoAttachPoint="hueSliderNode" x="139px" y="40px" width="24px" height="4px" style="stroke-opacity:1;fill-opacity:0;stroke:black;"/>
+</svg>

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/templates/HtmlCiviCrmDatePicker.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/templates/HtmlCiviCrmDatePicker.html?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/templates/HtmlCiviCrmDatePicker.html (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/templates/HtmlCiviCrmDatePicker.html Sat Jun 10 06:59:28 2006
@@ -0,0 +1,12 @@
+<table cellpadding="0" cellspacing="0" border="0" width="400">
+	<tr>
+		<td id="dateHolderTd" width="200">
+		</td>
+		<td id="timeHolderTd" width="200">
+		</td>
+	</tr>
+	<tr style="display: none;" id="formItemsTr">
+		<td id="formItemsTd">&nbsp;</td>
+		<td>&nbsp;</td>
+	</tr>
+</table>

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/templates/HtmlComboButtonTemplate.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/templates/HtmlComboButtonTemplate.html?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/templates/HtmlComboButtonTemplate.html (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/templates/HtmlComboButtonTemplate.html Sat Jun 10 06:59:28 2006
@@ -0,0 +1,18 @@
+<div class="dojoButton" style="position:relative;top:0px;left:0px; text-align:none;">
+
+	<div dojoAttachPoint="leftPart" class="dojoButtonLeftPart" style="position:absolute;left:0px;top:0px;"
+		dojoAttachEvent="onMouseOver:leftOver; onMouseOut:leftOut; onMouseUp:leftUp; onClick:leftClick;">
+		<div class="dojoButtonContents" dojoAttachPoint="containerNode" style="position:absolute;top:0px;right:0px;z-index:2;"></div>
+		<img dojoAttachPoint="leftImage" style="position:absolute;left:0px;top:0px;">
+		<img dojoAttachPoint="centerImage" style="position:absolute;right:0px;top:0px;z-index:1;">
+	</div>
+
+	<div dojoAttachPoint="rightPart" class="dojoButtonRightPart" style="position:absolute;top:0px;right:0px;"
+		dojoAttachEvent="onMouseOver:rightOver; onMouseOut:rightOut; onMouseUp:rightUp; onClick:rightClick;">
+		<img dojoAttachPoint="arrowBackgroundImage" style="position:absolute;top:0px;left:0px;z-index:1;">
+		<img src="${dojoRoot}src/widget/templates/images/whiteDownArrow.gif"
+		  		style="z-index:2;position:absolute;left:3px;top:50%;">
+		<img dojoAttachPoint="rightImage" style="position:absolute;top:0px;right:0px;">
+	</div>
+
+</div>

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/templates/HtmlContextMenuTemplate.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/templates/HtmlContextMenuTemplate.html?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/templates/HtmlContextMenuTemplate.html (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/templates/HtmlContextMenuTemplate.html Sat Jun 10 06:59:28 2006
@@ -0,0 +1,3 @@
+<ul class="dojoContextMenu" 
+	dojoAttachPoint="containerNode">
+</ul>

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