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

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Rounded.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Rounded.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Rounded.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Rounded.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,711 @@
+/*
+	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.Rounded");
+dojo.widget.tags.addParseTreeHandler("dojo:rounded");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.ContentPane");
+dojo.require("dojo.html.style");
+dojo.require("dojo.html.display");
+dojo.require("dojo.gfx.color");
+
+/*
+ *	The following script is derived (with permission) from curvyCorners,
+ *	written by Cameron Cooke (CLA on file) and was adapted to Dojo by Brian
+ *	Lucas (CLA on file)
+ */
+
+dojo.widget.defineWidget(
+	"dojo.widget.Rounded",
+	dojo.widget.ContentPane,
+{
+	isSafari: dojo.render.html.safari,
+
+	boxMargin: "50px", // margin outside rounded corner box
+	radius: 14, // radius of corners
+	domNode: "",
+	corners: "TR,TL,BR,BL", // corner string to render
+	antiAlias: true, // false to disable anti-aliasing
+
+	fillInTemplate: function(args, frag) {
+		dojo.widget.Rounded.superclass.fillInTemplate.call(this, args, frag);
+
+		dojo.html.insertCssFile(this.templateCssPath);
+
+		// Magic to automatically calculate the box height/width if not supplied
+		if (this.domNode.style.height<=0) {
+			var minHeight = (this.radius*1)+this.domNode.clientHeight;
+			this.domNode.style.height = minHeight+"px";
+		}
+
+		if (this.domNode.style.width<=0) {
+			var minWidth = (this.radius*1)+this.domNode.clientWidth;
+			this.domNode.style.width = minWidth+"px";
+		}
+
+		var cornersAvailable = ["TR", "TL", "BR", "BL"];
+		var cornersPassed = this.corners.split(",");
+
+		this.settings = {
+			antiAlias: this.antiAlias
+		};
+
+		var setCorner = function(currentCorner) {
+			var val = currentCorner.toLowerCase();
+			if(dojo.lang.inArray(cornersPassed, currentCorner)) {
+				this.settings[val] = { radius: this.radius, enabled: true };
+			} else {
+				this.settings[val] = { radius: 0 }
+			}
+		}
+		dojo.lang.forEach(cornersAvailable, setCorner, this);
+
+		this.domNode.style.margin = this.boxMargin;
+		this.curvyCorners(this.settings);
+		this.applyCorners();
+	},
+
+	// ------------- curvyCorners OBJECT
+
+	curvyCorners: function(settings){	
+
+		// Setup Globals
+		this.box             = this.domNode;
+		this.topContainer    = null;
+		this.bottomContainer = null;
+		this.masterCorners   = [];
+
+		// Get box formatting details
+		var boxHeight       = dojo.html.getStyle(this.box, "height");
+		if(boxHeight=="") boxHeight="0px";
+		var boxWidth        = dojo.html.getStyle(this.box, "width");
+		var borderWidth     = dojo.html.getStyle(this.box, "borderTopWidth");
+		if(borderWidth=="") borderWidth="0px";
+		//alert(borderWidth);
+
+		var borderColour    = dojo.html.getStyle(this.box, "borderTopColor");
+		// Set to true if we have a border
+		if(borderWidth>0) this.antiAlias=true;
+
+		var boxColour       = dojo.html.getStyle(this.box, "backgroundColor");
+		var backgroundImage = dojo.html.getStyle(this.box, "backgroundImage");
+		var boxPosition     = dojo.html.getStyle(this.box, "position");
+
+		// Set formatting propertes
+		this.boxHeight       = parseInt(((boxHeight != "" && boxHeight != "auto" && boxHeight.indexOf("%") == -1)? boxHeight.substring(0, boxHeight.indexOf("px")) : this.box.scrollHeight));
+		this.boxWidth        = parseInt(((boxWidth != "" && boxWidth != "auto" && boxWidth.indexOf("%") == -1)? boxWidth.substring(0, boxWidth.indexOf("px")) : this.box.scrollWidth));
+		this.borderWidth     = parseInt(((borderWidth != "" && borderWidth.indexOf("px") !== -1)? borderWidth.slice(0, borderWidth.indexOf("px")) : 0));
+
+		// DEBUG ME?
+
+		//dojo.debug(this.rgb2Hex(boxColour));
+		var test  = new dojo.gfx.color.Color(boxColour);
+		//dojo.debug(test.toHex()); 
+
+		this.boxColour       = ((boxColour != "" && boxColour != "transparent")? ((boxColour.substr(0, 3) == "rgb")? this.rgb2Hex(boxColour) : boxColour) : "#ffffff");
+		this.borderColour    = ((borderColour != "" && borderColour != "transparent" && this.borderWidth > 0)? ((borderColour.substr(0, 3) == "rgb")? this.rgb2Hex(borderColour)  : borderColour) : this.boxColour);
+		this.borderString    = this.borderWidth + "px" + " solid " + this.borderColour;
+		this.backgroundImage = ((backgroundImage != "none")? backgroundImage : "");
+
+		// Make box relative if not already absolute
+		if(boxPosition != "absolute") this.box.style.position = "relative";
+
+		//This method creates the corners and
+		//applies them to the div element.
+
+		this.applyCorners = function() {
+			// Create top and bottom containers.
+			// These will be used as a parent for the corners and bars.
+			for(var t = 0; t < 2; t++) {
+			    switch(t) {
+			        // Top
+			        case 0:
+						// Only build top bar if a top corner is to be draw
+						if(this.settings.tl.enabled || this.settings.tr.enabled ) {
+							var newMainContainer = document.createElement("DIV");
+			
+							with(newMainContainer.style){
+								width    = "100%";
+								fontSize = "1px";
+								overflow = "hidden";
+								position = "absolute";
+								//backgroundColor = "#FFFFC4";
+								paddingLeft  = this.borderWidth + "px";
+								paddingRight = this.borderWidth + "px";
+								var topMaxRadius = Math.max(this.settings.tl ? this.settings.tl.radius : 0, this.settings.tr ? this.settings.tr.radius : 0);
+								height = topMaxRadius + "px";
+								top    = 0 - topMaxRadius + "px";
+								left   = 0 - this.borderWidth + "px";
+							}
+							
+							this.topContainer = this.box.appendChild(newMainContainer);
+						}
+			            break;
+	
+			        // Bottom
+			        case 1:      
+			            // Only build bottom bar if a top corner is to be draw
+			            if(this.settings.bl.enabled || this.settings.br.enabled) {
+							var newMainContainer = document.createElement("DIV");
+							with(newMainContainer.style){
+								width    = "100%";
+								fontSize = "1px";
+								overflow = "hidden";
+								position = "absolute";
+								//backgroundColor = "#FFFFC4";
+								paddingLeft  = this.borderWidth + "px";
+								paddingRight = this.borderWidth + "px";
+								var botMaxRadius = Math.max(this.settings.bl ? this.settings.bl.radius : 0, this.settings.br ? this.settings.br.radius : 0);
+								height  = botMaxRadius + "px";
+								bottom  =  0 - botMaxRadius + "px";
+								left    =  0 - this.borderWidth + "px";
+							}
+						this.bottomContainer = this.box.appendChild(newMainContainer);
+			            }
+		            break;
+			    }
+			}
+	
+			// Turn off current borders
+			if(this.topContainer) this.box.style.borderTopWidth = "0px";
+			if(this.bottomContainer) this.box.style.borderBottomWidth = "0px";
+	
+			// Create array of available corners
+			var corners = ["tr", "tl", "br", "bl"];
+		
+			//Loop for each corner
+	
+			for(var i in corners) {
+			    // Get current corner type from array
+			    var cc = corners[i];
+
+			    // Has the user requested the currentCorner be round?
+			    if(!this.settings[cc]) {
+			        // No
+			        if(((cc == "tr" || cc == "tl") && this.topContainer != null) || ((cc == "br" || cc == "bl") && this.bottomContainer != null)) {
+						// We need to create a filler div to fill the space upto the next horzontal corner.
+						var newCorner = document.createElement("DIV");
+		
+						// Setup corners properties
+						newCorner.style.position = "relative";
+						newCorner.style.fontSize = "1px";
+						newCorner.style.overflow = "hidden";
+		
+						// Add background image?
+						if(this.backgroundImage == "") {
+							newCorner.style.backgroundColor = this.boxColour;
+						} else {
+							newCorner.style.backgroundImage = this.backgroundImage;
+						}
+
+			            switch(cc) {
+							case "tl":
+								with(newCorner.style){
+									height      = topMaxRadius - this.borderWidth + "px";
+									marginRight = this.settings.tr.radius - (this.borderWidth*2) + "px";
+									borderLeft  = this.borderString;
+									borderTop   = this.borderString;
+									left         = -this.borderWidth + "px";
+								}
+							break;
+			
+							case "tr":
+								with(newCorner.style){
+									height      = topMaxRadius - this.borderWidth + "px";
+									marginLeft  = this.settings.tl.radius - (this.borderWidth*2) + "px";
+									borderRight = this.borderString;
+									borderTop   = this.borderString;
+									backgroundPosition  = "-" + this.boxWidth + "px 0px";
+									left         = this.borderWidth + "px";
+								}
+							break;
+	
+							case "bl":
+								with(newCorner.style){
+									height       = botMaxRadius - this.borderWidth + "px";
+									marginRight  = this.settings.br.radius - (this.borderWidth*2) + "px";
+									borderLeft   = this.borderString;
+									borderBottom = this.borderString;
+									left         = -this.borderWidth + "px";
+								}
+							break;
+			
+							case "br":
+								with(newCorner.style){
+									height       = botMaxRadius - this.borderWidth + "px";
+									marginLeft   = this.settings.bl.radius - (this.borderWidth*2) + "px";
+									borderRight  = this.borderString;
+									borderBottom = this.borderString;
+									left         = this.borderWidth + "px"
+								}
+							break;
+			            }
+			        }
+			    } else {
+			        /*
+			        PERFORMANCE NOTE:
+
+			        If more than one corner is requested and a corner has been already
+			        created for the same radius then that corner will be used as a master and cloned.
+			        The pixel bars will then be repositioned to form the new corner type.
+			        All new corners start as a bottom right corner.
+			        */
+			        if(this.masterCorners[this.settings[cc].radius]) {
+			            // Create clone of the master corner
+			            var newCorner = this.masterCorners[this.settings[cc].radius].cloneNode(true);
+			        } else {
+			            // Yes, we need to create a new corner
+			            var newCorner = document.createElement("DIV");
+						with(newCorner.style){
+							height = this.settings[cc].radius + "px";
+							width  = this.settings[cc].radius + "px";
+							position = "absolute";
+							fontSize = "1px";
+							overflow = "hidden";
+						}
+						// THE FOLLOWING BLOCK OF CODE CREATES A ROUNDED CORNER
+						// ---------------------------------------------------- TOP
+			
+						// Get border radius
+						var borderRadius = parseInt(this.settings[cc].radius - this.borderWidth);
+			
+						// Cycle the x-axis
+						for(var intx = 0, j = this.settings[cc].radius; intx < j; intx++) {
+							// Calculate the value of y1 which identifies the pixels inside the border
+							if((intx +1) >= borderRadius) {
+								var y1 = -1;
+							} else {
+								var y1 = (Math.floor(Math.sqrt(Math.pow(borderRadius, 2) - Math.pow((intx+1), 2))) - 1);
+							}
+			
+							// Only calculate y2 and y3 if there is a border defined
+							if(borderRadius != j) {
+								if((intx) >= borderRadius) {
+									var y2 = -1;
+								} else {
+									var y2 = Math.ceil(Math.sqrt(Math.pow(borderRadius,2) - Math.pow(intx, 2)));
+								}
+			
+								if((intx+1) >= j) {
+									var y3 = -1;
+								} else {
+									var y3 = (Math.floor(Math.sqrt(Math.pow(j ,2) - Math.pow((intx+1), 2))) - 1);
+								}
+							}
+
+							// Calculate y4
+							if((intx) >= j) {
+								var y4 = -1;
+							} else {
+								var y4 = Math.ceil(Math.sqrt(Math.pow(j ,2) - Math.pow(intx, 2)));
+							}
+
+							// Draw bar on inside of the border with foreground colour
+							if(y1 > -1) this.drawPixel(intx, 0, this.boxColour, 100, (y1+1), newCorner, -1, this.settings[cc].radius);
+	
+							// Only draw border/foreground antialiased pixels and border if there is a border defined
+							if(borderRadius != j) {
+								// Draw aa pixels?
+								if(this.antiAlias) {
+									// Cycle the y-axis
+									for(var inty = (y1 + 1); inty < y2; inty++) {
+										// For each of the pixels that need anti aliasing between the foreground and border colour draw single pixel divs
+										if(this.backgroundImage != "") {					
+											var borderFract = (this.pixelFraction(intx, inty, borderRadius) * 100);
+					
+											if (borderFract < 30) {
+												this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, 0, this.settings[cc].radius);
+											} else {
+												this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, -1, this.settings[cc].radius);
+											}
+										} else {
+											var pixelcolour = dojo.gfx.color.blend(this.boxColour, this.borderColour, this.pixelFraction(intx, inty, borderRadius));
+											this.drawPixel(intx, inty, pixelcolour, 100, 1, newCorner, 0, this.settings[cc].radius);
+										}
+									}
+								}
+
+								// Draw bar for the border
+								if(y3 >= y2) {
+									if (y1 == -1) {
+										y1 = 0;
+									}
+									this.drawPixel(intx, y2, this.borderColour, 100, (y3 - y2 + 1), newCorner, 0, this.settings[cc].radius);
+								}	
+								// Set the colour for the outside curve
+								var outsideColour = this.borderColour;
+							} else {
+								// Set the coour for the outside curve
+								var outsideColour = this.boxColour;
+								var y3 = y1;
+							}
+			
+							// Draw aa pixels?
+							if(this.antiAlias) {		
+								// Cycle the y-axis and draw the anti aliased pixels on the
+								// outside of the curve
+								for(var inty = (y3 + 1); inty < y4; inty++) {
+									// For each of the pixels that need anti aliasing between 
+									//the foreground/border colour & background draw single pixel divs
+									this.drawPixel(intx, inty, outsideColour, (this.pixelFraction(intx, inty , j) * 100), 1, newCorner, ((this.borderWidth > 0)? 0 : -1), this.settings[cc].radius);
+								}
+							}
+			            }
+
+			            // END OF CORNER CREATION
+			            // ---------------------------------------------------- END
+
+			            // We now need to store the current corner in the masterConers array
+			            this.masterCorners[this.settings[cc].radius] = newCorner.cloneNode(true);
+			        }
+			
+					//Now we have a new corner we need to reposition all the pixels unless
+					//the current corner is the bottom right.
+			        if(cc != "br") {	
+						// Loop through all children (pixel bars)
+						for(var t = 0, k = newCorner.childNodes.length; t < k; t++) {
+							// Get current pixel bar
+							var pixelBar = newCorner.childNodes[t];
+	
+							// Get current top and left properties
+							var pixelBarTop    = parseInt(pixelBar.style.top.substring(0, pixelBar.style.top.indexOf("px")));
+							var pixelBarLeft   = parseInt(pixelBar.style.left.substring(0, pixelBar.style.left.indexOf("px")));
+							var pixelBarHeight = parseInt(pixelBar.style.height.substring(0, pixelBar.style.height.indexOf("px")));
+							
+							// Reposition pixels
+							if(cc == "tl" || cc == "bl") {
+								pixelBar.style.left = this.settings[cc].radius -pixelBarLeft -1 + "px"; // Left
+							}
+							if(cc == "tr" || cc == "tl") {
+								pixelBar.style.top =  this.settings[cc].radius -pixelBarHeight -pixelBarTop + "px"; // Top
+							}
+							var value;
+					
+							switch(cc) {
+								case "tr":
+									value = (-1 *( Math.abs((this.boxWidth - this.settings[cc].radius + this.borderWidth) + pixelBarLeft) - (Math.abs(this.settings[cc].radius -pixelBarHeight -pixelBarTop - this.borderWidth))));
+									pixelBar.style.backgroundPosition  = value + "px";
+									
+								break;
+				
+								case "tl":
+									value = (-1 *( Math.abs((this.settings[cc].radius -pixelBarLeft -1)  - this.borderWidth) - (Math.abs(this.settings[cc].radius -pixelBarHeight -pixelBarTop - this.borderWidth))));
+									pixelBar.style.backgroundPosition  = value + "px";
+
+								break;
+				
+								case "bl":
+									value = (-1 *( Math.abs((this.settings[cc].radius -pixelBarLeft -1) - this.borderWidth) - (Math.abs((this.boxHeight + this.settings[cc].radius + pixelBarTop) -this.borderWidth))));
+									pixelBar.style.backgroundPosition  = value + "px";
+
+								break;
+							}
+						}
+					}
+				}
+				if(newCorner) {
+					// Position the container
+					switch(cc) {
+						case "tl":
+							if(newCorner.style.position == "absolute") newCorner.style.top  = "0px";
+							if(newCorner.style.position == "absolute") newCorner.style.left = "0px";
+							if(this.topContainer) this.topContainer.appendChild(newCorner);
+						break;
+
+						case "tr":
+							if(newCorner.style.position == "absolute") newCorner.style.top  = "0px";
+							if(newCorner.style.position == "absolute") newCorner.style.right = "0px";
+							if(this.topContainer) this.topContainer.appendChild(newCorner);
+						break;
+		
+						case "bl":
+							if(newCorner.style.position == "absolute") newCorner.style.bottom  = "0px";
+							if(newCorner.style.position == "absolute") newCorner.style.left = "0px";
+							if(this.bottomContainer) this.bottomContainer.appendChild(newCorner);
+						break;
+						
+						case "br":
+							if(newCorner.style.position == "absolute") newCorner.style.bottom = "0px";
+							if(newCorner.style.position == "absolute") newCorner.style.right = "0px";
+							if(this.bottomContainer) this.bottomContainer.appendChild(newCorner);
+						break;
+					}
+				}
+			}
+			//The last thing to do is draw the rest of the filler DIVs.
+			//We only need to create a filler DIVs when two corners have
+			//diffrent radiuses in either the top or bottom container.
+	
+			// Find out which corner has the biiger radius and get the difference amount
+			var radiusDiff = [];
+			radiusDiff["t"] = this.settings.tl.enabled && this.settings.tr.enabled ? Math.abs(this.settings.tl.radius - this.settings.tr.radius) : 0;
+			radiusDiff["b"] = this.settings.bl.enabled && this.settings.br.enabled ? Math.abs(this.settings.bl.radius - this.settings.br.radius) : 0;
+
+			for(var z in radiusDiff) {
+				if(radiusDiff[z]) {
+					// Get the type of corner that is the smaller one
+					var smallerCornerType = ((this.settings[z + "l"].radius < this.settings[z + "r"].radius)? z +"l" : z +"r");
+
+					// First we need to create a DIV for the space under the smaller corner
+					var newFiller = document.createElement("DIV");
+					with(newFiller.style) {
+						height = radiusDiff[z] + "px";
+						width  =  this.settings[smallerCornerType].radius+ "px"
+						position = "absolute";
+						fontSize = "1px";
+						overflow = "hidden";
+						backgroundColor = this.boxColour;
+					}
+
+					// Position filler
+					switch(smallerCornerType) {
+						case "tl":
+							with(newFiller.style) {
+								bottom = "0px";
+								left   = "0px";
+								borderLeft = this.borderString;
+							}
+							this.topContainer.appendChild(newFiller);
+						break;
+	
+						case "tr":
+							with(newFiller.style) {
+								bottom = "0px";
+								right  = "0px";
+								borderRight = this.borderString;
+							}
+							this.topContainer.appendChild(newFiller);
+						break;
+
+						case "bl":
+							with(newFiller.style) {
+								top    = "0px";
+								left   = "0px";
+								borderLeft = this.borderString;
+							}
+							this.bottomContainer.appendChild(newFiller);
+						break;
+
+						case "br":
+							with(newFiller.style) {
+								top    = "0px";
+								right  = "0px";
+								borderRight = this.borderString;
+							}
+							this.bottomContainer.appendChild(newFiller);
+						break;
+					}
+			    }
+
+				// Create the bar to fill the gap between each corner horizontally
+				var newFillerBar = document.createElement("DIV");
+				with(newFillerBar.style) {
+					position = "relative";
+					fontSize = "1px";
+					overflow = "hidden";
+					backgroundColor = this.boxColour;
+				}
+
+				switch(z) {
+					case "t":
+						// Top Bar
+						if(this.topContainer) {
+							with(newFillerBar.style) {
+								height      = topMaxRadius - this.borderWidth + "px";
+								marginLeft  = this.settings.tl.radius - this.borderWidth + "px";
+								marginRight = this.settings.tr.radius - this.borderWidth + "px";
+								borderTop   = this.borderString;
+							}
+						this.topContainer.appendChild(newFillerBar);
+						}
+					break;
+
+					case "b":
+						if(this.bottomContainer) {
+						// Bottom Bar
+						with(newFillerBar.style) {
+							height       = botMaxRadius - this.borderWidth + "px";
+							marginLeft   = this.settings.bl.radius - this.borderWidth + "px";
+							marginRight  = this.settings.br.radius - this.borderWidth + "px";
+							borderBottom = this.borderString;
+						}
+						this.bottomContainer.appendChild(newFillerBar);
+					}
+					break;
+				}
+			}
+		}
+
+		// This function draws the pixles
+		this.drawPixel = function(intx, inty, colour, transAmount, height, newCorner, image, cornerRadius) {
+			// Create pixel
+			var pixel = document.createElement("DIV");
+
+			
+			// Section doesn't like with (pixel.style) { DEBUG?
+			pixel.style.height   = height + "px";
+			pixel.style.width    = "1px";
+			pixel.style.position = "absolute";
+			pixel.style.fontSize = "1px";
+			pixel.style.overflow = "hidden";
+			
+			// Dont apply background image to border pixels
+			if(image == -1 && this.backgroundImage != "") {
+				pixel.style.backgroundImage = this.backgroundImage;
+				pixel.style.backgroundPosition  = "-" + (this.boxWidth - (cornerRadius - intx) + this.borderWidth) + "px -" + ((this.boxHeight + cornerRadius + inty) -this.borderWidth) + "px";
+			} else {
+				pixel.style.backgroundColor = colour;
+			}
+			
+			// Set opacity if the transparency is anything other than 100
+			if (transAmount != 100) {
+				dojo.html.setOpacity(pixel, transAmount);
+			}
+			// Set the pixels position
+			pixel.style.top = inty + "px";
+			pixel.style.left = intx + "px";
+		
+			newCorner.appendChild(pixel);
+		}
+	},
+
+	//For a pixel cut by the line determines the fraction of the pixel on the 'inside' of the
+	//line.  Returns a number between 0 and 1
+	pixelFraction: function(x, y, r) {
+		var pixelfraction = 0;
+		
+		//determine the co-ordinates of the two points on the perimeter of the pixel that the
+		//circle crosses
+		
+		var xvalues = [];
+		var yvalues = [];
+		var point = 0;
+		var whatsides = "";
+
+		// x + 0 = Left
+		var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x,2)));
+
+		if ((intersect >= y) && (intersect < (y+1))) {
+			whatsides = "Left";
+			xvalues[point] = 0;
+			yvalues[point] = intersect - y;
+			point =  point + 1;
+		}
+
+		// y + 1 = Top
+		var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y+1,2)));
+		
+		if ((intersect >= x) && (intersect < (x+1))) {
+			whatsides = whatsides + "Top";
+			xvalues[point] = intersect - x;
+			yvalues[point] = 1;
+			point = point + 1;
+		}
+		// x + 1 = Right
+		var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x+1,2)));
+
+		if ((intersect >= y) && (intersect < (y+1))) {
+			whatsides = whatsides + "Right";
+			xvalues[point] = 1;
+			yvalues[point] = intersect - y;
+			point =  point + 1;
+		}
+		// y + 0 = Bottom
+		var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y,2)));
+
+		if ((intersect >= x) && (intersect < (x+1))) {
+			whatsides = whatsides + "Bottom";
+			xvalues[point] = intersect - x;
+			yvalues[point] = 0;
+		}
+
+	    //depending on which sides of the perimeter of the pixel the circle crosses calculate the
+	    //fraction of the pixel inside the circle
+
+		switch (whatsides) {
+			case "LeftRight":
+				pixelfraction = Math.min(yvalues[0],yvalues[1]) + ((Math.max(yvalues[0],yvalues[1]) - Math.min(yvalues[0],yvalues[1]))/2);
+			break;
+			
+			case "TopRight":
+				pixelfraction = 1-(((1-xvalues[0])*(1-yvalues[1]))/2);
+			break;
+			
+			case "TopBottom":
+				pixelfraction = Math.min(xvalues[0],xvalues[1]) + ((Math.max(xvalues[0],xvalues[1]) - Math.min(xvalues[0],xvalues[1]))/2);
+			break;
+			
+			case "LeftBottom":
+				pixelfraction = (yvalues[0]*xvalues[1])/2;
+			break;
+			
+			default:
+				pixelfraction = 1;
+	    }
+	    return pixelfraction;
+	},
+
+	// This function converts CSS rgb(x, x, x) to hexadecimal
+	rgb2Hex: function (rgbColour) {
+		try{	
+			// Get array of RGB values
+			var rgbArray = this.rgb2Array(rgbColour);
+			
+			// Get RGB values
+			var red   = parseInt(rgbArray[0]);
+			var green = parseInt(rgbArray[1]);
+			var blue  = parseInt(rgbArray[2]);
+			
+			// Build hex colour code
+			var hexColour = "#" + this.intToHex(red) + this.intToHex(green) + this.intToHex(blue);
+		}
+		catch(e){ alert("There was an error converting the RGB value to Hexadecimal in function rgb2Hex");
+		}
+		return hexColour;
+	},
+
+	//Converts a number to hexadecimal format
+
+	intToHex: function (strNum) {
+		var base = strNum / 16;
+		var rem = strNum % 16;
+		var base = base - (rem / 16);
+		var baseS = this.makeHex(base);
+		var remS = this.makeHex(rem);
+		return baseS + '' + remS;
+	},
+	//gets the hex bits of a number
+
+	makeHex: function(x) {
+		if((x >= 0) && (x <= 9)) {
+			return x;
+		} else {
+			switch(x) {
+				case 10: return "A";
+				case 11: return "B";
+				case 12: return "C";
+				case 13: return "D";
+				case 14: return "E";
+				case 15: return "F";
+			}
+		}
+	},
+
+	// Returns an array of rbg values
+	rgb2Array: function(rgbColour) {
+		// Remove rgb()
+		var rgbValues = rgbColour.substring(4, rgbColour.indexOf(")"));
+	
+		// Split RGB into array
+		var rgbArray = rgbValues.split(", ");
+		return rgbArray;
+	}
+}); // end function

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Select.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Select.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Select.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Select.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,76 @@
+/*
+	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.Select");
+
+dojo.require("dojo.widget.ComboBox");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.html.stabile");
+
+/*
+ * The Select widget is an enhanced version of HTML's <select> tag.
+ *
+ * Similar features:
+ *   - There is a drop down list of possible values.
+ *   - You can only enter a value from the drop down list.  (You can't enter an arbitrary value.)
+ *   - The value submitted with the form is the hidden value (ex: CA),
+       not the displayed value a.k.a. label (ex: California)
+ *
+ * Enhancements over plain HTML version:
+ *   - If you type in some text then it will filter down the list of possible values in the drop down list.
+ *   - List can be specified either as a static list or via a javascript function (that can get the list from a server)
+ */
+
+dojo.widget.defineWidget(
+	"dojo.widget.Select",
+	dojo.widget.ComboBox,
+	{
+		forceValidOption: true,
+
+		setValue: function(value) {
+			this.comboBoxValue.value = value;
+			dojo.widget.html.stabile.setState(this.widgetId, this.getState(), true);
+			this.onValueChanged(value);
+		},
+
+		setLabel: function(value){
+			// FIXME, not sure what to do here!
+			this.comboBoxSelectionValue.value = value;
+			if (this.textInputNode.value != value) { // prevent mucking up of selection
+				this.textInputNode.value = value;
+			}
+		},	  
+
+		getLabel: function(){
+			return this.comboBoxSelectionValue.value;
+		},
+
+		getState: function() {
+			return {
+				value: this.getValue(),
+				label: this.getLabel()
+			};
+		},
+
+		onKeyUp: function(evt){
+			this.setLabel(this.textInputNode.value);
+		},
+
+		setState: function(state) {
+			this.setValue(state.value);
+			this.setLabel(state.label);
+		},
+
+		setAllValues: function(value1, value2){
+			this.setValue(value2);
+			this.setLabel(value1);
+		}
+	}
+);

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Show.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Show.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Show.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Show.js Fri Sep 22 16:22:30 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.Show");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.uri.Uri");
+dojo.require("dojo.event.*");
+dojo.require("dojo.lfx.*");
+dojo.require("dojo.math.curves");
+dojo.require("dojo.lang.common");
+dojo.require("dojo.lang.func");
+
+dojo.widget.defineWidget(
+	"dojo.widget.Show",
+	dojo.widget.HtmlWidget,
+	function(){
+		this._slides=[];
+	},
+{
+	isContainer: true,
+	_slide: -1,
+
+	body: null,
+	nav: null,
+	hider: null,
+	select: null,
+	option: null,
+	inNav: false,
+	debugPane: null,
+	noClick: false,
+	templatePath: dojo.uri.dojoUri("src/widget/templates/Show.html"),
+	templateCssPath: dojo.uri.dojoUri("src/widget/templates/Show.css"),
+	fillInTemplate: function(args, frag){
+		if(args.debugPane){
+			var dp = this.debugPane = dojo.widget.byId(args.debugPane);
+			dp.hide();
+			dojo.event.connect(dp, "closeWindow", dojo.lang.hitch(this, function(){ this.debugPane = false; }));
+		}
+		var source = this.getFragNodeRef(frag);
+		this.sourceNode = dojo.body().appendChild(source.cloneNode(true));
+		for(var i = 0, child; child = this.sourceNode.childNodes[i]; i++){
+			if(child.tagName && child.getAttribute("dojotype").toLowerCase() == "showslide"){
+				child.className = "dojoShowPrintSlide";
+				child.innerHTML = "<h1>" + child.title + "</h1>" + child.innerHTML;
+			}
+		}
+		this.sourceNode.className = "dojoShowPrint";
+		this.sourceNode.style.display = "none";
+		
+		dojo.event.connect(document, "onclick", this, "gotoSlideByEvent");
+		if(dojo.render.html.ie) {
+			dojo.event.connect(document,"onkeydown",this, "gotoSlideByEvent");
+		} else {
+			// while keydown works, keypress allows rapid successive key presses
+			// to be handled correctly
+			dojo.event.connect(document,"onkeypress",this, "gotoSlideByEvent");
+		}
+		dojo.event.connect(window, "onresize", this, "resizeWindow");
+		dojo.event.connect(this.nav, "onmousemove", this, "popUpNav");
+	},
+	postCreate: function(){		
+		this._slides = [];
+		for(var i = 0, child; child = this.children[i]; i++){
+			if(child.widgetType == "ShowSlide"){
+				this._slides.push(child);
+				this.option.text = child.title+" ("+(i+1)+")";
+				this.option.parentNode.insertBefore(this.option.cloneNode(true), this.option);
+			}
+		}
+		this.option.parentNode.removeChild(this.option);
+
+		dojo.body().style.display = "block";
+		this.resizeWindow();
+
+		this.gotoSlide(0, true);
+
+		// check to see if we're initialized from a particular slide
+		dojo.addOnLoad(dojo.lang.hitch(this, 
+			function(){
+				var th = window.location.hash;
+				if(th.length){
+					var parts = (""+window.location).split(this.widgetId+"_SlideNo_");
+					if(parts.length > 1){
+						setTimeout(dojo.lang.hitch(this, function(){
+							this.gotoSlide(parseInt(parts[1]), true);
+						}), 300);
+					}
+				}
+			})
+		);
+	},
+	gotoSlide: function(/*int*/ slide, /*Boolean*/preventSetHash){
+		if(slide == this._slide){
+			return;
+		}
+
+		if(!this._slides[slide]){
+			// slide: string
+			for(var i = 0, child; child = this._slides[i]; i++){
+				if(child.title == slide){
+					slide = i;
+					break;
+				}
+			}
+		}
+		
+		if(!this._slides[slide]){
+			return;
+		}
+
+		if(this.debugPane){
+			if(this._slides[slide].debug){
+				this.debugPane.show();
+			}else{
+				this.debugPane.hide();
+			}
+		}
+		
+		if(this._slide != -1){
+			while(this._slides[this._slide].previousAction()){}
+		}
+
+		if(!preventSetHash){
+			window.location.href = "#"+this.widgetId+"_SlideNo_"+slide;
+		}
+		if(this._slides[this._slide]){
+			this._slides[this._slide].hide();
+		}
+		
+		this._slide = slide;
+		this.select.selectedIndex = slide;
+		var cn = this.contentNode;
+		while(cn.firstChild){ cn.removeChild(cn.firstChild); }
+		cn.appendChild(this._slides[slide].domNode);
+		this._slides[slide].show();
+	},
+	gotoSlideByEvent: function(/*Event*/ event){
+		var node = event.target;
+		var type = event.type;
+		if(type == "click"){
+			if(node.tagName == "OPTION" && node.parentNode == this.select){
+				this.gotoSlide(node.index);
+			}else if(node == this.select){
+				this.gotoSlide(node.selectedIndex);
+			}else{
+				this.nextSlide(event);
+			}
+		}else if (type=="keydown" || type=="keypress") {
+			var key = event.keyCode;
+			var ch = event.charCode;
+			if(key == 63234 || key == 37){
+				this.previousSlide(event);
+			}else if(key == 63235 || key == 39 || ch == 32){
+				this.nextSlide(event);
+			}
+		}
+	},
+	nextSlide: function(/*Event?*/ event){
+		if(!this.stopEvent(event)){
+			return false;
+		}
+		if(!this._slides[this._slide].nextAction(event)){
+			if((this._slide + 1) != this._slides.length){
+				this.gotoSlide(this._slide + 1);
+				return true; // boolean
+			}
+			return false; // boolean
+		}
+	},
+	previousSlide: function(/*Event?*/ event){
+		if(!this.stopEvent(event)){
+			return false;
+		}
+		if(!this._slides[this._slide].previousAction(event)){
+			if((this._slide - 1) != -1){
+				this.gotoSlide(this._slide - 1);
+				return true; // boolean
+			}
+			return false; // boolean
+		}
+	},
+
+	stopEvent: function(/*Event*/ ev){
+		if(!ev){
+			return true;
+		}
+	
+		if (ev.type == "click" && (this._slides[this._slide].noClick || this.noClick)) {
+			return false;
+		}	
+		var target = ev.target;
+		// Check to see if the target is below the show domNode
+		while(target != null){
+			if(target == this.domNode){
+				target = ev.target;
+				break;
+			}
+			target = target.parentNode;
+		}
+		// Now that we know it's below this widget's domNode, we bubble up until we get to our domNode
+		while(target && target != this.domNode){
+			if(target.tagName == "A" || target.tagName == "INPUT" || target.tagName == "TEXTAREA" || target.tagName == "SELECT"){
+				return false;
+			}
+			if(typeof target.onclick == "function" || typeof target.onkeypress == "function"){
+				return false;
+			}
+			target = target.parentNode;
+		}
+		
+		if(window.event){
+			ev.returnValue = false;
+			ev.cancelBubble = true;
+		}else{
+			ev.preventDefault();
+			ev.stopPropagation();
+		}
+		
+		return true;
+	},
+	popUpNav: function(){
+		if(!this.inNav){
+			// dojo.widget.Show.node = this.nav;
+			dojo.lfx.propertyAnimation(this.nav, {
+				"height": { start: 5, end: 30 }
+			}, 250).play();
+		}
+		clearTimeout(this.inNav);
+		this.inNav = setTimeout(dojo.lang.hitch(this, "hideNav"), 2000);
+	},
+	hideNav: function(){
+		clearTimeout(this.inNav);
+		this.inNav = false;
+		// dojo.widget.Show.node = this.nav;
+		dojo.lfx.propertyAnimation(this.nav, {
+			"height": { start: 30, end: 5 }
+		}, 250).play();
+	},
+	resizeWindow: function(/*Event*/ ev){
+		dojo.body().style.height = "auto";
+		var h = Math.max(
+			document.documentElement.scrollHeight || dojo.body().scrollHeight,
+			dojo.html.getViewport().height);
+		dojo.body().style.height = h + "px";
+	}
+});

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/ShowAction.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/ShowAction.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/ShowAction.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/ShowAction.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,24 @@
+/*
+	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.ShowAction");
+dojo.require("dojo.widget.*");
+
+dojo.widget.defineWidget(
+	"dojo.widget.ShowAction",
+	dojo.widget.HtmlWidget,
+{
+	on: "",
+	action: "fade",
+	duration: 350,
+	from: "",
+	to: "",
+	auto: "false"
+});

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/ShowSlide.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/ShowSlide.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/ShowSlide.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/ShowSlide.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,224 @@
+/*
+	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.ShowSlide");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.lang.common");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.lfx.html");
+dojo.require("dojo.html.display");
+dojo.require("dojo.html.layout");
+dojo.require("dojo.animation.Animation");
+dojo.require("dojo.gfx.color");
+
+dojo.widget.defineWidget(
+	"dojo.widget.ShowSlide",
+	dojo.widget.HtmlWidget,
+{
+	title: "",
+	_action: -1,
+	isContainer: true,
+	_components: {},
+	_actions: [],
+
+	gotoAction: function(/*int*/ action){
+		this._action = action;
+	},
+	_nextAction: function(/*Event?*/ event){
+		if((this._action + 1) != this._actions.length){
+			++this._action;
+			return true; // boolean
+		}
+		return false; // boolean
+	},
+	_previousAction: function(/*Event?*/ event){
+		if((this._action - 1) != -1){
+			--this._action;
+			return true; // boolean
+		}
+		return false; // boolean
+	},
+
+	htmlTitle: null,
+	debug: false,
+	noClick: false,
+	templatePath: dojo.uri.dojoUri("src/widget/templates/ShowSlide.html"),
+	templateCssPath: dojo.uri.dojoUri("src/widget/templates/ShowSlide.css"),
+	postCreate: function(){
+		this.htmlTitle.innerHTML = this.title;
+
+		var actions = this.getChildrenOfType("ShowAction", false);
+		var atypes = {};
+		dojo.lang.forEach(actions, function(act){ atypes[act.on] = true; });
+
+		this._components = {};
+		var cn = this.containerNode;
+		var nodes = dojo.render.html.ie ? cn.all : cn.getElementsByTagName('*');
+		dojo.lang.forEach(nodes, function(node){
+			var as = node.getAttribute("as");
+			if(as){
+				if(!this._components[as]){
+					this._components[as] = [];
+				}
+				this._components[as].push(node);
+				if(!atypes[as]){
+					var tmpAction = dojo.widget.createWidget("ShowAction", { on: as });
+					this.addChild(tmpAction);
+					atypes[as] = true;
+				}
+			}
+		}, this);
+
+		this._actions = [];
+		actions = this.getChildrenOfType("ShowAction", false);
+		dojo.lang.forEach(actions, function(child){
+			this._actions.push(child);
+			var components = this._components[child.on];
+			for(var j = 0, component; component = components[j]; j++){
+				if(child["action"] && (
+					(child.action != "remove")&&
+					(child.action != "fadeout")&&
+					(child.action != "wipeout")
+				) ){
+					this.hideComponent(component);
+				}
+			}
+		}, this);
+	},
+
+	previousAction: function(/*Event?*/ event){
+		if(!this.parent.stopEvent(event)){
+			return false;
+		}
+
+		var action = this._actions[this._action];
+		if(!action){
+			return false;
+		}
+
+		var on = action.on;
+		while(action.on == on){
+			var components = this._components[on];
+			for(var i = 0, component; component = components[i]; i++){
+				if(
+					(action.action == "remove")||
+					(action.action == "fadeout")||
+					(action.action == "wipeout")
+				){
+					if(component.style.display == "none"){
+						component.style.display = "";
+						component.style.visibility = "visible";
+						var exits = true;
+					}
+					dojo.html.setOpacity(component, 1);
+				}else if(action.action){
+					this.hideComponent(component);
+				}
+			}
+
+			--this._action;
+
+			if(exits){
+				return true;
+			}	
+
+			if(action.auto == "true"){
+				on = this._actions[this._action].on;
+			}
+
+			action = this._actions[this._action];
+			if(!action){
+				return false;
+			}
+		}
+		return true;
+	},
+	hideComponent: function(/*Node*/ component){
+		component.style.visibility = "hidden";
+		component.style.backgroundColor = "transparent";
+		var parent = component.parentNode;
+		if((parent)&&(parent.tagName.toLowerCase() == "li")){
+			parent.oldType = parent.style.listStyleType;
+			parent.style.listStyleType = "none";
+		}
+	},
+	nextAction: function(/*Event?*/ event){
+		if(!this.parent.stopEvent(event)){
+			return false;
+		}
+
+		if(!this._nextAction(this)){
+			return false;
+		}
+
+		var action = this._actions[this._action];
+		if(!action){
+			return false;
+		}
+		var tmpAction = action["action"];
+		
+		var components = this._components[action.on];
+		for(var i = 0, component; component = components[i]; i++){
+			if(tmpAction){
+				var duration = action.duration || 1000;
+				if((tmpAction == "fade")||(tmpAction == "fadeIn")){
+					dojo.html.setOpacity(component, 0);
+					dojo.lfx.html.fadeShow(component, duration).play(true);
+				}else if(tmpAction == "fadeout"){
+					dojo.lfx.html.fadeHide(component, duration).play(true);
+				}else if(tmpAction == "fly"){
+					var width = dojo.html.getMarginBox(component).width;
+					var position = dojo.html.getAbsolutePosition(component);
+					// alert(position);
+					component.style.position = "relative";
+					component.style.left = -(width + position.x) + "px";
+					dojo.lfx.html.slideBy(component, { top: 0, left: (width + position.x)}, duration, -1, this.callWith).play(true);
+				}else if((tmpAction == "wipe")||(tmpAction == "wipein")){
+					dojo.lfx.html.wipeIn(component, duration).play();
+				}else if(tmpAction == "wipeout"){
+					dojo.lfx.html.wipeOut(component, duration).play();
+				}else if(tmpAction == "color"){
+					var from = new dojo.gfx.color.Color(action.from).toRgb();
+					var to = new dojo.gfx.color.Color(action.to).toRgb();
+					var anim = new dojo.animation.Animation(new dojo.math.curves.Line(from, to), duration, 0);
+					var node = component;
+					dojo.event.connect(anim, "onAnimate", function(e) {
+						node.style.color = "rgb(" + e.coordsAsInts().join(",") + ")";
+					});
+					anim.play(true);
+				}else if(tmpAction == "bgcolor"){
+					dojo.lfx.html.unhighlight(component, action.to, duration).play();
+				}else if(tmpAction == "remove"){
+					component.style.display = "none";
+				}
+				component.style.visibility = "visible";
+			}
+		}
+		
+		action = this._actions[this._action + 1];
+		if(action && action.auto == "true"){
+			this.nextAction();
+		}
+
+		return true;
+	},
+	callWith: function(/*Node*/ node){
+		if(!node){ return; }
+		if(dojo.lang.isArray(node)){
+			dojo.lang.forEach(node, arguments.callee);
+			return;
+		}
+		var parent = node.parentNode;
+		if((parent)&&(parent.tagName.toLowerCase() == "li")){
+			parent.style.listStyleType = parent.oldType;
+		}
+	}
+});

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/SlideShow.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/SlideShow.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/SlideShow.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/SlideShow.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,141 @@
+/*
+	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.SlideShow");
+
+dojo.require("dojo.event.*");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.lfx.*");
+dojo.require("dojo.html.display");
+
+dojo.widget.defineWidget(
+	"dojo.widget.SlideShow",
+	dojo.widget.HtmlWidget,
+	{
+		templatePath: dojo.uri.dojoUri("src/widget/templates/SlideShow.html"),
+		templateCssPath: dojo.uri.dojoUri("src/widget/templates/SlideShow.css"),
+
+		// useful properties
+		imgUrls: [],		// the images we'll go through
+		imgUrlBase: "",
+		urlsIdx: 0,		// where in the images we are
+		delay: 4000, 		// give it 4 seconds
+		transitionInterval: 2000, // 2 seconds
+		imgWidth: 800,	// img width
+		imgHeight: 600,	// img height
+		background: "img2", // what's in the bg
+		foreground: "img1", // what's in the fg
+		stopped: false,	// should I stay or should I go?
+		fadeAnim: null, // references our animation
+
+		// our DOM nodes:
+		imagesContainer: null,
+		startStopButton: null,
+		controlsContainer: null,
+		img1: null,
+		img2: null,
+		preventCache: false,
+
+		fillInTemplate: function(){
+			// safari will cache the images and not fire an image onload event if
+			// there are only two images in the slideshow
+			if(dojo.render.html.safari && this.imgUrls.length == 2) {
+				this.preventCache = true;
+			}
+			dojo.html.setOpacity(this.img1, 0.9999);
+			dojo.html.setOpacity(this.img2, 0.9999);
+			with(this.imagesContainer.style){
+				width = this.imgWidth+"px";
+				height = this.imgHeight+"px";
+			}
+			with(this.img1.style){
+				width = this.imgWidth+"px";
+				height = this.imgHeight+"px";
+			}
+			with(this.img2.style){
+				width = this.imgWidth+"px";
+				height = this.imgHeight+"px";
+			}
+			if(this.imgUrls.length>1){
+				this.img2.src = this.imgUrlBase+this.imgUrls[this.urlsIdx++] + this.getUrlSuffix();
+				this.endTransition();
+			}else{
+				this.img1.src = this.imgUrlBase+this.imgUrls[this.urlsIdx++] + this.getUrlSuffix();
+			}
+		},
+
+		getUrlSuffix: function() {
+			if(this.preventCache) {
+				return "?ts=" + (new Date()).getTime();
+			} else {
+				return "";
+			}
+		},
+		
+		togglePaused: function(){
+			dojo.debug("pause");
+			if(this.stopped){
+				this.stopped = false;
+				this.backgroundImageLoaded();
+				this.startStopButton.value= "pause";
+			}else{
+				this.stopped = true;
+				this.startStopButton.value= "play";
+			}
+		},
+
+		backgroundImageLoaded: function(){
+			// start fading out the foreground image
+			if(this.stopped){ return; }
+
+			// actually start the fadeOut effect
+			// NOTE: if we wanted to use other transition types, we'd set them up
+			// 		 here as well
+			if(this.fadeAnim) {
+				this.fadeAnim.stop();
+			}
+			this.fadeAnim = dojo.lfx.fadeOut(this[this.foreground], 
+				this.transitionInterval, null);
+			dojo.event.connect(this.fadeAnim,"onEnd",this,"endTransition");
+			this.fadeAnim.play();
+		},
+
+		endTransition: function(){
+			// move the foreground image to the background 
+			with(this[this.background].style){ zIndex = parseInt(zIndex)+1; }
+			with(this[this.foreground].style){ zIndex = parseInt(zIndex)-1; }
+
+			// fg/bg book-keeping
+			var tmp = this.foreground;
+			this.foreground = this.background;
+			this.background = tmp;
+			// keep on truckin
+			this.loadNextImage();
+		},
+
+		loadNextImage: function(){
+			// load a new image in that container, and make sure it informs
+			// us when it finishes loading
+			dojo.event.kwConnect({
+				srcObj: this[this.background],
+				srcFunc: "onload",
+				adviceObj: this,
+				adviceFunc: "backgroundImageLoaded",
+				once: true, // make sure we only ever hear about it once
+				delay: this.delay
+			});
+			dojo.html.setOpacity(this[this.background], 1.0);
+			this[this.background].src = this.imgUrlBase+this.imgUrls[this.urlsIdx++];
+			if(this.urlsIdx>(this.imgUrls.length-1)){
+				this.urlsIdx = 0;
+			}
+		}
+	}
+);

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Slider.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Slider.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Slider.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Slider.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,876 @@
+/*
+	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)
+ *
+ * References (aka sources of inspiration):
+ *  - http://dojotoolkit.org/docs/fast_widget_authoring.html
+ *  - http://dojotoolkit.org/docs/dojo_event_system.html
+ * 
+ * $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.Slider");
+
+// load dependencies
+dojo.require("dojo.event.*");
+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.html.layout");
+
+
+/**
+ * Define the two dimensional slider widget class.
+ */
+dojo.widget.defineWidget (
+	"dojo.widget.Slider",
+	dojo.widget.HtmlWidget,
+	{
+		// useful properties (specified as attributes in the html tag)
+		// minimum value to be represented by slider in the horizontal direction
+		minimumX: 0,
+		// minimum value to be represented by slider in the vertical direction
+		minimumY: 0,
+		// maximum value to be represented by slider in the horizontal direction
+		maximumX: 10,
+		// maximum value to be represented by slider in the vertical direction
+		maximumY: 10,
+		// can values be changed on the x (horizontal) axis?
+		// number of values to be represented by slider in the horizontal direction
+		// =0 means no snapping
+		snapValuesX: 0,
+		// number of values to be represented by slider in the vertical direction
+		// =0 means no snapping
+		snapValuesY: 0,
+		// should the handle snap to the grid or remain where it was dragged to?
+		// FIXME: snapToGrid=false is logically in conflict with setting snapValuesX and snapValuesY
+		_snapToGrid: true,
+		// 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,
+		// left most edge of constraining container (pixels) in the X dimension
+		_minX: 0,
+		// top most edge of constraining container (pixels) in the Y dimension
+		_minY: 0,
+		// constrained slider size (pixels) in the x dimension
+		_constraintWidth: 0,
+		// constrained slider size (pixels) in the y dimension
+		_constraintHeight: 0,
+		// progress image right clip value (pixels) in the X dimension
+		_clipLeft: 0,
+		// progress image left clip value (pixels) in the X dimension
+		_clipRight: 0,
+		// progress image top clip value (pixels) in the Y dimension
+		_clipTop: 0,
+		// progress image bottom clip value (pixels) in the Y dimension
+		_clipBottom: 0,
+		// half the size of the slider handle (pixels) in the X dimension
+		_clipXdelta: 0,
+		// half the size of the slider handle (pixels) in the Y dimension
+		_clipYdelta: 0,
+		// initial value in the x dimension
+		initialValueX: 0,
+		// initial value in the y dimension
+		initialValueY: 0,
+		// values decrease in the X dimension
+		flipX: false,
+		// values decrease in the Y dimension
+		flipY: false,
+
+		// 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 value change while you are dragging, or just after drag finishes?
+		activeDrag: false,
+
+		templateCssPath: dojo.uri.dojoUri ("src/widget/templates/Slider.css"),
+		templatePath: dojo.uri.dojoUri ("src/widget/templates/Slider.html"),
+
+		// our DOM nodes
+		sliderHandleNode: null,
+		constrainingContainerNode: null,
+		sliderBackgroundNode: null,
+		progressBackgroundNode: null,
+		topButtonNode: null,
+		leftButtonNode: null,
+		rightButtonNode: null,
+		bottomButtonNode: null,
+		focusNode: null,
+
+		// private attributes
+		// This is set to true when a drag is started, so that it is not confused
+		// with a click
+		isDragInProgress: false,
+
+		// default user style attributes
+		widgetStyle: "",
+		buttonStyleX: "",
+		buttonStyleY: "",
+		bottomButtonSrc: dojo.uri.dojoUri("src/widget/templates/images/slider_down_arrow.png"),
+		topButtonSrc: dojo.uri.dojoUri("src/widget/templates/images/slider_up_arrow.png"),
+		leftButtonSrc: dojo.uri.dojoUri("src/widget/templates/images/slider_left_arrow.png"),
+		rightButtonSrc: dojo.uri.dojoUri("src/widget/templates/images/slider_right_arrow.png"),
+		backgroundSrc: dojo.uri.dojoUri("src/widget/templates/images/blank.gif"),
+		progressBackgroundSrc: dojo.uri.dojoUri("src/widget/templates/images/blank.gif"),
+		backgroundSize: "width:200px;height:200px;",
+		backgroundStyle: "",
+		handleStyle: "",
+		handleSrc: dojo.uri.dojoUri("src/widget/templates/images/slider-button.png"),
+		showButtons: true,
+		_eventCount: 0,
+		_typamaticTimer: null,
+		_typamaticFunction: null,
+		defaultTimeout: 500,
+		timeoutChangeRate: 0.90,
+		_currentTimeout: this.defaultTimeout,
+
+		// does the keyboard related stuff
+		_handleKeyEvents: function(evt){
+			var k = dojo.event.browser.keys;
+			var keyCode = evt.keyCode;
+
+			switch(keyCode){
+				case k.KEY_LEFT_ARROW:
+					dojo.event.browser.stopEvent(evt);
+					this._leftButtonPressed(evt);
+					return;
+				case k.KEY_RIGHT_ARROW:
+					dojo.event.browser.stopEvent(evt);
+					this._rightButtonPressed(evt);
+					return;
+				case k.KEY_DOWN_ARROW:
+					dojo.event.browser.stopEvent(evt);
+					this._bottomButtonPressed(evt);
+					return;
+				case k.KEY_UP_ARROW:
+					dojo.event.browser.stopEvent(evt);
+					this._topButtonPressed(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);
+			}
+		},
+
+		_pressButton: function(buttonNode){
+			buttonNode.className = buttonNode.className.replace("Outset","Inset");
+		},
+
+		_releaseButton: function(buttonNode){
+			buttonNode.className = buttonNode.className.replace("Inset","Outset");
+		},
+
+		_buttonPressed: function(evt, buttonNode){
+			this._setFocus();
+			if(typeof evt == "object"){
+				if(this._typamaticTimer != null){
+					if(this._typamaticNode == buttonNode){
+						return;
+					}
+					clearTimeout(this._typamaticTimer);
+				}
+				this._buttonReleased(null);
+				this._eventCount++;
+				this._typamaticTimer = null;
+				this._currentTimeout = this.defaultTimeout;
+				dojo.event.browser.stopEvent(evt);
+			}else if (evt != this._eventCount){
+				this._buttonReleased(null);
+				return false;
+			}
+			if (buttonNode == this.leftButtonNode && this.isEnableX) {
+				this._snapX(dojo.html.getPixelValue (this.sliderHandleNode,"left") - this._valueSizeX, this._handleMove );
+			}
+			else if (buttonNode == this.rightButtonNode && this.isEnableX) {
+				this._snapX(dojo.html.getPixelValue (this.sliderHandleNode,"left") + this._valueSizeX, this._handleMove );
+			}
+			else if (buttonNode == this.topButtonNode && this.isEnableY) {
+				this._snapY(dojo.html.getPixelValue (this.sliderHandleNode,"top") - this._valueSizeY, this._handleMove );
+			}
+			else if (buttonNode == this.bottomButtonNode && this.isEnableY) {
+				this._snapY(dojo.html.getPixelValue (this.sliderHandleNode,"top") + this._valueSizeY, this._handleMove );
+			}
+			else {
+				return false;
+			}
+			this._pressButton(buttonNode);
+			this.notifyListeners();
+			this._typamaticNode = buttonNode;
+			this._typamaticTimer = dojo.lang.setTimeout(this, "_buttonPressed", this._currentTimeout, this._eventCount, buttonNode);
+			this._currentTimeout = Math.round(this._currentTimeout * this.timeoutChangeRate);
+			return false;
+		},
+
+		_bottomButtonPressed: function(evt){
+			return this._buttonPressed(evt,this.bottomButtonNode);
+		},
+
+		// IE sends these events when rapid clicking, mimic an extra single click
+		_bottomButtonDoubleClicked: function(evt){
+			var rc = this._bottomButtonPressed(evt);
+			dojo.lang.setTimeout( this, "_buttonReleased", 50, null);
+			return rc;
+		},
+
+		_topButtonPressed: function(evt){
+			return this._buttonPressed(evt,this.topButtonNode);
+		},
+
+		// IE sends these events when rapid clicking, mimic an extra single click
+		_topButtonDoubleClicked: function(evt){
+			var rc = this._topButtonPressed(evt);
+			dojo.lang.setTimeout( this, "_buttonReleased", 50, null);
+			return rc;
+		},
+
+		_leftButtonPressed: function(evt) {
+			return this._buttonPressed(evt,this.leftButtonNode);
+		},
+
+		// IE sends these events when rapid clicking, mimic an extra single click
+		_leftButtonDoubleClicked: function(evt){
+			var rc = this._leftButtonPressed(evt);
+			dojo.lang.setTimeout( this, "_buttonReleased", 50, null);
+			return rc;
+		},
+
+		_rightButtonPressed: function(evt) {
+			return this._buttonPressed(evt,this.rightButtonNode);
+		},
+
+		// IE sends these events when rapid clicking, mimic an extra single click
+		_rightButtonDoubleClicked: function(evt){
+			var rc = this._rightButtonPressed(evt);
+			dojo.lang.setTimeout( this, "_buttonReleased", 50, null);
+			return rc;
+		},
+
+		_buttonReleased: function(evt){
+			if(typeof evt == "object" && evt != null && typeof evt.keyCode != "undefined" && evt.keyCode != null){
+				var keyCode = evt.keyCode;
+				var k = dojo.event.browser.keys;
+
+				switch(keyCode){
+					case k.KEY_LEFT_ARROW:
+					case k.KEY_RIGHT_ARROW:
+					case k.KEY_DOWN_ARROW:
+					case k.KEY_UP_ARROW:
+						dojo.event.browser.stopEvent(evt);
+						break;
+				}
+			}
+			this._releaseButton(this.topButtonNode);
+			this._releaseButton(this.bottomButtonNode);
+			this._releaseButton(this.leftButtonNode);
+			this._releaseButton(this.rightButtonNode);
+			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 (this.isEnableY) {
+				if(scrollAmount > 0){
+					this._topButtonPressed(evt);
+					this._buttonReleased(evt);
+				}else if (scrollAmount < 0){
+					this._bottomButtonPressed(evt);
+					this._buttonReleased(evt);
+				}
+			} else if (this.isEnableX) {
+				if(scrollAmount > 0){
+					this._rightButtonPressed(evt);
+					this._buttonReleased(evt);
+				}else if (scrollAmount < 0){
+					this._leftButtonPressed(evt);
+					this._buttonReleased(evt);
+				}
+			}
+		},
+
+		_discardEvent: function(evt) {
+			dojo.event.browser.stopEvent(evt);
+		},
+
+		_setFocus: function(){
+			if (this.focusNode.focus) {
+				this.focusNode.focus();
+			}
+		},
+
+		// remove comments from the node
+		_removeComments: function(parent){
+			var children = parent.childNodes;
+			for (var i = children.length-1; i >= 0; i--) {
+				var aChild = children.item(i);
+				if (aChild  != null) {
+					switch(aChild.nodeType){
+						case 1: // recurse
+							this._removeComments(aChild);
+							break;
+						case 8: // comment
+							parent.removeChild(aChild);
+					}
+				}
+			}
+		},
+
+		// This function is called when the template is loaded
+		fillInTemplate: function (args, frag) 
+		{
+			this._removeComments(this.domNode);
+			var source = this.getFragNodeRef(frag);
+			dojo.html.copyStyle(this.domNode, source);
+			// the user's style for the widget might include border and padding
+			// unfortunately, border isn't supported for inline elements
+			// so I get to fake everyone out by setting the border and padding
+			// of the outer table cells
+			var padding = this.domNode.style.padding;
+			if (dojo.lang.isString(padding) && padding != "" && padding != "0px" && padding != "0px 0px 0px 0px") {
+				this.topBorderNode.style.padding = 
+					this.bottomBorderNode.style.padding = padding;
+				this.topBorderNode.style.paddingBottom = "0px";
+				this.bottomBorderNode.style.paddingTop = "0px";
+				this.rightBorderNode.style.paddingRight = this.domNode.style.paddingRight;
+				this.leftBorderNode.style.paddingLeft= this.domNode.style.paddingLeft;
+				this.domNode.style.padding = "0px 0px 0px 0px";
+			}
+			var borderWidth = this.domNode.style.borderWidth;
+			if (dojo.lang.isString(borderWidth) && borderWidth != "" && borderWidth != "0px" && borderWidth != "0px 0px 0px 0px") {
+				this.topBorderNode.style.borderStyle = 
+					this.rightBorderNode.style.borderStyle = 
+					this.bottomBorderNode.style.borderStyle = 
+					this.leftBorderNode.style.borderStyle = 
+						this.domNode.style.borderStyle;
+				this.topBorderNode.style.borderColor = 
+					this.rightBorderNode.style.borderColor = 
+					this.bottomBorderNode.style.borderColor = 
+					this.leftBorderNode.style.borderColor = 
+						this.domNode.style.borderColor;
+				this.topBorderNode.style.borderWidth = 
+					this.bottomBorderNode.style.borderWidth = borderWidth;
+				this.topBorderNode.style.borderBottomWidth = "0px";
+				this.bottomBorderNode.style.borderTopWidth = "0px";
+				this.rightBorderNode.style.borderRightWidth = this.domNode.style.borderRightWidth;
+				this.leftBorderNode.style.borderLeftWidth = this.domNode.style.borderLeftWidth;
+				this.domNode.style.borderWidth = "0px 0px 0px 0px";
+			}
+
+			// dojo.debug ("fillInTemplate - className = " + this.domNode.className);
+
+			// setup drag-n-drop for the sliderHandle
+			this._handleMove = new dojo.widget._SliderDragMoveSource (this.sliderHandleNode);
+			this._handleMove.setParent (this);
+
+			if (this.clickSelect) {
+				dojo.event.connect (this.constrainingContainerNode, "onmousedown", this, "onClick");
+			} 
+
+			if (this.isEnableX) {
+				this.setValueX (!isNaN(this.initialValueX) ? this.initialValueX : (!isNaN(this.minimumX) ? this.minimumX : 0));
+			}
+			if (!this.isEnableX || !this.showButtons) {
+				this.rightButtonNode.style.width = "1px"; // allow the border to show
+				this.rightButtonNode.style.visibility = "hidden";
+				this.leftButtonNode.style.width = "1px"; // allow the border to show
+				this.leftButtonNode.style.visibility = "hidden";
+			}
+			if (this.isEnableY) {
+				this.setValueY (!isNaN(this.initialValueY) ? this.initialValueY : (!isNaN(this.minimumY) ? this.minimumY : 0));
+			}
+			if (!this.isEnableY || !this.showButtons) {
+				this.bottomButtonNode.style.width = "1px"; // allow the border to show
+				this.bottomButtonNode.style.visibility = "hidden";
+				this.topButtonNode.style.width = "1px"; // allow the border to show
+				this.topButtonNode.style.visibility = "hidden";
+			}
+			if(this.focusNode.addEventListener){
+				// dojo.event.connect() doesn't seem to work with DOMMouseScroll
+				this.focusNode.addEventListener('DOMMouseScroll', dojo.lang.hitch(this, "_mouseWheeled"), false); // Mozilla + Firefox + Netscape
+			}
+		},
+
+		// move the X value to the closest allowable value
+		_snapX: function (x,_handleMove) {
+			if (x < 0) { x = 0; }
+			else if (x > this._constraintWidth) { x = this._constraintWidth; }
+			else {
+				var selectedValue = Math.round (x / this._valueSizeX);
+				x = Math.round (selectedValue * this._valueSizeX);
+			}
+			this.sliderHandleNode.style.left = x + "px";
+			if (this.flipX) {
+				this._clipLeft = x + this._clipXdelta;
+			} else {
+				this._clipRight = x + this._clipXdelta;
+			}
+			this.progressBackgroundNode.style.clip = "rect("+this._clipTop+"px,"+this._clipRight+"px,"+this._clipBottom+"px,"+this._clipLeft+"px)";
+		},
+
+		// compute _valueSizeX & _constraintWidth & default snapValuesX
+		_calc_valueSizeX: function () {
+			var constrainingCtrBox = dojo.html.getContentBox(this.constrainingContainerNode);
+			var sliderHandleBox = dojo.html.getContentBox(this.sliderHandleNode);
+			if (constrainingCtrBox.width <= 0 || sliderHandleBox.width <= 0) { 
+				return false; 
+			}
+
+			this._constraintWidth = constrainingCtrBox.width 
+				+ dojo.html.getPadding(this.constrainingContainerNode).width
+				- sliderHandleBox.width;
+
+			if (this.flipX) {
+				this._clipLeft = this._clipRight = constrainingCtrBox.width;
+			} else {
+				this._clipLeft = this._clipRight = 0;
+			}
+			this._clipXdelta = sliderHandleBox.width >> 1;
+			if (!this.isEnableY) {
+				this._clipTop = 0;
+				this._clipBottom = constrainingCtrBox.height;
+			}
+
+			if (this._constraintWidth <= 0) { return false; }
+			if (this.snapValuesX == 0) {
+				this.snapValuesX = this._constraintWidth + 1;
+			}
+
+			this._valueSizeX = this._constraintWidth / (this.snapValuesX - 1);
+			return true;
+		},
+
+		// Move the handle (in the X dimension) to the specified value
+		setValueX: function (value) {
+			if (0.0 == this._valueSizeX) {
+				if (this._calc_valueSizeX () == false) {
+					dojo.lang.setTimeout(this, "setValueX", 100, value);
+					return;
+				}
+			}
+			if (isNaN(value)) {
+				value = 0;
+			}
+			if (value > this.maximumX) {
+				value = this.maximumX;
+			}
+			else if (value < this.minimumX) {
+				value = this.minimumX;
+			}
+			var pixelPercent = (value-this.minimumX) / (this.maximumX-this.minimumX);
+			if (this.flipX) {
+				pixelPercent = 1.0 - pixelPercent;
+			}
+			this._snapX (pixelPercent * this._constraintWidth, this._handleMove);
+			this.notifyListeners();
+		},
+
+
+		// Get the number of the value that matches the position of the handle
+		getValueX: function () {
+			var pixelPercent = dojo.html.getPixelValue (this.sliderHandleNode,"left") / this._constraintWidth;
+			if (this.flipX) {
+				pixelPercent = 1.0 - pixelPercent;
+			}
+			return Math.round (pixelPercent * (this.snapValuesX-1)) * ((this.maximumX-this.minimumX) / (this.snapValuesX-1)) + this.minimumX;
+		},
+
+		// move the Y value to the closest allowable value
+		_snapY: function (y,_handleMove) {
+			if (y < 0) { y = 0; }
+			else if (y > this._constraintHeight) { y = this._constraintHeight; }
+			else {
+				var selectedValue = Math.round (y / this._valueSizeY);
+				y = Math.round (selectedValue * this._valueSizeY);
+			}
+			this.sliderHandleNode.style.top = y + "px";
+			if (this.flipY) {
+				this._clipTop = y + this._clipYdelta;
+			} else {
+				this._clipBottom = y + this._clipYdelta;
+			}
+			this.progressBackgroundNode.style.clip = "rect("+this._clipTop+"px,"+this._clipRight+"px,"+this._clipBottom+"px,"+this._clipLeft+"px)";
+		},
+		// compute _valueSizeY & _constraintHeight & default snapValuesY
+		_calc_valueSizeY: function () {
+			var constrainingCtrBox = dojo.html.getContentBox(this.constrainingContainerNode);
+			var sliderHandleBox = dojo.html.getContentBox(this.sliderHandleNode);
+			if (constrainingCtrBox.height <= 0 || sliderHandleBox.height <= 0) { 
+				return false; 
+			}
+
+			this._constraintHeight = constrainingCtrBox.height
+				+ dojo.html.getPadding(this.constrainingContainerNode).height
+				- sliderHandleBox.height;
+
+			if (this.flipY) {
+				this._clipTop = this._clipBottom = constrainingCtrBox.height;
+			} else {
+				this._clipTop = this._clipBottom = 0;
+			}
+			this._clipYdelta = sliderHandleBox.height >> 1;
+			if (!this.isEnableX) {
+				this._clipLeft = 0;
+				this._clipRight = constrainingCtrBox.width;
+			}
+
+			if (this._constraintHeight <= 0) { return false; }
+			if (this.snapValuesY == 0) {
+				this.snapValuesY = this._constraintHeight + 1;
+			}
+
+			this._valueSizeY = this._constraintHeight / (this.snapValuesY - 1);
+			return true;
+		},
+
+		// set the slider to a particular value
+		setValueY: function (value) {
+			if (0.0 == this._valueSizeY) {
+				if (this._calc_valueSizeY () == false) {
+					dojo.lang.setTimeout(this, "setValueY", 100, value);
+					return;
+				}
+			}
+			if (isNaN(value)) {
+				value = 0;
+			}
+			if (value > this.maximumY) {
+				value = this.maximumY;
+			}
+			else if (value < this.minimumY) {
+				value = this.minimumY;
+			}
+			var pixelPercent = (value-this.minimumY) / (this.maximumY-this.minimumY);
+			if (this.flipY) {
+				pixelPercent = 1.0 - pixelPercent;
+			}
+			this._snapY (pixelPercent * this._constraintHeight, this._handleMove);
+			this.notifyListeners();
+		},
+
+		// Get the number of the value that the matches the position of the handle
+		getValueY: function () {
+			var pixelPercent = dojo.html.getPixelValue (this.sliderHandleNode,"top") / this._constraintHeight;
+			if (this.flipY) {
+				pixelPercent = 1.0 - pixelPercent;
+			}
+			return Math.round (pixelPercent * (this.snapValuesY-1)) * ((this.maximumY-this.minimumY) / (this.snapValuesY-1)) + this.minimumY;
+		},
+
+		// set the position of the handle
+		onClick: function (evt) {
+			if (this.isDragInProgress) {
+				return;
+			}
+
+			var offset = dojo.html.getScroll().offset;
+			var parent = dojo.html.getAbsolutePosition(this.constrainingContainerNode, true);
+			var content = dojo.html.getContentBox(this._handleMove.domNode);			
+			if (this.isEnableX) {
+				var x = offset.x + evt.clientX - parent.x - (content.width >> 1);
+				this._snapX(x, this._handleMove);
+			}
+			if (this.isEnableY) {
+				var y = offset.y + evt.clientY - parent.y - (content.height >> 1);
+				this._snapY(y, this._handleMove);
+			}
+			this.notifyListeners();
+		},
+
+		notifyListeners: function() {
+			this.onValueChanged(this.getValueX(), this.getValueY());
+		},
+
+		onValueChanged: function(x, y){
+		}
+	}
+);
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/**
+ * Define the horizontal slider widget class.
+ */
+dojo.widget.defineWidget (
+	"dojo.widget.SliderHorizontal",
+	dojo.widget.Slider,
+	{
+		widgetType: "SliderHorizontal",
+
+		isEnableX: true,
+		isEnableY: false,
+		initialValue: "",
+		snapValues: "",
+		minimum: "",
+		maximum: "",
+		buttonStyle: "",
+		backgroundSize: "height:10px;width:200px;",
+		backgroundSrc: dojo.uri.dojoUri("src/widget/templates/images/slider-bg.gif"),
+		flip: false,
+
+		postMixInProperties: function(){
+			dojo.widget.SliderHorizontal.superclass.postMixInProperties.apply(this, arguments);
+			if (!isNaN(parseFloat(this.initialValue))) {
+				this.initialValueX = parseFloat(this.initialValue);
+			}
+			if (!isNaN(parseFloat(this.minimum))) {
+				this.minimumX = parseFloat(this.minimum);
+			}
+			if (!isNaN(parseFloat(this.maximum))) {
+				this.maximumX = parseFloat(this.maximum);
+			}
+			if (!isNaN(parseInt(this.snapValues))) {
+				this.snapValuesX = parseInt(this.snapValues);
+			}
+			if (dojo.lang.isString(this.buttonStyle) && this.buttonStyle != "") {
+				this.buttonStyleX = this.buttonStyle;
+			}
+			if (dojo.lang.isBoolean(this.flip)) {
+				this.flipX = this.flip;
+			}
+		},
+
+		notifyListeners: function() {
+			this.onValueChanged(this.getValueX());
+		},
+
+		// wrapper for getValueX
+		getValue: function () {
+			return this.getValueX ();
+		},
+
+		// wrapper for setValueX
+		setValue: function (value) {
+			this.setValueX (value);
+		},
+
+		onValueChanged: function(value){
+		}
+	}
+);
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/**
+ * Define the vertical slider widget class.
+ */
+dojo.widget.defineWidget (
+	"dojo.widget.SliderVertical",
+	dojo.widget.Slider,
+	{
+		widgetType: "SliderVertical",
+
+		isEnableX: false,
+		isEnableY: true,
+		initialValue: "",
+		snapValues: "",
+		minimum: "",
+		maximum: "",
+		buttonStyle: "",
+		backgroundSize: "width:10px;height:200px;",
+		backgroundSrc: dojo.uri.dojoUri("src/widget/templates/images/slider-bg-vert.gif"),
+		flip: false,
+
+		postMixInProperties: function(){
+			dojo.widget.SliderVertical.superclass.postMixInProperties.apply(this, arguments);
+			if (!isNaN(parseFloat(this.initialValue))) {
+				this.initialValueY = parseFloat(this.initialValue);
+			}
+			if (!isNaN(parseFloat(this.minimum))) {
+				this.minimumY = parseFloat(this.minimum);
+			}
+			if (!isNaN(parseFloat(this.maximum))) {
+				this.maximumY = parseFloat(this.maximum);
+			}
+			if (!isNaN(parseInt(this.snapValues))) {
+				this.snapValuesY = parseInt(this.snapValues);
+			}
+			if (dojo.lang.isString(this.buttonStyle) && this.buttonStyle != "") {
+				this.buttonStyleY = this.buttonStyle;
+			}
+			if (dojo.lang.isBoolean(this.flip)) {
+				this.flipY = this.flip;
+			}
+		},
+
+		notifyListeners: function() {
+			this.onValueChanged(this.getValueY());
+		},
+
+		// wrapper for getValueY
+		getValue: function () {
+			return this.getValueY ();
+		},
+
+		// wrapper for setValueY
+		setValue: function (value) {
+			this.setValueY (value);
+		},
+
+		onValueChanged: function(value){
+		}
+	}
+);
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/**
+ * This class extends the HtmlDragMoveSource class to provide
+ * features for the slider handle.
+ */
+dojo.declare (
+	"dojo.widget._SliderDragMoveSource",
+	dojo.dnd.HtmlDragMoveSource,
+{
+	slider: null,
+
+	/** Setup the handle for drag
+	 *  Extends dojo.dnd.HtmlDragMoveSource by creating a SliderDragMoveSource */
+	onDragStart: function (evt) {
+		this.slider.isDragInProgress = true;
+		if (this.slider.isEnableX) {
+			this.slider._minX = dojo.html.getAbsolutePosition(this.slider.constrainingContainerNode).x;
+		}
+		if (this.slider.isEnableY) {
+			this.slider._minY = dojo.html.getAbsolutePosition(this.slider.constrainingContainerNode).y;
+		}
+
+		var dragObj = this.createDragMoveObject ();
+
+		this.slider.notifyListeners();
+		return dragObj;
+	},
+
+	onDragEnd: function (evt) {
+		this.slider.isDragInProgress = false;
+		this.slider.notifyListeners();
+	},
+
+	createDragMoveObject: function () {
+		//dojo.debug ("SliderDragMoveSource#createDragMoveObject - " + this.slider);
+		var dragObj = new dojo.widget._SliderDragMoveObject (this.dragObject, this.type);
+		dragObj.slider = this.slider;
+
+		// this code copied from dojo.dnd.HtmlDragSource#onDragStart
+		if (this.dragClass) { 
+			dragObj.dragClass = this.dragClass; 
+		}
+
+		return dragObj;
+	},
+
+
+	setParent: function (slider) {
+		this.slider = slider;
+	}
+});
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/**
+ * This class extends the HtmlDragMoveObject class to provide
+ * features for the slider handle.
+ */
+dojo.declare (
+	"dojo.widget._SliderDragMoveObject",
+	dojo.dnd.HtmlDragMoveObject,
+{
+	// reference to dojo.widget.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 (evt) {
+		this.updateDragOffset ();
+
+		var offset = dojo.html.getScroll().offset;
+		if (this.slider.isEnableX) {
+			var x = this.dragOffset.x + evt.pageX - this.slider._minX - offset.x;
+			this.slider._snapX(x, this.slider._handleMove);
+		}
+
+		if (this.slider.isEnableY) {
+			var y = this.dragOffset.y + evt.pageY - this.slider._minY - offset.y;
+			this.slider._snapY(y, this.slider._handleMove);
+		}
+		if(this.slider.activeDrag){
+			this.slider.notifyListeners();
+		}
+	}
+});

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