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/09/29 05:43:06 UTC

svn commit: r451106 [27/40] - in /tapestry/tapestry4/trunk: ./ tapestry-framework/src/java/org/apache/tapestry/asset/ tapestry-framework/src/js/dojo/ tapestry-framework/src/js/dojo/src/ tapestry-framework/src/js/dojo/src/animation/ tapestry-framework/s...

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/FisheyeList.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/FisheyeList.js?view=auto&rev=451106
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/FisheyeList.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/FisheyeList.js Thu Sep 28 20:42:39 2006
@@ -0,0 +1,741 @@
+/*
+	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.FisheyeList");
+dojo.provide("dojo.widget.FisheyeListItem");
+
+//
+// TODO
+// fix SVG support, and turn it on only if the browser supports it
+// fix really long labels in vertical mode
+//
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.html.style");
+dojo.require("dojo.html.selection");
+dojo.require("dojo.html.util");
+dojo.require("dojo.event.*");
+
+dojo.widget.defineWidget(
+	"dojo.widget.FisheyeList",
+	dojo.widget.HtmlWidget,
+{
+	templateString: '<div class="dojoHtmlFisheyeListBar"></div>',
+	templateCssPath: dojo.uri.dojoUri("src/widget/templates/FisheyeList.css"),
+
+	EDGE: {
+		CENTER: 0,
+		LEFT: 1,
+		RIGHT: 2,
+		TOP: 3,
+		BOTTOM: 4
+	},
+
+	isContainer: true,
+	snarfChildDomOutput: true,
+	
+	pos: {x: -1, y: -1},		// current cursor position, relative to the grid
+	
+	// for conservative trigger mode, when triggered, timerScale is gradually increased from 0 to 1
+	timerScale: 1.0,
+
+	/////////////////////////////////////////////////////////////////
+	//
+	// i spy OPTIONS!!!!
+	//
+
+	itemWidth: 40,
+	itemHeight: 40,
+
+	itemMaxWidth: 150,
+	itemMaxHeight: 150,
+
+	orientation: 'horizontal',
+	
+	conservativeTrigger: false,		// don't active menu until mouse is over an image (macintosh style)
+
+	effectUnits: 2,
+	itemPadding: 10,
+
+	attachEdge: 'center',
+	labelEdge: 'bottom',
+
+	enableCrappySvgSupport: false,
+
+
+	//
+	//
+	//
+	/////////////////////////////////////////////////////////////////
+
+	fillInTemplate: function(args, frag) {
+		//dojo.debug(this.orientation);
+
+		dojo.html.disableSelection(this.domNode);
+
+		this.isHorizontal = (this.orientation == 'horizontal') ? 1 : 0;
+		this.selectedNode = -1;
+
+		this.isOver = false;
+		this.hitX1 = -1;
+		this.hitY1 = -1;
+		this.hitX2 = -1;
+		this.hitY2 = -1;
+
+		//
+		// only some edges make sense...
+		//
+
+		this.anchorEdge = this.toEdge(this.attachEdge, this.EDGE.CENTER);
+		this.labelEdge  = this.toEdge(this.labelEdge,  this.EDGE.TOP);
+
+		if ( this.isHorizontal && (this.anchorEdge == this.EDGE.LEFT  )){ this.anchorEdge = this.EDGE.CENTER; }
+		if ( this.isHorizontal && (this.anchorEdge == this.EDGE.RIGHT )){ this.anchorEdge = this.EDGE.CENTER; }
+		if (!this.isHorizontal && (this.anchorEdge == this.EDGE.TOP   )){ this.anchorEdge = this.EDGE.CENTER; }
+		if (!this.isHorizontal && (this.anchorEdge == this.EDGE.BOTTOM)){ this.anchorEdge = this.EDGE.CENTER; }
+
+		if (this.labelEdge == this.EDGE.CENTER){ this.labelEdge = this.EDGE.TOP; }
+		if ( this.isHorizontal && (this.labelEdge == this.EDGE.LEFT  )){ this.labelEdge = this.EDGE.TOP; }
+		if ( this.isHorizontal && (this.labelEdge == this.EDGE.RIGHT )){ this.labelEdge = this.EDGE.TOP; }
+		if (!this.isHorizontal && (this.labelEdge == this.EDGE.TOP   )){ this.labelEdge = this.EDGE.LEFT; }
+		if (!this.isHorizontal && (this.labelEdge == this.EDGE.BOTTOM)){ this.labelEdge = this.EDGE.LEFT; }
+
+
+		//
+		// figure out the proximity size
+		//
+
+		this.proximityLeft   = this.itemWidth  * (this.effectUnits - 0.5);
+		this.proximityRight  = this.itemWidth  * (this.effectUnits - 0.5);
+		this.proximityTop    = this.itemHeight * (this.effectUnits - 0.5);
+		this.proximityBottom = this.itemHeight * (this.effectUnits - 0.5);
+
+		if (this.anchorEdge == this.EDGE.LEFT){
+			this.proximityLeft = 0;
+		}
+		if (this.anchorEdge == this.EDGE.RIGHT){
+			this.proximityRight = 0;
+		}
+		if (this.anchorEdge == this.EDGE.TOP){
+			this.proximityTop = 0;
+		}
+		if (this.anchorEdge == this.EDGE.BOTTOM){
+			this.proximityBottom = 0;
+		}
+		if (this.anchorEdge == this.EDGE.CENTER){
+			this.proximityLeft   /= 2;
+			this.proximityRight  /= 2;
+			this.proximityTop    /= 2;
+			this.proximityBottom /= 2;
+		}
+	},
+	
+	postCreate: function(args, frag) {
+		this.initializePositioning();
+
+		//
+		// in liberal trigger mode, activate menu whenever mouse is close
+		//
+		if( !this.conservativeTrigger ){
+			dojo.event.connect(document.documentElement, "onmousemove", this, "mouseHandler");
+		}
+		
+		// Deactivate the menu if mouse is moved off screen (doesn't work for FF?)
+		dojo.event.connect(document.documentElement, "onmouseout", this, "onBodyOut");
+		dojo.event.connect(this, "addChild", this, "initializePositioning");
+	},
+
+	initializePositioning: function(){
+		this.itemCount = this.children.length;
+
+		this.barWidth  = (this.isHorizontal ? this.itemCount : 1) * this.itemWidth;
+		this.barHeight = (this.isHorizontal ? 1 : this.itemCount) * this.itemHeight;
+
+		this.totalWidth  = this.proximityLeft + this.proximityRight  + this.barWidth;
+		this.totalHeight = this.proximityTop  + this.proximityBottom + this.barHeight;
+
+		//
+		// calculate effect ranges for each item
+		//
+
+		for (var i=0; i<this.children.length; i++){
+
+			this.children[i].posX = this.itemWidth  * (this.isHorizontal ? i : 0);
+			this.children[i].posY = this.itemHeight * (this.isHorizontal ? 0 : i);
+
+			this.children[i].cenX = this.children[i].posX + (this.itemWidth  / 2);
+			this.children[i].cenY = this.children[i].posY + (this.itemHeight / 2);
+
+			var isz = this.isHorizontal ? this.itemWidth : this.itemHeight;
+			var r = this.effectUnits * isz;
+			var c = this.isHorizontal ? this.children[i].cenX : this.children[i].cenY;
+			var lhs = this.isHorizontal ? this.proximityLeft : this.proximityTop;
+			var rhs = this.isHorizontal ? this.proximityRight : this.proximityBottom;
+			var siz = this.isHorizontal ? this.barWidth : this.barHeight;
+
+			var range_lhs = r;
+			var range_rhs = r;
+
+			if (range_lhs > c+lhs){ range_lhs = c+lhs; }
+			if (range_rhs > (siz-c+rhs)){ range_rhs = siz-c+rhs; }
+
+			this.children[i].effectRangeLeft = range_lhs / isz;
+			this.children[i].effectRangeRght = range_rhs / isz;
+
+			//dojo.debug('effect range for '+i+' is '+range_lhs+'/'+range_rhs);
+		}
+
+
+		//
+		// create the bar
+		//
+
+		this.domNode.style.width = this.barWidth + 'px';
+		this.domNode.style.height = this.barHeight + 'px';
+
+
+		//
+		// position the items
+		//
+		for (var i=0; i<this.children.length; i++){
+			var itm = this.children[i];
+			var elm = itm.domNode;
+			elm.style.left   = itm.posX + 'px';
+			elm.style.top    = itm.posY + 'px';
+			elm.style.width  = this.itemWidth + 'px';
+			elm.style.height = this.itemHeight + 'px';
+			
+			if ( itm.svgNode ) {
+				itm.svgNode.style.position = 'absolute';
+				itm.svgNode.style.left = this.itemPadding+'%';
+				itm.svgNode.style.top = this.itemPadding+'%';
+				itm.svgNode.style.width = (100 - 2 * this.itemPadding) + '%';
+				itm.svgNode.style.height = (100 - 2 * this.itemPadding) + '%';
+				itm.svgNode.style.zIndex = 1;
+	
+				itm.svgNode.setSize(this.itemWidth, this.itemHeight);
+			} else {
+				itm.imgNode.style.left = this.itemPadding+'%';
+				itm.imgNode.style.top = this.itemPadding+'%';
+				itm.imgNode.style.width = (100 - 2 * this.itemPadding) + '%';
+				itm.imgNode.style.height = (100 - 2 * this.itemPadding) + '%';
+			}
+		}
+
+		//
+		// calc the grid
+		//
+
+		this.calcHitGrid();
+	},
+
+	onBodyOut: function(e){
+		// clicking over an object inside of body causes this event to fire; ignore that case
+		if( dojo.html.overElement(dojo.body(), e) ){
+			return;
+		}
+		this.setDormant(e);
+	},
+
+	// when mouse moves out of menu's range
+	setDormant: function(e){
+		if( !this.isOver ){ return; }	// already dormant?
+		this.isOver = false;
+
+		if ( this.conservativeTrigger ) {
+			// user can't re-trigger the menu expansion
+			// until he mouses over a icon again
+			dojo.event.disconnect(document.documentElement, "onmousemove", this, "mouseHandler");
+		}
+		this.onGridMouseMove(-1, -1);
+	},
+
+	// when mouse is moved into menu's range
+	setActive: function(e){
+		if( this.isOver ){ return; }	// already activated?
+		this.isOver = true;
+
+		if ( this.conservativeTrigger ) {
+			// switch event handlers so that we handle mouse events from anywhere near
+			// the menu
+			dojo.event.connect(document.documentElement, "onmousemove", this, "mouseHandler");
+
+			this.timerScale=0.0;
+
+			// call mouse handler to do some initial necessary calculations/positioning
+			this.mouseHandler(e);
+
+			// slowly expand the icon size so it isn't jumpy
+			this.expandSlowly();
+		}
+	},
+
+	// when mouse is moved
+	mouseHandler: function(e) {
+		if ((e.pageX >= this.hitX1) && (e.pageX <= this.hitX2) &&
+			(e.pageY >= this.hitY1) && (e.pageY <= this.hitY2)){
+			if( !this.isOver ){
+				this.setActive(e);
+			}
+			this.onGridMouseMove(e.pageX-this.hitX1, e.pageY-this.hitY1);
+		}else{
+			if (this.isOver){
+				this.setDormant(e);
+			}
+		}
+	},
+
+	onResized: function() {
+		this.calcHitGrid();
+	},
+
+	onGridMouseMove: function(x, y){
+		this.pos = {x:x, y:y};
+		this.paint();
+	},
+	
+	paint: function(){
+		var x=this.pos.x;
+		var y=this.pos.y;
+
+		if( this.itemCount <= 0 ){ return; }
+
+		//
+		// figure out our main index
+		//
+
+		var pos = this.isHorizontal ? x : y;
+		var prx = this.isHorizontal ? this.proximityLeft : this.proximityTop;
+		var siz = this.isHorizontal ? this.itemWidth : this.itemHeight;
+		var sim = this.isHorizontal ? 
+			(1.0-this.timerScale)*this.itemWidth + this.timerScale*this.itemMaxWidth :
+			(1.0-this.timerScale)*this.itemHeight + this.timerScale*this.itemMaxHeight ;
+
+		var cen = ((pos - prx) / siz) - 0.5;
+		var max_off_cen = (sim / siz) - 0.5;
+
+		if (max_off_cen > this.effectUnits){ max_off_cen = this.effectUnits; }
+
+
+		//
+		// figure out our off-axis weighting
+		//
+
+		var off_weight = 0;
+
+		if (this.anchorEdge == this.EDGE.BOTTOM){
+			var cen2 = (y - this.proximityTop) / this.itemHeight;
+			off_weight = (cen2 > 0.5) ? 1 : y / (this.proximityTop + (this.itemHeight / 2));
+		}
+		if (this.anchorEdge == this.EDGE.TOP){
+			var cen2 = (y - this.proximityTop) / this.itemHeight;
+			off_weight = (cen2 < 0.5) ? 1 : (this.totalHeight - y) / (this.proximityBottom + (this.itemHeight / 2));
+		}
+		if (this.anchorEdge == this.EDGE.RIGHT){
+			var cen2 = (x - this.proximityLeft) / this.itemWidth;
+			off_weight = (cen2 > 0.5) ? 1 : x / (this.proximityLeft + (this.itemWidth / 2));
+		}
+		if (this.anchorEdge == this.EDGE.LEFT){
+			var cen2 = (x - this.proximityLeft) / this.itemWidth;
+			off_weight = (cen2 < 0.5) ? 1 : (this.totalWidth - x) / (this.proximityRight + (this.itemWidth / 2));
+		}
+		if (this.anchorEdge == this.EDGE.CENTER){
+
+			if (this.isHorizontal){
+				off_weight = y / (this.totalHeight);
+			}else{
+				off_weight = x / (this.totalWidth);
+			}
+
+			if (off_weight > 0.5){
+				off_weight = 1 - off_weight;
+			}
+
+			off_weight *= 2;
+		}
+
+
+		//
+		// set the sizes
+		//
+
+		for(var i=0; i<this.itemCount; i++){
+
+			var weight = this.weightAt(cen, i);
+
+			if (weight < 0){weight = 0;}
+
+			this.setitemsize(i, weight * off_weight);
+		}
+
+		//
+		// set the positions
+		//
+
+		var main_p = Math.round(cen);
+		var offset = 0;
+
+		if (cen < 0){
+			main_p = 0;
+
+		}else if (cen > this.itemCount - 1){
+
+			main_p = this.itemCount -1;
+
+		}else{
+
+			offset = (cen - main_p) * ((this.isHorizontal ? this.itemWidth : this.itemHeight) - this.children[main_p].sizeMain);
+		}
+
+		this.positionElementsFrom(main_p, offset);
+	},
+
+	weightAt: function(cen, i){
+
+		var dist = Math.abs(cen - i);
+
+		var limit = ((cen - i) > 0) ? this.children[i].effectRangeRght : this.children[i].effectRangeLeft;
+
+		return (dist > limit) ? 0 : (1 - dist / limit);
+	},
+
+	positionFromNode: function(p, w){
+
+		//
+		// we need to grow all the nodes growing out from node 'i'
+		//
+
+		this.setitemsize(p, w);
+
+		var wx = w;
+		for(var i=p; i<this.itemCount; i++){
+			wx = 0.8 * wx;
+			this.setitemsize(i, wx);
+		}
+
+		var wx = w;
+		for(var i=p; i>=0; i--){
+			wx = 0.8 * wx;
+			this.setitemsize(i, wx);
+		}
+	},
+
+	setitemsize: function(p, scale){
+		scale *= this.timerScale;
+		var w = Math.round(this.itemWidth  + ((this.itemMaxWidth  - this.itemWidth ) * scale));
+		var h = Math.round(this.itemHeight + ((this.itemMaxHeight - this.itemHeight) * scale));
+
+		if (this.isHorizontal){
+
+			this.children[p].sizeW = w;
+			this.children[p].sizeH = h;
+
+			this.children[p].sizeMain = w;
+			this.children[p].sizeOff  = h;
+
+			var y = 0;
+
+			if (this.anchorEdge == this.EDGE.TOP){
+
+				y = (this.children[p].cenY - (this.itemHeight / 2));
+
+			}else if (this.anchorEdge == this.EDGE.BOTTOM){
+
+				y = (this.children[p].cenY - (h - (this.itemHeight / 2)));
+
+			}else{
+
+				y = (this.children[p].cenY - (h / 2));
+			}
+
+			this.children[p].usualX = Math.round(this.children[p].cenX - (w / 2));
+			
+			this.children[p].domNode.style.top  = y + 'px';
+
+			this.children[p].domNode.style.left  = this.children[p].usualX + 'px';
+
+		}else{
+
+			this.children[p].sizeW = w;
+			this.children[p].sizeH = h;
+
+			this.children[p].sizeOff  = w;
+			this.children[p].sizeMain = h;
+
+			var x = 0;
+
+			if (this.anchorEdge == this.EDGE.LEFT){
+
+				x = this.children[p].cenX - (this.itemWidth / 2);
+
+			}else if (this.anchorEdge == this.EDGE.RIGHT){
+
+				x = this.children[p].cenX - (w - (this.itemWidth / 2));
+			}else{
+
+				x = this.children[p].cenX - (w / 2);
+			}
+
+			this.children[p].domNode.style.left = x + 'px';
+			this.children[p].usualY = Math.round(this.children[p].cenY - (h / 2));
+
+			this.children[p].domNode.style.top  = this.children[p].usualY + 'px';
+		}
+
+		this.children[p].domNode.style.width  = w + 'px';
+		this.children[p].domNode.style.height = h + 'px';
+
+		if (this.children[p].svgNode){
+			this.children[p].svgNode.setSize(w, h);
+		}
+	},
+
+	positionElementsFrom: function(p, offset){
+
+		var pos = 0;
+
+		if (this.isHorizontal){
+			pos = Math.round(this.children[p].usualX + offset);
+			this.children[p].domNode.style.left = pos + 'px';
+		}else{
+			pos = Math.round(this.children[p].usualY + offset);
+			this.children[p].domNode.style.top = pos + 'px';
+		}
+		this.positionLabel(this.children[p]);
+
+
+		//
+		// position before
+		//
+
+		var bpos = pos;
+
+		for(var i=p-1; i>=0; i--){
+
+			bpos -= this.children[i].sizeMain;
+
+			if (this.isHorizontal){
+				this.children[i].domNode.style.left = bpos + 'px';
+			}else{
+				this.children[i].domNode.style.top = bpos + 'px';
+			}
+			this.positionLabel(this.children[i]);
+		}
+
+		//
+		// position after
+		//
+
+		var apos = pos;
+
+		for(var i=p+1; i<this.itemCount; i++){
+
+			apos += this.children[i-1].sizeMain;
+
+			if (this.isHorizontal){
+				this.children[i].domNode.style.left = apos + 'px';
+			}else{
+				this.children[i].domNode.style.top = apos + 'px';
+			}
+			this.positionLabel(this.children[i]);
+		}
+
+	},
+
+	positionLabel: function(itm){
+
+		var x = 0;
+		var y = 0;
+		
+		var mb = dojo.html.getMarginBox(itm.lblNode);
+
+		if (this.labelEdge == this.EDGE.TOP){
+			x = Math.round((itm.sizeW / 2) - (mb.width / 2));
+			y = -mb.height;
+		}
+
+		if (this.labelEdge == this.EDGE.BOTTOM){
+			x = Math.round((itm.sizeW / 2) - (mb.width / 2));
+			y = itm.sizeH;
+		}
+
+		if (this.labelEdge == this.EDGE.LEFT){
+			x = -mb.width;
+			y = Math.round((itm.sizeH / 2) - (mb.height / 2));
+		}
+
+		if (this.labelEdge == this.EDGE.RIGHT){
+			x = itm.sizeW;
+			y = Math.round((itm.sizeH / 2) - (mb.height / 2));
+		}
+
+		itm.lblNode.style.left = x + 'px';
+		itm.lblNode.style.top  = y + 'px';
+	},
+
+	calcHitGrid: function(){
+
+		var pos = dojo.html.getAbsolutePosition(this.domNode, true);
+
+		this.hitX1 = pos.x - this.proximityLeft;
+		this.hitY1 = pos.y - this.proximityTop;
+		this.hitX2 = this.hitX1 + this.totalWidth;
+		this.hitY2 = this.hitY1 + this.totalHeight;
+
+		//dojo.debug(this.hitX1+','+this.hitY1+' // '+this.hitX2+','+this.hitY2);
+	},
+
+	toEdge: function(inp, def){
+		return this.EDGE[inp.toUpperCase()] || def;
+	},
+	
+	// slowly expand the image to user specified max size
+	expandSlowly: function(){
+		if( !this.isOver ){ return; }
+		this.timerScale += 0.2;
+		this.paint();
+		if ( this.timerScale<1.0 ) {
+			dojo.lang.setTimeout(this, "expandSlowly", 10);
+		}
+	},
+
+	destroy: function(){
+		// need to disconnect when we destroy
+		dojo.event.disconnect(document.documentElement, "onmouseout", this, "onBodyOut");
+		dojo.event.disconnect(document.documentElement, "onmousemove", this, "mouseHandler");
+		dojo.widget.FisheyeList.superclass.destroy.call(this);
+	}
+});
+
+dojo.widget.defineWidget(
+	"dojo.widget.FisheyeListItem",
+	dojo.widget.HtmlWidget,
+{
+	// Constructor arguments
+	iconSrc: "",
+	svgSrc: "",
+	caption: "",
+	// will be set to the id of the orginal div element
+	id: "",
+
+	blankImgPath: dojo.uri.dojoUri("src/widget/templates/images/blank.gif"),
+
+	templateString:
+		'<div class="dojoHtmlFisheyeListItem">' +
+		'  <img class="dojoHtmlFisheyeListItemImage" dojoAttachPoint="imgNode" dojoAttachEvent="onMouseOver;onMouseOut;onClick">' +
+		'  <div class="dojoHtmlFisheyeListItemLabel" dojoAttachPoint="lblNode"></div>' +
+		'</div>',
+	
+	imgNode: null,
+
+	fillInTemplate: function() {
+		//
+		// set image
+		// TODO: turn on/off SVG support based on browser version.
+		// this.parent.enableCrappySvgSupport is not available to this function
+		//
+		if (this.svgSrc != ""){
+			this.svgNode = this.createSvgNode(this.svgSrc);
+			this.domNode.appendChild(this.svgNode);
+			this.imgNode.style.display = 'none';
+		} else if((this.iconSrc.toLowerCase().substring(this.iconSrc.length-4)==".png")&&(dojo.render.html.ie)&&(!dojo.render.html.ie70)){
+			/* we set the id of the new fisheyeListItem to the id of the div defined in the HTML */
+			if (dojo.dom.hasParent(this.imgNode) && this.id != ""){
+				var parent = this.imgNode.parentNode;
+				parent.setAttribute("id", this.id);
+			}
+			this.imgNode.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+this.iconSrc+"', sizingMethod='scale')";
+			this.imgNode.src = this.blankImgPath.toString();
+		} else {
+			if (dojo.dom.hasParent(this.imgNode) && this.id != ""){
+				var parent = this.imgNode.parentNode;
+				parent.setAttribute("id", this.id);
+			}
+			this.imgNode.src = this.iconSrc;
+		}
+
+		//
+		// Label
+		//
+		if ( this.lblNode ) {
+			this.lblNode.appendChild(document.createTextNode(this.caption));
+		}
+		dojo.html.disableSelection(this.domNode);
+	},
+	
+	createSvgNode: function(src){
+
+		var elm = document.createElement('embed');
+		elm.src = src;
+		elm.type = 'image/svg+xml';
+		//elm.style.border = '1px solid black';
+		elm.style.width = '1px';
+		elm.style.height = '1px';
+		elm.loaded = 0;
+		elm.setSizeOnLoad = false;
+
+		elm.onload = function(){
+			this.svgRoot = this.getSVGDocument().rootElement;
+			this.svgDoc = this.getSVGDocument().documentElement;
+			this.zeroWidth = this.svgRoot.width.baseVal.value;
+			this.zeroHeight = this.svgRoot.height.baseVal.value;
+			this.loaded = true;
+
+			if (this.setSizeOnLoad){
+				this.setSize(this.setWidth, this.setHeight);
+			}
+		}
+
+		elm.setSize = function(w, h){
+			if (!this.loaded){
+				this.setWidth = w;
+				this.setHeight = h;
+				this.setSizeOnLoad = true;
+				return;
+			}
+
+			this.style.width = w+'px';
+			this.style.height = h+'px';
+			this.svgRoot.width.baseVal.value = w;
+			this.svgRoot.height.baseVal.value = h;
+
+			var scale_x = w / this.zeroWidth;
+			var scale_y = h / this.zeroHeight;
+
+			for(var i=0; i<this.svgDoc.childNodes.length; i++){
+				if (this.svgDoc.childNodes[i].setAttribute){
+					this.svgDoc.childNodes[i].setAttribute( "transform", "scale("+scale_x+","+scale_y+")" );
+				}
+			}
+		}
+
+		return elm;
+	},
+
+	onMouseOver: function(e) {
+		// in conservative mode, don't activate the menu until user mouses over an icon
+		if( !this.parent.isOver ){
+			this.parent.setActive(e);
+		}
+		if ( this.caption != "" ) {
+			dojo.html.addClass(this.lblNode, "selected");
+			this.parent.positionLabel(this);
+		}
+	},
+	
+	onMouseOut: function() {
+		dojo.html.removeClass(this.lblNode, "selected");
+	},
+
+	onClick: function() {
+	}
+});
+

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/FloatingPane.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/FloatingPane.js?view=auto&rev=451106
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/FloatingPane.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/FloatingPane.js Thu Sep 28 20:42:39 2006
@@ -0,0 +1,386 @@
+/*
+	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.FloatingPane");
+
+//
+// this widget provides a window-like floating pane
+//
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.Manager");
+dojo.require("dojo.html.*");
+dojo.require("dojo.html.layout");
+dojo.require("dojo.html.iframe");
+dojo.require("dojo.html.selection");
+dojo.require("dojo.lfx.shadow");
+dojo.require("dojo.widget.html.layout");
+dojo.require("dojo.widget.ContentPane");
+dojo.require("dojo.dnd.HtmlDragMove");
+dojo.require("dojo.dnd.HtmlDragMoveSource");
+dojo.require("dojo.dnd.HtmlDragMoveObject");
+dojo.require("dojo.widget.ResizeHandle");
+
+dojo.declare(
+	"dojo.widget.FloatingPaneBase",
+	null,
+	{
+		// Constructor arguments
+		title: '',
+		iconSrc: '',
+		hasShadow: false,
+		constrainToContainer: false,
+		taskBarId: "",
+		resizable: true,
+		titleBarDisplay: "fancy",
+
+		windowState: "normal",
+		displayCloseAction: false,
+		displayMinimizeAction: false,
+		displayMaximizeAction: false,
+
+		maxTaskBarConnectAttempts: 5,
+		taskBarConnectAttempts: 0,
+
+		templatePath: dojo.uri.dojoUri("src/widget/templates/FloatingPane.html"),
+		templateCssPath: dojo.uri.dojoUri("src/widget/templates/FloatingPane.css"),
+
+		drag: null,
+
+		fillInFloatingPaneTemplate: function(args, frag){
+			// Copy style info from input node to output node
+			var source = this.getFragNodeRef(frag);
+			dojo.html.copyStyle(this.domNode, source);
+	
+			// necessary for safari, khtml (for computing width/height)
+			dojo.body().appendChild(this.domNode);
+	
+			// if display:none then state=minimized, otherwise state=normal
+			if(!this.isShowing()){
+				this.windowState="minimized";
+			}
+	
+			// <img src=""> can hang IE!  better get rid of it
+			if(this.iconSrc==""){
+				dojo.html.removeNode(this.titleBarIcon);
+			}else{
+				this.titleBarIcon.src = this.iconSrc.toString();// dojo.uri.Uri obj req. toString()
+			}
+	
+			if(this.titleBarDisplay!="none"){	
+				this.titleBar.style.display="";
+				dojo.html.disableSelection(this.titleBar);
+	
+				this.titleBarIcon.style.display = (this.iconSrc=="" ? "none" : "");
+	
+				this.minimizeAction.style.display = (this.displayMinimizeAction ? "" : "none");
+				this.maximizeAction.style.display= 
+					(this.displayMaximizeAction && this.windowState!="maximized" ? "" : "none");
+				this.restoreAction.style.display= 
+					(this.displayMaximizeAction && this.windowState=="maximized" ? "" : "none");
+				this.closeAction.style.display= (this.displayCloseAction ? "" : "none");
+	
+				this.drag = new dojo.dnd.HtmlDragMoveSource(this.domNode);	
+				if (this.constrainToContainer) {
+					this.drag.constrainTo();
+				}
+				this.drag.setDragHandle(this.titleBar);
+	
+				var self = this;
+	
+				dojo.event.topic.subscribe("dragMove",
+					function (info){
+						if (info.source.domNode == self.domNode){
+							dojo.event.topic.publish('floatingPaneMove', { source: self } );
+						}
+					}
+				);
+			}
+	
+			if(this.resizable){
+				this.resizeBar.style.display="";
+				this.resizeHandle = dojo.widget.createWidget("ResizeHandle", {targetElmId: this.widgetId, id:this.widgetId+"_resize"});
+				this.resizeBar.appendChild(this.resizeHandle.domNode);
+			}
+	
+			// add a drop shadow
+			if(this.hasShadow){
+				this.shadow=new dojo.lfx.shadow(this.domNode);
+			}
+	
+			// Prevent IE bleed-through problem
+			this.bgIframe = new dojo.html.BackgroundIframe(this.domNode);
+	
+			if( this.taskBarId ){
+				this.taskBarSetup();
+			}
+	
+			// counteract body.appendChild above
+			dojo.body().removeChild(this.domNode);
+		},
+	
+		postCreate: function(){
+			if (dojo.hostenv.post_load_) {
+				this.setInitialWindowState();
+			} else {
+				dojo.addOnLoad(this, "setInitialWindowState");
+			}
+		},
+	
+		maximizeWindow: function(evt) {
+			var mb = dojo.html.getMarginBox(this.domNode);
+			this.previous={
+				width: mb.width || this.width,
+				height: mb.height || this.height,
+				left: this.domNode.style.left,
+				top: this.domNode.style.top,
+				bottom: this.domNode.style.bottom,
+				right: this.domNode.style.right
+			};
+			if(this.domNode.parentNode.style.overflow.toLowerCase() != 'hidden'){
+				this.parentPrevious={
+					overflow: this.domNode.parentNode.style.overflow
+				};
+				dojo.debug(this.domNode.parentNode.style.overflow);
+				this.domNode.parentNode.style.overflow = 'hidden';
+			}
+
+			this.domNode.style.left =
+				dojo.html.getPixelValue(this.domNode.parentNode, "padding-left", true) + "px";
+			this.domNode.style.top =
+				dojo.html.getPixelValue(this.domNode.parentNode, "padding-top", true) + "px";
+
+			if ((this.domNode.parentNode.nodeName.toLowerCase() == 'body')) {
+				var viewport = dojo.html.getViewport();
+				var padding = dojo.html.getPadding(dojo.body());
+				this.resizeTo(viewport.width-padding.width, viewport.height-padding.height);
+			} else {
+				var content = dojo.html.getContentBox(this.domNode.parentNode);
+				this.resizeTo(content.width, content.height);
+			}
+			this.maximizeAction.style.display="none";
+			this.restoreAction.style.display="";
+
+			//disable resize and drag
+			if(this.resizeHandle){
+				this.resizeHandle.domNode.style.display="none";
+			}
+			this.drag.setDragHandle(null);
+
+			this.windowState="maximized";
+		},
+	
+		minimizeWindow: function(evt) {
+			this.hide();
+			for(var attr in this.parentPrevious){
+				this.domNode.parentNode.style[attr] = this.parentPrevious[attr];
+			}
+			this.lastWindowState = this.windowState;
+			this.windowState = "minimized";
+		},
+	
+		restoreWindow: function(evt) {
+			if (this.windowState=="minimized") {
+				this.show();
+				if(this.lastWindowState == "maximized"){
+					this.domNode.parentNode.style.overflow = 'hidden';
+					this.windowState="maximized";
+				}else{ //normal
+					this.windowState="normal";
+				}
+			} else if (this.windowState=="maximized"){
+				for(var attr in this.previous){
+					this.domNode.style[attr] = this.previous[attr];
+				}
+				for(var attr in this.parentPrevious){
+					this.domNode.parentNode.style[attr] = this.parentPrevious[attr];
+				}
+				this.resizeTo(this.previous.width, this.previous.height);
+				this.previous=null;
+				this.parentPrevious=null;
+
+				this.restoreAction.style.display="none";
+				this.maximizeAction.style.display=this.displayMaximizeAction ? "" : "none";
+
+				if(this.resizeHandle){
+					this.resizeHandle.domNode.style.display="";
+				}
+				this.drag.setDragHandle(this.titleBar);
+				this.windowState="normal";
+			} else { //normal
+				// do nothing
+			}
+		},
+
+		toggleDisplay: function(){
+			if(this.windowState=="minimized"){
+				this.restoreWindow();
+			}else{
+				this.minimizeWindow();
+			}
+		},
+
+		closeWindow: function(evt) {
+			dojo.html.removeNode(this.domNode);
+			this.destroy();
+		},
+	
+		onMouseDown: function(evt) {
+			this.bringToTop();
+		},
+	
+		bringToTop: function() {
+			var floatingPanes= dojo.widget.manager.getWidgetsByType(this.widgetType);
+			var windows = [];
+			for (var x=0; x<floatingPanes.length; x++) {
+				if (this.widgetId != floatingPanes[x].widgetId) {
+						windows.push(floatingPanes[x]);
+				}
+			}
+	
+			windows.sort(function(a,b) {
+				return a.domNode.style.zIndex - b.domNode.style.zIndex;
+			});
+			
+			windows.push(this);
+	
+			var floatingPaneStartingZ = 100;
+			for (x=0; x<windows.length;x++) {
+				windows[x].domNode.style.zIndex = floatingPaneStartingZ + x*2;
+			}
+		},
+	
+		setInitialWindowState: function() {
+			if(this.isShowing()){
+				this.width=-1;	// force resize
+				var mb = dojo.html.getMarginBox(this.domNode);
+				this.resizeTo(mb.width, mb.height);
+			}
+			if (this.windowState == "maximized") {
+				this.maximizeWindow();
+				this.show();
+				return;
+			}
+	
+			if (this.windowState=="normal") {
+				this.show();
+				return;
+			}
+	
+			if (this.windowState=="minimized") {
+				this.hide();
+				return;
+			}
+	
+			this.windowState="minimized";
+		},
+	
+		// add icon to task bar, connected to me
+		taskBarSetup: function() {
+			var taskbar = dojo.widget.getWidgetById(this.taskBarId);
+			if (!taskbar){
+				if (this.taskBarConnectAttempts <  this.maxTaskBarConnectAttempts) {
+					dojo.lang.setTimeout(this, this.taskBarSetup, 50);
+					this.taskBarConnectAttempts++;
+				} else {
+					dojo.debug("Unable to connect to the taskBar");
+				}
+				return;
+			}
+			taskbar.addChild(this);
+		},
+
+		showFloatingPane: function(){
+			this.bringToTop();
+		},
+
+		onFloatingPaneShow: function(){
+			var mb = dojo.html.getMarginBox(this.domNode);
+			this.resizeTo(mb.width, mb.height);
+		},
+	
+		// This is called when the user adjusts the size of the floating pane
+		resizeTo: function(w, h){
+			dojo.html.setMarginBox(this.domNode, { width: w, height: h });
+	
+			dojo.widget.html.layout(this.domNode,
+				[
+				  {domNode: this.titleBar, layoutAlign: "top"},
+				  {domNode: this.resizeBar, layoutAlign: "bottom"},
+				  {domNode: this.containerNode, layoutAlign: "client"}
+				] );
+	
+			// If any of the children have layoutAlign specified, obey it
+			dojo.widget.html.layout(this.containerNode, this.children, "top-bottom");
+			
+			this.bgIframe.onResized();
+			if(this.shadow){ this.shadow.size(w, h); }
+			this.onResized();
+		},
+	
+		checkSize: function() {
+			// checkSize() is called when the user has resized the browser window,
+			// but that doesn't affect this widget (or this widget's children)
+			// so it can be safely ignored...
+			// TODO: unless we are maximized.  then we should resize ourself.
+		}
+	}
+);
+
+dojo.widget.defineWidget(
+	"dojo.widget.FloatingPane",
+	[dojo.widget.ContentPane, dojo.widget.FloatingPaneBase], 
+{
+	fillInTemplate: function(args, frag){	
+		this.fillInFloatingPaneTemplate(args, frag);
+		dojo.widget.FloatingPane.superclass.fillInTemplate.call(this, args, frag);
+	},
+	postCreate: function(){
+		dojo.widget.FloatingPaneBase.prototype.postCreate.apply(this, arguments);
+		dojo.widget.FloatingPane.superclass.postCreate.apply(this, arguments);
+	},
+	show: function(){
+		dojo.widget.FloatingPane.superclass.show.apply(this, arguments);
+		this.showFloatingPane();
+	},
+	onShow: function(){
+		dojo.widget.FloatingPane.superclass.onShow.call(this);
+		this.onFloatingPaneShow();
+	}
+});
+
+dojo.require("dojo.widget.Dialog");
+dojo.widget.defineWidget(
+	"dojo.widget.ModalFloatingPane",
+	[dojo.widget.FloatingPane, dojo.widget.ModalDialogBase],
+	{
+		windowState: "minimized",
+		displayCloseAction: true,
+		postCreate: function(){
+			dojo.widget.ModalDialogBase.prototype.postCreate.call(this);
+			dojo.widget.ModalFloatingPane.superclass.postCreate.call(this);
+		},
+		show: function(){
+			dojo.widget.ModalFloatingPane.superclass.show.apply(this, arguments);
+			this.showModalDialog();
+			this.placeModalDialog();
+			//place the background div under this modal pane
+			this.shared.bg.style.zIndex = this.domNode.style.zIndex-1;
+		},
+		hide: function(){
+			this.hideModalDialog();
+			dojo.widget.ModalFloatingPane.superclass.hide.apply(this, arguments);
+		},
+		closeWindow: function(){
+			this.hide();
+			dojo.widget.ModalFloatingPane.superclass.closeWindow.apply(this, arguments);
+		}
+	}
+);

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/FormContainer.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/FormContainer.js?view=auto&rev=451106
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/FormContainer.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/FormContainer.js Thu Sep 28 20:42:39 2006
@@ -0,0 +1,222 @@
+/*
+	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.FormContainer");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlWidget");
+
+dojo.widget.defineWidget("dojo.widget.FormContainer", dojo.widget.HtmlWidget,
+	{
+		isContainer: true,
+
+		_getFormElement: function(name) {
+			for(var i=0, len=this.domNode.elements.length; i<len; i++) {
+				var element = this.domNode.elements[i];
+				if (element.name == name) {
+					return element;
+				} // if
+			} // for
+			return null;
+		},
+
+		_getObject: function(obj, searchString) {
+			var namePath = [];
+			namePath=searchString.split(".");
+			var myObj=obj;
+			var name=namePath[namePath.length-1];
+
+			for(var j=0, len=namePath.length;j<len;++j) {
+				var p=namePath[j];
+				if (typeof(myObj[p]) == "undefined") {
+					myObj[p]={};
+				}
+				myObj=myObj[p];
+			}
+			return myObj;
+		},
+		_setToContainers: function (obj, widget) {
+			for(var i=0, len=widget.children.length; i<len; ++i) {
+				if (widget.children[i].widgetType == "RepeaterContainer") {
+					var rIndex=widget.children[i].index;
+					var rIndexPos=rIndex.indexOf("%{index}");
+					rIndex=rIndex.substr(0,rIndexPos-1);
+					var myObj = this._getObject(obj, rIndex);
+					if (typeof(myObj) == "object" && myObj.length == 0) {
+						myObj=[];
+					}
+					var rowCount = widget.children[i].getRowCount();
+					if (myObj.length > rowCount) {
+						for (var j=rowCount, len2=myObj.length; j<len2; j++) {
+							widget.children[i].addRow();
+						}
+					} else if (myObj.length < rowCount) {
+						for (var j=rowCount, len2=myObj.length; j>len2; j--) {
+							widget.children[i].deleteRow(0);
+						}
+					}
+					for (var j=0, len2=myObj.length;j<len2; ++j) {
+						for (var key in myObj[j]) {
+							var prefix = dojo.string.substituteParams(widget.children[i].index, {"index": "" + j});
+							this._getFormElement(prefix+"."+key).value=myObj[j][key];
+						}
+					}
+				}
+
+				if (widget.children[i].isContainer) {
+					this._setToContainers (obj, widget.children[i]);
+					continue;
+				}
+
+				switch(widget.children[i].widgetType) {
+					case "Checkbox":
+						continue;
+						break;
+					case "DropdownDatePicker":
+						if(widget.children[i].valueNode.value == "") {
+							widget.children[i].inputNode.value="";
+							widget.children[i].datePicker.storedDate="";
+						} else {
+							widget.children[i].datePicker.setDate(widget.children[i].valueNode.value);
+							//widget.children[i].datePicker.date=dojo.widget.DatePicker.util.fromRfcDate(widget.children[i].valueNode.value);
+							widget.children[i].onSetDate();
+						}
+						break;
+					case "Select":
+						//widget.children[i].setValue(myObj[name]);
+						continue;
+						break;
+					case "ComboBox":
+						//widget.children[i].setSelectedValue(myObj[name]);
+						continue;
+						break;
+					default:
+						break;
+				}
+			}
+		},
+		setValues: function(obj) {
+			for(var i=0, len=this.domNode.elements.length; i<len; i++) {
+				var element = this.domNode.elements[i];
+				if (element.name == '') {continue};
+				var namePath = new Array();
+				namePath=element.name.split(".");
+				var myObj=obj;
+				var name=namePath[namePath.length-1];
+				for(var j=1,len2=namePath.length;j<len2;++j) {
+					var p=namePath[j - 1];
+					if(typeof(myObj[p]) == "undefined") {
+						myObj=undefined;
+						break;
+						//myObj[p]={}
+					};
+					myObj=myObj[p];
+				}
+
+				if (typeof(myObj) == "undefined") {
+					continue;
+				}
+
+				var type=element.type;
+				if (type == "hidden" || type == "text" || type == "textarea" || type == "password") {
+					type = "text";
+				}
+				switch(type) {
+					case "checkbox":
+						this.domNode.elements[i].checked=false;
+						if (typeof(myObj[name]) == 'undefined') continue;
+						for (var j=0,len2=myObj[name].length; j<len2; ++j) {
+							if(element.value == myObj[name][j]) {
+								element.checked=true;
+							}
+						}
+						break;
+					case "radio":
+						this.domNode.elements[i].checked=false;
+						if (typeof(myObj[name]) == 'undefined') {continue};
+						if (myObj[name] == this.domNode.elements[i].value) {
+							this.domNode.elements[i].checked=true;
+						}
+						break;
+					case "select-one":
+						this.domNode.elements[i].selectedIndex="0";
+						for (var j=0,len2=element.options.length; j<len2; ++j) {
+							if (element.options[j].value == myObj[name]) {
+								element.options[j].selected=true;
+							} else {
+								//element.options[j].selected=false;
+							}
+						}
+						break;
+					case "text":
+						var value="";
+						if (typeof(myObj[name]) == 'string') {
+							value = myObj[name];
+						}
+						this.domNode.elements[i].value=value;
+						break;
+					default:
+						//dojo.debug("Not supported type ("+type+")");
+						break;
+				}
+      }
+			this._setToContainers(obj,this);
+		},
+		getValues: function() {
+			var obj = { };
+
+			for(var i=0,len=this.domNode.elements.length; i<len; i++) {
+				// FIXME: would be better to give it an attachPoint:
+				var elm = this.domNode.elements[i];
+				var namePath = [];
+				if (elm.name == '') { continue;}
+				namePath=elm.name.split(".");
+				var myObj=obj;
+				var name=namePath[namePath.length-1];
+				for(var j=1,len2=namePath.length;j<len2;++j) {
+					var nameIndex = null;
+					var p=namePath[j - 1];
+					var nameA=p.split("[");
+					if (nameA.length > 1) {
+						if(typeof(myObj[nameA[0]]) == "undefined") {
+							myObj[nameA[0]]=[ ];
+						} // if
+						nameIndex=parseInt(nameA[1]);
+						if(typeof(myObj[nameA[0]][nameIndex]) == "undefined") {
+							myObj[nameA[0]][nameIndex]={};
+						}
+					} else if(typeof(myObj[nameA[0]]) == "undefined") {
+						myObj[nameA[0]]={}
+					} // if
+
+					if (nameA.length == 1) {
+						myObj=myObj[nameA[0]];
+					} else {
+						myObj=myObj[nameA[0]][nameIndex];
+					} // if
+				} // for
+
+				if ((elm.type != "checkbox" && elm.type != "radio") || (elm.type=="radio" && elm.checked)) {
+					if(name == name.split("[")[0]) {
+						myObj[name]=elm.value;
+					} else {
+						// can not set value when there is no name
+					}
+				} else if (elm.type == "checkbox" && elm.checked) {
+					if(typeof(myObj[name]) == 'undefined') {
+						myObj[name]=[ ];
+					}
+					myObj[name].push(elm.value);
+				} // if
+				name=undefined;
+			} // for
+		return obj;
+	}
+});

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/GoogleMap.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/GoogleMap.js?view=auto&rev=451106
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/GoogleMap.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/GoogleMap.js Thu Sep 28 20:42:39 2006
@@ -0,0 +1,208 @@
+/*
+	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.GoogleMap");
+dojo.require("dojo.event.*");
+dojo.require("dojo.math");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.uri.Uri");
+dojo.require("dojo.widget.HtmlWidget");
+
+(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_){
+		if(!gkey || gkey==""){
+			dojo.raise("dojo.widget.GoogleMap: The Google Map widget requires a proper API key in order to be used.");
+		}
+		var tag = "<scr"+"ipt src='http://maps.google.com/maps?file=api&amp;v=2&amp;key="+gkey+"'></scri"+"pt>";
+		if(!dj_global["GMap2"]){
+			document.write(tag);
+		}
+	}else{
+		dojo.debug("Cannot initialize Google 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.defineWidget(
+	"dojo.widget.GoogleMap",
+	dojo.widget.HtmlWidget,
+	function(){
+		this.map=null;
+		this.geocoder=null;
+		this.data=[];
+		this.datasrc="";
+		this.controls=["largemap","scale","maptype"];
+	},
+{
+	templatePath:null,
+	templateCssPath:null,
+	isContainer: false,
+
+	_defaultPoint:{lat:39.10662, lng: -94.578209},
+
+	setControls:function(){
+		var methodmap={
+			largemap:GLargeMapControl,
+			smallmap:GSmallMapControl,
+			smallzoom:GSmallZoomControl,
+			scale:GScaleControl,
+			maptype:GMapTypeControl,
+			overview:GOverviewMapControl
+		};
+		for(var i=0; i<this.controls.length; i++){
+			this.map.addControl(new (methodmap[this.controls[i].toLowerCase()])());
+		}
+	},
+	
+	findCenter:function(bounds){
+		if(this.data.length==1){
+			return (new GLatLng(this.data[0].lat, this.data[0].lng));
+		}
+		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;
+	},
+	plot:function(obj){
+		var p=new GLatLng(obj.lat,obj.lng);
+		var d=obj.description||null;
+		var m=this.createPinpoint(p,d);
+		this.map.addOverlay(m);
+	},
+	plotAddress:function(address){
+		var self=this;
+		this.geocoder.getLocations(address, function(response){
+			if(!response || response.Status.code != 200){
+				alert("The address \"" + address + "\" was not found.");
+				return;
+			}
+			var obj={
+				lat:response.Placemark[0].Point.coordinates[1],
+				lng:response.Placemark[0].Point.coordinates[0],
+				description:response.Placemark[0].address
+			};
+			self.data.push(obj);
+			self.render();
+		});
+	},
+
+	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(){
+		if(this.data.length==0){
+			this.map.setCenter(new GLatLng(this._defaultPoint.lat, this._defaultPoint.lng), 4);
+			return;
+		}
+
+		//	remove all overlays
+		this.map.clearOverlays();
+
+		var bounds=new GLatLngBounds();
+		var d=this.data;
+		for(var i=0; i<d.length; i++){
+			bounds.extend(new GLatLng(d[i].lat,d[i].lng));
+		}
+		var zoom=Math.min((this.map.getBoundsZoomLevel(bounds)-1),14);
+		this.map.setCenter(this.findCenter(bounds), zoom);
+
+		for(var i=0; i<this.data.length; i++){
+			this.plot(this.data[i]);
+		}
+	},
+
+	initialize:function(args, frag){
+		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.domNode.style.position!="absolute"){
+			this.domNode.style.position="relative";
+		}
+		this.map=new GMap2(this.domNode);
+		try{
+			this.geocoder=new GClientGeocoder();
+		}catch(ex){}
+		this.render();
+		this.setControls();
+	}
+});

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/HslColorPicker.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/HslColorPicker.js?view=auto&rev=451106
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/HslColorPicker.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/HslColorPicker.js Thu Sep 28 20:42:39 2006
@@ -0,0 +1,142 @@
+/*
+	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.HslColorPicker");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.widget.HslColorPicker");
+dojo.require("dojo.math");
+dojo.require("dojo.svg");
+dojo.require("dojo.gfx.color");
+dojo.require("dojo.gfx.color.hsl");
+dojo.require("dojo.experimental");
+dojo.experimental("dojo.widget.svg.HslColorPicker");
+
+
+dojo.widget.defineWidget(
+	"dojo.widget.svg.HslColorPicker",
+	dojo.widget.HtmlWidget,
+	function(){
+		dojo.debug("warning: the HslColorPicker is not a finished widget, and is not yet ready for general use");
+		this.filterObject = {};
+	},
+{
+	hue: "0",
+	saturation: "0",
+	light: "0",
+	storedColor: "#0054aa",
+
+	//	widget props
+	templatePath: dojo.uri.dojoUri("src/widget/templates/HslColorPicker.svg"),
+	fillInTemplate: function() {
+		this.height = "131px";
+		this.svgDoc = this.hueNode.ownerDocument;
+		this.leftGradientColorNode = this.hueNode.ownerDocument.getElementById("leftGradientColor");
+		this.rightGradientColorNode = this.hueNode.ownerDocument.getElementById("rightGradientColor");
+		this.hueNode.setAttributeNS(dojo.dom.xmlns.xlink, "href", dojo.uri.dojoUri("src/widget/templates/images/hue.png"));
+		var hsl = dojo.gfx.color.hex2hsl(this.storedColor);
+		this.hue = hsl[0];
+		this.saturation = hsl[1];
+		this.light = hsl[2];
+		this.setSaturationStopColors();
+		//this.setHueSlider();
+		//this.setSaturationLightSlider();
+	},
+	setSaturationStopColors: function() {
+		//this.leftGradientStopColor = "rgb(" + dojo.gfx.color.hsl2rgb(this.hue, 20, 50).join(", ") + ")";
+		//this.rightGradientStopColor = "rgb(" + dojo.gfx.color.hsl2rgb(this.hue, 100, 50).join(", ") + ")";
+		//this.leftGradientStopColor = dojo.gfx.color.hsl2hex(this.hue, 20, 50);
+		//this.rightGradientStopColor = dojo.gfx.color.hsl2hex(this.hue, 100, 50);
+		this.leftGradientStopColor = dojo.gfx.color.rgb2hex(this.hsl2rgb(this.hue, 0, 50));
+		this.rightGradientStopColor = dojo.gfx.color.rgb2hex(this.hsl2rgb(this.hue, 100, 50));
+		this.leftGradientColorNode.setAttributeNS(null,'stop-color',this.leftGradientStopColor);
+		this.rightGradientColorNode.setAttributeNS(null,'stop-color',this.rightGradientStopColor);
+	},
+	setHue: function(hue) {
+		this.hue = hue;
+	},
+	setHueSlider: function() {
+		// FIXME: need to add some padding around the picker so you can see the slider at the top and bottom of the picker)
+		this.hueSliderNode.setAttribute("y", parseInt((this.hue/360) * parseInt(this.height) - 2) + "px" );
+	},
+	setSaturationLight: function(saturation, light) {
+		this.saturation = saturation;
+		this.light = light;
+	},
+	setSaturationLightSlider: function() {
+		// TODO
+	},
+	onHueClick: function(evt) {
+		// get the position that was clicked on the element
+		// FIXME: handle document scrolling, offset
+		var yPosition = parseInt(evt.clientY) - parseInt(evt.target.getAttribute("y"));
+		this.setHue( 360 - parseInt(yPosition*(360/parseInt(this.height))) );
+		this.setSaturationStopColors();
+		this.setStoredColor(dojo.gfx.color.hsl2hex(this.hue, this.saturation, this.light));
+	},
+	onHueDrag: function(evt) {
+		// TODO
+	},
+	onSaturationLightClick: function(evt) {
+		// get the position that was clicked on the element
+		// FIXME: handle document scrolling, offset
+		var xPosition = parseInt(evt.clientX) - parseInt(evt.target.getAttribute("y"));
+		var yPosition = parseInt(evt.clientY) - parseInt(evt.target.getAttribute("y"));
+		var saturation = parseInt(parseInt(xPosition)*(101/106));
+		var light = parseInt(parseInt(yPosition)*(101/106));
+		this.setSaturationLight(saturation, light);
+		this.setStoredColor(dojo.gfx.color.hsl2hex(this.hue, this.saturation, this.light));
+	},
+	onSaturationLightDrag: function(evt) {
+		// TODO
+	},
+	getStoredColor: function() {
+		return this.storedColor;
+	},
+	setStoredColor: function(rgbHexColor) {
+		this.storedColor = rgbHexColor;
+		dojo.event.topic.publish("/" + this.widgetId + "/setStoredColor", this.filterObject);
+	},
+	hsl2rgb: function(hue, saturation, light)
+	{
+		// hsl2rgb in dojo.gfx.color did not behave hte way I expected, so 
+		// I'm using some old code I wrote until I figure out what the issue is
+		// first, check to see if saturation = 0
+		function rgb(q1,q2,hue) {
+			if (hue>360) hue=hue-360;
+			if (hue<0) hue=hue+360;
+			if (hue<60) return (q1+(q2-q1)*hue/60);
+			else if (hue<180) return(q2);
+			else if (hue<240) return(q1+(q2-q1)*(240-hue)/60);
+			else return(q1);
+		}
+		this.rgb = rgb
+	
+		if (saturation==0) {
+			return [Math.round(light*255/100), Math.round(light*255/100), Math.round(light*255/100)];
+		} else {
+			light = light/100;
+			saturation = saturation/100;
+			// check to see if light > 0.5
+			if ((light)<0.5) {
+				var temp2 = (light)*(1.0+saturation)
+			} else {
+				var temp2 = (light+saturation-(light*saturation))
+			}
+			var temp1 = 2.0*light - temp2;
+			var rgbcolor = [];
+			rgbcolor[0] = Math.round(rgb(temp1,temp2,parseInt(hue)+120)*255);
+			rgbcolor[1] = Math.round(rgb(temp1,temp2,hue)*255);
+			rgbcolor[2] = Math.round(rgb(temp1,temp2,parseInt(hue)-120)*255);
+			return rgbcolor;
+		}
+	}
+});

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/HtmlWidget.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/HtmlWidget.js?view=auto&rev=451106
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/HtmlWidget.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/HtmlWidget.js Thu Sep 28 20:42:39 2006
@@ -0,0 +1,170 @@
+/*
+	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.HtmlWidget");
+dojo.require("dojo.widget.DomWidget");
+dojo.require("dojo.html.util");
+dojo.require("dojo.html.display");
+dojo.require("dojo.html.layout");
+dojo.require("dojo.lang.extras");
+dojo.require("dojo.lang.func");
+dojo.require("dojo.lfx.toggle");
+
+dojo.declare("dojo.widget.HtmlWidget", dojo.widget.DomWidget, {								 
+	widgetType: "HtmlWidget",
+
+	templateCssPath: null,
+	templatePath: null,
+
+	lang: "",
+	// for displaying/hiding widget
+	toggle: "plain",
+	toggleDuration: 150,
+
+	animationInProgress: false,
+
+	initialize: function(args, frag){
+	},
+
+	postMixInProperties: function(args, frag){
+		if(this.lang === ""){this.lang = null;}
+		// now that we know the setting for toggle, get toggle object
+		// (default to plain toggler if user specified toggler not present)
+		this.toggleObj =
+			dojo.lfx.toggle[this.toggle.toLowerCase()] || dojo.lfx.toggle.plain;
+	},
+
+	getContainerHeight: function(){
+		// NOTE: container height must be returned as the INNER height
+		dojo.unimplemented("dojo.widget.HtmlWidget.getContainerHeight");
+	},
+
+	getContainerWidth: function(){
+		return this.parent.domNode.offsetWidth;
+	},
+
+	setNativeHeight: function(height){
+		var ch = this.getContainerHeight();
+	},
+
+	createNodesFromText: function(txt, wrap){
+		return dojo.html.createNodesFromText(txt, wrap);
+	},
+
+	destroyRendering: function(finalize){
+		try{
+			if(!finalize && this.domNode){
+				dojo.event.browser.clean(this.domNode);
+			}
+			this.domNode.parentNode.removeChild(this.domNode);
+			delete this.domNode;
+		}catch(e){ /* squelch! */ }
+	},
+
+	/////////////////////////////////////////////////////////
+	// Displaying/hiding the widget
+	/////////////////////////////////////////////////////////
+	isShowing: function(){
+		return dojo.html.isShowing(this.domNode);
+	},
+
+	toggleShowing: function(){
+		// dojo.html.toggleShowing(this.domNode);
+		if(this.isHidden){
+			this.show();
+		}else{
+			this.hide();
+		}
+	},
+
+	show: function(){
+		this.animationInProgress=true;
+		this.isHidden = false;
+		this.toggleObj.show(this.domNode, this.toggleDuration, null,
+			dojo.lang.hitch(this, this.onShow), this.explodeSrc);
+	},
+
+	// called after the show() animation has completed
+	onShow: function(){
+		this.animationInProgress=false;
+		this.checkSize();
+	},
+
+	hide: function(){
+		this.animationInProgress = true;
+		this.isHidden = true;
+		this.toggleObj.hide(this.domNode, this.toggleDuration, null,
+			dojo.lang.hitch(this, this.onHide), this.explodeSrc);
+	},
+
+	// called after the hide() animation has completed
+	onHide: function(){
+		this.animationInProgress=false;
+	},
+
+	//////////////////////////////////////////////////////////////////////////////
+	// Sizing related methods
+	//  If the parent changes size then for each child it should call either
+	//   - resizeTo(): size the child explicitly
+	//   - or checkSize(): notify the child the the parent has changed size
+	//////////////////////////////////////////////////////////////////////////////
+
+	// Test if my size has changed.
+	// If width & height are specified then that's my new size; otherwise,
+	// query outerWidth/outerHeight of my domNode
+	_isResized: function(w, h){
+		// If I'm not being displayed then disregard (show() must
+		// check if the size has changed)
+		if(!this.isShowing()){ return false; }
+
+		// If my parent has been resized and I have style="height: 100%"
+		// or something similar then my size has changed too.
+		var wh = dojo.html.getMarginBox(this.domNode);
+		var width=w||wh.width;
+		var height=h||wh.height;
+		if(this.width == width && this.height == height){ return false; }
+
+		this.width=width;
+		this.height=height;
+		return true;
+	},
+
+	// Called when my parent has changed size, but my parent won't call resizeTo().
+	// This is useful if my size is height:100% or something similar.
+	// Also called whenever I am shown, because the first time I am shown I may need
+	// to do size calculations.
+	checkSize: function(){
+		if(!this._isResized()){ return; }
+		this.onResized();
+	},
+
+	// Explicitly set this widget's size (in pixels).
+	resizeTo: function(w, h){
+		dojo.html.setMarginBox(this.domNode, { width: w, height: h });
+		
+		// can't do sizing if widget is hidden because referencing node.offsetWidth/node.offsetHeight returns 0.
+		// do sizing on show() instead.
+		if(this.isShowing()){
+			this.onResized();
+		}
+	},
+
+	resizeSoon: function(){
+		if(this.isShowing()){
+			dojo.lang.setTimeout(this, this.onResized, 0);
+		}
+	},
+
+	// Called when my size has changed.
+	// Must notify children if their size has (possibly) changed
+	onResized: function(){
+		dojo.lang.forEach(this.children, function(child){ if(child.checkSize){child.checkSize();} });
+	}
+});

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/InlineEditBox.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/InlineEditBox.js?view=auto&rev=451106
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/InlineEditBox.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/InlineEditBox.js Thu Sep 28 20:42:39 2006
@@ -0,0 +1,211 @@
+/*
+	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.InlineEditBox");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.event.*");
+dojo.require("dojo.lfx.*");
+dojo.require("dojo.gfx.color");
+dojo.require("dojo.string");
+dojo.require("dojo.html.*");
+dojo.require("dojo.html.layout");
+
+dojo.widget.defineWidget(
+	"dojo.widget.InlineEditBox",
+	dojo.widget.HtmlWidget,
+	function(){
+		// mutable objects need to be in constructor to give each instance its own copy
+		this.history = [];
+	},
+{
+	templatePath: dojo.uri.dojoUri("src/widget/templates/InlineEditBox.html"),
+	templateCssPath: dojo.uri.dojoUri("src/widget/templates/InlineEditBox.css"),
+
+	form: null,
+	editBox: null,
+	edit: null,
+	text: null,
+	textarea: null,
+	submitButton: null,
+	cancelButton: null,
+	mode: "text",
+	name: "",
+	
+	minWidth: 100, //px. minimum width of edit box
+	minHeight: 200, //px. minimum width of edit box, if it's a TA
+
+	editing: false,
+	textValue: "",
+	defaultText: "",
+	doFade: false,
+	
+	onSave: function(newValue, oldValue, name){},
+	onUndo: function(value){},
+
+	postCreate: function(args, frag){
+		// put original node back in the document, and attach handlers
+		// which hide it and display the editor
+		this.editable = this.getFragNodeRef(frag);
+		dojo.html.insertAfter(this.editable, this.form);
+		dojo.event.connect(this.editable, "onmouseover", this, "onMouseOver");
+		dojo.event.connect(this.editable, "onmouseout", this, "onMouseOut");
+		dojo.event.connect(this.editable, "onclick", this, "beginEdit");
+
+		this.textValue = dojo.string.trim(this.editable.innerHTML);
+		if(dojo.string.trim(this.textValue).length == 0){
+			this.editable.innerHTML = this.defaultText;
+		}		
+	},
+	
+	onMouseOver: function(){
+		if(!this.editing){
+			if (!this.isEnabled){
+				dojo.html.addClass(this.editable, "editableRegionDisabled");
+			} else {
+				dojo.html.addClass(this.editable, "editableRegion");
+				if(this.mode == "textarea"){
+					dojo.html.addClass(this.editable, "editableTextareaRegion");
+				}
+			}
+		}
+		
+		this.mouseover();
+	},
+	
+	mouseover: function(e){
+		// TODO: How do we deprecate a function without going into overkill with debug statements?
+		// dojo.deprecated("onMouseOver should be used instead of mouseover to listen for mouse events");
+	},
+	
+	onMouseOut: function(){
+		if(!this.editing){
+			dojo.html.removeClass(this.editable, "editableRegion");
+			dojo.html.removeClass(this.editable, "editableTextareaRegion");
+			dojo.html.removeClass(this.editable, "editableRegionDisabled");
+		}
+		
+		this.mouseout();
+	},
+	
+	mouseout: function(e){
+		// dojo.deprecated("onMouseOut should be used instead of mouseout to listen for mouse events");
+	},
+
+	// When user clicks the text, then start editing.
+	// Hide the text and display the form instead.
+	beginEdit: function(e){
+		if(this.editing || !this.isEnabled){ return; }
+		this.mouseout();
+		this.editing = true;
+
+		// setup the form's <input> or <textarea> field, as specified by mode
+		var ee = this[this.mode.toLowerCase()];
+		ee.value = dojo.string.trim(this.textValue);
+		ee.style.fontSize = dojo.html.getStyle(this.editable, "font-size");
+		ee.style.fontWeight = dojo.html.getStyle(this.editable, "font-weight");
+		ee.style.fontStyle = dojo.html.getStyle(this.editable, "font-style");
+		var bb = dojo.html.getBorderBox(this.editable);
+		ee.style.width = Math.max(bb.width, this.minWidth) + "px";
+		if(this.mode.toLowerCase()=="textarea"){
+			ee.style.display = "block";
+			ee.style.height = Math.max(bb.height, this.minHeight) + "px";
+		} else {
+			ee.style.display = "";
+		}
+
+		// show the edit form and hide the read only version of the text
+		this.form.style.display = "";
+		this.editable.style.display = "none";
+
+		ee.focus();
+		ee.select();
+		this.submitButton.disabled = true;
+	},
+
+	saveEdit: function(e){
+		e.preventDefault();
+		e.stopPropagation();
+		var ee = this[this.mode.toLowerCase()];
+		if((this.textValue != ee.value)&&
+			(dojo.string.trim(ee.value) != "")){
+			this.doFade = true;
+			this.history.push(this.textValue);
+			this.onSave(ee.value, this.textValue, this.name);
+			this.textValue = ee.value;
+			this.editable.innerHTML = "";
+			var textNode = document.createTextNode( this.textValue );
+			this.editable.appendChild( textNode );
+		}else{
+			this.doFade = false;
+		}
+		this.finishEdit(e);
+	},
+
+	cancelEdit: function(e){
+		if(!this.editing){ return false; }
+		this.editing = false;
+		this.form.style.display="none";
+		this.editable.style.display = "";
+		return true;
+	},
+
+	finishEdit: function(e){
+		if(!this.cancelEdit(e)){ return; }
+		if(this.doFade) {
+			dojo.lfx.highlight(this.editable, dojo.gfx.color.hex2rgb("#ffc"), 700).play(300);
+		}
+		this.doFade = false;
+	},
+	
+	setText: function(txt){
+		// sets the text without informing the server
+		var tt = dojo.string.trim(txt);
+		this.textValue = tt
+		this.editable.innerHTML = tt;
+	},
+
+	undo: function(){
+		if(this.history.length > 0){
+			var curValue = this.textValue;
+			var value = this.history.pop();
+			this.editable.innerHTML = value;
+			this.textValue = value;
+			this.onUndo(value);
+			this.onSave(value, curValue, this.name);
+		}
+	},
+
+	checkForValueChange: function(){
+		var ee = this[this.mode.toLowerCase()];
+		if((this.textValue != ee.value)&&
+			(dojo.string.trim(ee.value) != "")){
+			this.submitButton.disabled = false;
+		}
+	},
+	
+	disable: function(){
+		this.submitButton.disabled = true;
+		this.cancelButton.disabled = true;
+		var ee = this[this.mode.toLowerCase()];
+		ee.disabled = true;
+		
+		dojo.widget.Widget.prototype.disable.call(this);
+	},
+	
+	enable: function(){
+		this.checkForValueChange();
+		this.cancelButton.disabled = false;
+		var ee = this[this.mode.toLowerCase()];
+		ee.disabled = false;
+		
+		dojo.widget.Widget.prototype.enable.call(this);
+	}
+});

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/LayoutContainer.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/LayoutContainer.js?view=auto&rev=451106
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/LayoutContainer.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/LayoutContainer.js Thu Sep 28 20:42:39 2006
@@ -0,0 +1,63 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+//
+// this widget provides Delphi-style panel layout semantics
+//
+
+dojo.provide("dojo.widget.LayoutContainer");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.html.layout");
+
+dojo.widget.defineWidget(
+	"dojo.widget.LayoutContainer",
+	dojo.widget.HtmlWidget,
+{
+	isContainer: true,
+
+	layoutChildPriority: 'top-bottom',
+
+	postCreate: function(){
+		dojo.widget.html.layout(this.domNode, this.children, this.layoutChildPriority);
+	},
+
+	addChild: function(child, overrideContainerNode, pos, ref, insertIndex){
+		dojo.widget.LayoutContainer.superclass.addChild.call(this, child, overrideContainerNode, pos, ref, insertIndex);
+		dojo.widget.html.layout(this.domNode, this.children, this.layoutChildPriority);
+	},
+
+	removeChild: function(pane){
+		dojo.widget.LayoutContainer.superclass.removeChild.call(this,pane);
+		dojo.widget.html.layout(this.domNode, this.children, this.layoutChildPriority);
+	},
+
+	onResized: function(){
+		dojo.widget.html.layout(this.domNode, this.children, this.layoutChildPriority);
+	},
+
+	show: function(){
+		// If this node was created while display=="none" then it
+		// hasn't been laid out yet.  Do that now.
+		this.domNode.style.display="";
+		this.checkSize();
+		this.domNode.style.display="none";
+		this.domNode.style.visibility="";
+
+		dojo.widget.LayoutContainer.superclass.show.call(this);
+	}
+});
+
+// This argument can be specified for the children of a LayoutContainer.
+// Since any widget can be specified as a LayoutContainer child, mix it
+// into the base widget class.  (This is a hack, but it's effective.)
+dojo.lang.extend(dojo.widget.Widget, {
+	layoutAlign: 'none'
+});

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/LinkPane.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/LinkPane.js?view=auto&rev=451106
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/LinkPane.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/LinkPane.js Thu Sep 28 20:42:39 2006
@@ -0,0 +1,41 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+//
+// a div that loads from a URL.  (Similar to an iframe, but
+// it's in the same environment as the main window)
+//
+
+dojo.provide("dojo.widget.LinkPane");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.ContentPane");
+dojo.require("dojo.html.style");
+
+dojo.widget.defineWidget(
+	"dojo.widget.LinkPane",
+	dojo.widget.ContentPane,
+{
+	// 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);
+	}
+});

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

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Manager.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Manager.js?view=auto&rev=451106
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Manager.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Manager.js Thu Sep 28 20:42:39 2006
@@ -0,0 +1,359 @@
+/*
+	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.Manager");
+dojo.require("dojo.lang.array");
+dojo.require("dojo.lang.func");
+dojo.require("dojo.event.*");
+
+// Manager class
+dojo.widget.manager = new function(){
+	this.widgets = [];
+	this.widgetIds = [];
+	
+	// map of widgetId-->widget for widgets without parents (top level widgets)
+	this.topWidgets = {};
+
+	var widgetTypeCtr = {};
+	var renderPrefixCache = [];
+
+	this.getUniqueId = function (widgetType) {
+		return widgetType + "_" + (widgetTypeCtr[widgetType] != undefined ?
+			++widgetTypeCtr[widgetType] : widgetTypeCtr[widgetType] = 0);
+	}
+
+	this.add = function(widget){
+		//dojo.profile.start("dojo.widget.manager.add");
+		this.widgets.push(widget);
+		// Opera9 uses ID (caps)
+		if(!widget.extraArgs["id"]){
+			widget.extraArgs["id"] = widget.extraArgs["ID"];
+		}
+		// FIXME: the rest of this method is very slow!
+		if(widget.widgetId == ""){
+			if(widget["id"]){
+				widget.widgetId = widget["id"];
+			}else if(widget.extraArgs["id"]){
+				widget.widgetId = widget.extraArgs["id"];
+			}else{
+				widget.widgetId = this.getUniqueId(widget.widgetType);
+			}
+		}
+		if(this.widgetIds[widget.widgetId]){
+			dojo.debug("widget ID collision on ID: "+widget.widgetId);
+		}
+		this.widgetIds[widget.widgetId] = widget;
+		// Widget.destroy already calls removeById(), so we don't need to
+		// connect() it here
+		//dojo.profile.end("dojo.widget.manager.add");
+	}
+
+	this.destroyAll = function(){
+		for(var x=this.widgets.length-1; x>=0; x--){
+			try{
+				// this.widgets[x].destroyChildren();
+				this.widgets[x].destroy(true);
+				delete this.widgets[x];
+			}catch(e){ }
+		}
+	}
+
+	// FIXME: we should never allow removal of the root widget until all others
+	// are removed!
+	this.remove = function(widgetIndex){
+		if(dojo.lang.isNumber(widgetIndex)){
+			var tw = this.widgets[widgetIndex].widgetId;
+			delete this.widgetIds[tw];
+			this.widgets.splice(widgetIndex, 1);
+		}else{
+			this.removeById(widgetIndex);
+		}
+	}
+	
+	// FIXME: suboptimal performance
+	this.removeById = function(id) {
+		if(!dojo.lang.isString(id)){
+			id = id["widgetId"];
+			if(!id){ dojo.debug("invalid widget or id passed to removeById"); return; }
+		}
+		for (var i=0; i<this.widgets.length; i++){
+			if(this.widgets[i].widgetId == id){
+				this.remove(i);
+				break;
+			}
+		}
+	}
+
+	this.getWidgetById = function(id){
+		if(dojo.lang.isString(id)){
+			return this.widgetIds[id];
+		}
+		return id;
+	}
+
+	this.getWidgetsByType = function(type){
+		var lt = type.toLowerCase();
+		var getType = (type.indexOf(":") < 0 ? 
+			function(x) { return x.widgetType.toLowerCase(); } :
+			function(x) { return x.getNamespacedType(); }
+		);
+		var ret = [];
+		dojo.lang.forEach(this.widgets, function(x){
+			if(getType(x) == lt){ret.push(x);}
+		});
+		return ret;
+	}
+
+	this.getWidgetsByFilter = function(unaryFunc, onlyOne){
+		var ret = [];
+		dojo.lang.every(this.widgets, function(x){
+			if(unaryFunc(x)){
+				ret.push(x);
+				if(onlyOne){return false;}
+			}
+			return true;
+		});
+		return (onlyOne ? ret[0] : ret);
+	}
+
+	this.getAllWidgets = function() {
+		return this.widgets.concat();
+	}
+
+	//	added, trt 2006-01-20
+	this.getWidgetByNode = function(/* DOMNode */ node){
+		var w=this.getAllWidgets();
+		node = dojo.byId(node);
+		for(var i=0; i<w.length; i++){
+			if(w[i].domNode==node){
+				return w[i];
+			}
+		}
+		return null;
+	}
+
+	// shortcuts, baby
+	this.byId = this.getWidgetById;
+	this.byType = this.getWidgetsByType;
+	this.byFilter = this.getWidgetsByFilter;
+	this.byNode = this.getWidgetByNode;
+
+	// map of previousally discovered implementation names to constructors
+	var knownWidgetImplementations = {};
+
+	// support manually registered widget packages
+	var widgetPackages = ["dojo.widget"];
+	for (var i=0; i<widgetPackages.length; i++) {
+		// convenience for checking if a package exists (reverse lookup)
+		widgetPackages[widgetPackages[i]] = true;
+	}
+
+	this.registerWidgetPackage = function(pname) {
+		if(!widgetPackages[pname]){
+			widgetPackages[pname] = true;
+			widgetPackages.push(pname);
+		}
+	}
+	
+	this.getWidgetPackageList = function() {
+		return dojo.lang.map(widgetPackages, function(elt) { return(elt!==true ? elt : undefined); });
+	}
+	
+	this.getImplementation = function(widgetName, ctorObject, mixins, ns){
+		// try and find a name for the widget
+		var impl = this.getImplementationName(widgetName, ns);
+		if(impl){ 
+			// var tic = new Date();
+			var ret = ctorObject ? new impl(ctorObject) : new impl();
+			// dojo.debug(new Date() - tic);
+			return ret;
+		}
+	}
+
+	function buildPrefixCache() {
+		for(var renderer in dojo.render){
+			if(dojo.render[renderer]["capable"] === true){
+				var prefixes = dojo.render[renderer].prefixes;
+				for(var i=0; i<prefixes.length; i++){
+					renderPrefixCache.push(prefixes[i].toLowerCase());
+				}
+			}
+		}
+		// make sure we don't HAVE to prefix widget implementation names
+		// with anything to get them to render
+		//renderPrefixCache.push("");
+		// empty prefix is included automatically
+	}
+	
+	var findImplementationInModule = function(lowerCaseWidgetName, module){
+		if(!module){return null;}
+		for(var i=0, l=renderPrefixCache.length, widgetModule; i<=l; i++){
+			widgetModule = (i<l ? module[renderPrefixCache[i]] : module);
+			if(!widgetModule){continue;}
+			for(var name in widgetModule){
+				if(name.toLowerCase() == lowerCaseWidgetName){
+					return widgetModule[name];
+				}
+			}
+		}
+		return null;
+	}
+
+	var findImplementation = function(lowerCaseWidgetName, moduleName){
+		// locate registered widget module
+		var module = dojo.evalObjPath(moduleName, false);
+		// locate a widget implementation in the registered module for our current rendering environment
+		return (module ? findImplementationInModule(lowerCaseWidgetName, module) : null);
+	}
+
+	this.getImplementationName = function(widgetName, ns){
+		/*
+		 * Locate an implementation (constructor) for 'widgetName' in namespace 'ns' 
+		 * widgetNames are case INSENSITIVE
+		 * 
+		 * 1. Return value from implementation cache, if available, for quick turnaround.
+		 * 2. Locate a namespace registration for 'ns'
+		 * 3. If no namespace found, register the conventional one (ns.widget)
+		 * 4. Allow the namespace resolver (if any) to load a module for this widget.
+		 * 5. Permute the widget name and capable rendering prefixes to locate, cache, and return 
+		 *    an appropriate widget implementation.
+		 * 6. If no implementation is found, attempt to load the namespace manifest,
+		 *    and then look again for an implementation to cache and return.
+		 * 7. Use the deprecated widgetPackages registration system to attempt to locate the widget
+		 * 8. Fail
+		 */
+		var lowerCaseWidgetName = widgetName.toLowerCase();
+
+		// default to dojo namespace
+		ns=ns||"dojo";
+		// use cache if available
+		var imps = knownWidgetImplementations[ns] || (knownWidgetImplementations[ns]={});
+		//if(!knownWidgetImplementations[ns]){knownWidgetImplementations[ns]={};}
+		var impl = imps[lowerCaseWidgetName];
+		if(impl){
+			return impl;
+		}
+		
+		// (one time) store a list of the render prefixes we are capable of rendering
+		if(!renderPrefixCache.length){
+			buildPrefixCache();
+		}
+
+		// lookup namespace
+		var nsObj = dojo["namespace"].get(ns);
+		if(!nsObj){
+			// default to <ns>.widget by convention
+			dojo.namespace.register(ns, ns + '.widget');
+			nsObj = dojo["namespace"].get(ns);
+		}
+		
+		// allow the namespace to resolve the widget module
+		if(nsObj){nsObj.resolve(widgetName);}
+
+		// locate a widget implementation in the registered module for our current rendering environment
+		impl = findImplementation(lowerCaseWidgetName, nsObj.getModule(widgetName));
+		if(impl){return(imps[lowerCaseWidgetName] = impl)};
+
+		// try to load a manifest to resolve this implemenation
+		nsObj = dojo["namespace"].require(ns);
+		if((nsObj)&&(nsObj.resolver)){
+			nsObj.resolve(widgetName);
+			impl = findImplementation(lowerCaseWidgetName, nsObj.getModule(widgetName));
+			if(impl){return(imps[lowerCaseWidgetName] = impl)};
+		}
+	
+		// this is an error condition under new rules
+		dojo.deprecated('dojo.widget.Manager.getImplementationName', 
+			'Could not locate widget implementation for "' + widgetName + '" in "' + nsObj.module + '" registered to namespace "' + nsObj.name + '". '										
+			+ "Developers must specify correct namespaces for all non-Dojo widgets", "0.5");
+
+		// backward compat: if the user has not specified any namespace and their widget is not in dojo.widget.*
+		// search registered widget packages [sic]
+		// note: registerWidgetPackage itself is now deprecated 
+		for(var i=0; i<widgetPackages.length; i++){
+			impl = findImplementation(lowerCaseWidgetName, widgetPackages[i]);
+			if(impl){return(imps[lowerCaseWidgetName] = impl)};
+		}
+		
+		throw new Error('Could not locate widget implementation for "' + widgetName + '" in "' + nsObj.module + '" registered to namespace "' + nsObj.name + '"');
+	}
+
+	// FIXME: does it even belong in this module?
+	// NOTE: this method is implemented by DomWidget.js since not all
+	// hostenv's would have an implementation.
+	/*this.getWidgetFromPrimitive = function(baseRenderType){
+		dojo.unimplemented("dojo.widget.manager.getWidgetFromPrimitive");
+	}
+
+	this.getWidgetFromEvent = function(nativeEvt){
+		dojo.unimplemented("dojo.widget.manager.getWidgetFromEvent");
+	}*/
+
+	// Catch window resize events and notify top level widgets
+	this.resizing=false;
+	this.onWindowResized = function(){
+		if(this.resizing){
+			return;	// duplicate event
+		}
+		try{
+			this.resizing=true;
+			for(var id in this.topWidgets){
+				var child = this.topWidgets[id];
+				if(child.checkSize ){
+					child.checkSize();
+				}
+			}
+		}catch(e){
+		}finally{
+			this.resizing=false;
+		}
+	}
+	if(typeof window != "undefined") {
+		dojo.addOnLoad(this, 'onWindowResized');							// initial sizing
+		dojo.event.connect(window, 'onresize', this, 'onWindowResized');	// window resize
+	}
+
+	// FIXME: what else?
+};
+
+(function(){
+	var dw = dojo.widget;
+	var dwm = dw.manager;
+	var h = dojo.lang.curry(dojo.lang, "hitch", dwm);
+	var g = function(oldName, newName){
+		dw[(newName||oldName)] = h(oldName);
+	}
+	// copy the methods from the default manager (this) to the widget namespace
+	g("add", "addWidget");
+	g("destroyAll", "destroyAllWidgets");
+	g("remove", "removeWidget");
+	g("removeById", "removeWidgetById");
+	g("getWidgetById");
+	g("getWidgetById", "byId");
+	g("getWidgetsByType");
+	g("getWidgetsByFilter");
+	g("getWidgetsByType", "byType");
+	g("getWidgetsByFilter", "byFilter");
+	g("getWidgetByNode", "byNode");
+	dw.all = function(n){
+		var widgets = dwm.getAllWidgets.apply(dwm, arguments);
+		if(arguments.length > 0) {
+			return widgets[n];
+		}
+		return widgets;
+	}
+	g("registerWidgetPackage");
+	g("getImplementation", "getWidgetImplementation");
+	g("getImplementationName", "getWidgetImplementationName");
+
+	dw.widgets = dwm.widgets;
+	dw.widgetIds = dwm.widgetIds;
+	dw.root = dwm.root;
+})();

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