incubator-xap-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mtu...@apache.org
Subject svn commit: r518313 [31/43] - in /incubator/xap/trunk/codebase/src/dojo: ./ src/ src/animation/ src/cal/ src/charting/ src/charting/svg/ src/charting/vml/ src/collections/ src/crypto/ src/data/ src/data/core/ src/data/old/ src/data/old/format/ src/data...
Date Wed, 14 Mar 2007 20:37:27 GMT
Added: incubator/xap/trunk/codebase/src/dojo/src/widget/FloatingPane.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/dojo/src/widget/FloatingPane.js?view=auto&rev=518313
==============================================================================
--- incubator/xap/trunk/codebase/src/dojo/src/widget/FloatingPane.js (added)
+++ incubator/xap/trunk/codebase/src/dojo/src/widget/FloatingPane.js Wed Mar 14 13:36:44 2007
@@ -0,0 +1,453 @@
+/*
+	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");
+
+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.widget.Dialog");		// for ModalFloatingPane
+dojo.require("dojo.widget.ResizeHandle");
+
+dojo.declare(
+	"dojo.widget.FloatingPaneBase",
+	null,
+	{
+		// summary
+		//	Base class for FloatingPane, ModalFloatingPane
+
+		// title: String
+		//	text to display in floating pane's title bar (ex: "My Window")
+		title: '',
+
+		// iconSrc: String
+		//	path of icon to display in floating pane's title bar
+		iconSrc: '',
+
+		// hasShadow: Boolean
+		//	if true, display a shadow behind the floating pane
+		hasShadow: false,
+
+		// constrainToContainer: Boolean
+		//	if true, and the floating pane is inside another container (ContentPane, another FloatingPane, etc.),
+		//	then don't allow the floating pane to be dragged outside of it's container
+		constrainToContainer: false,
+
+		// taskBarId: String
+		//	widget id of TaskBar widget;
+		//	if specified, then an icon for this FloatingPane will be added to the specified TaskBar
+		taskBarId: "",
+
+		// resizable: Boolean
+		//	if true, allow user to resize floating pane
+		resizable: true,
+
+		// titleBarDisplay: Boolean
+		//	if true, display title bar for this floating pane
+		titleBarDisplay: true,
+
+		// windowState: String
+		//	controls whether window is initially not displayed ("minimized"), displayed full screen ("maximized"),
+		//	or just displayed normally ("normal").
+		// Values
+		//	"normal", "maximized", "minimized"
+		windowState: "normal",
+
+		// displayCloseAction: Boolean
+		//	display button to close window
+		displayCloseAction: false,
+
+		// displayMinimizeAction: Boolean
+		//	display button to minimize window (ie, window disappears so only the taskbar item remains)
+		displayMinimizeAction: false,
+
+		// displayMaximizeAction: Boolean
+		//	display button to maximize window (ie, to take up the full screen)
+		displayMaximizeAction: false,
+
+		// Related to connecting to taskbar
+		// TODO: use topics rather than repeated connect attempts?
+		_max_taskBarConnectAttempts: 5,
+		_taskBarConnectAttempts: 0,
+
+		templatePath: dojo.uri.dojoUri("src/widget/templates/FloatingPane.html"),
+		templateCssPath: dojo.uri.dojoUri("src/widget/templates/FloatingPane.css"),
+
+		fillInFloatingPaneTemplate: function(args, frag){
+			// summary: this should be called by fillInTemplate() of the widget that I'm mixed into
+
+			// 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){
+				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(/*Event*/ evt) {
+			// summary: maximize the window
+			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(/*Event*/ evt) {
+			// summary: hide the window so that only the icon in the taskbar is shown
+			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(/*Event*/ evt) {
+			// summary: set the winow to normal size (neither maximized nor minimized)
+			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(){
+			// summary: switch between hidden mode and displayed mode (either maximized or normal, depending on state before window was minimized)
+			if(this.windowState=="minimized"){
+				this.restoreWindow();
+			}else{
+				this.minimizeWindow();
+			}
+		},
+
+		closeWindow: function(/*Event*/ evt) {
+			// summary: destroy this window
+			dojo.html.removeNode(this.domNode);
+			this.destroy();
+		},
+
+		onMouseDown: function(/*Event*/ evt) {
+			// summary: callback when user clicks anywhere on the floating pane
+			this.bringToTop();
+		},
+
+		bringToTop: function() {
+			// summary
+			//	all the floating panes are stacked in z-index order; bring this floating pane to the top of that stack,
+			//	so that it's displayed in front of all the other floating panes
+			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";
+		},
+
+		_taskBarSetup: function() {
+			// summary: add icon to task bar, connected to me
+			var taskbar = dojo.widget.getWidgetById(this.taskBarId);
+			if (!taskbar){
+				if (this._taskBarConnectAttempts <  this._max_taskBarConnectAttempts) {
+					dojo.lang.setTimeout(this, this._taskBarSetup, 50);
+					this._taskBarConnectAttempts++;
+				} else {
+					dojo.debug("Unable to connect to the taskBar");
+				}
+				return;
+			}
+			taskbar.addChild(this);
+		},
+
+		showFloatingPane: function(){
+			// summary:
+			//	bring this floating pane to the top
+			this.bringToTop();
+		},
+
+		onFloatingPaneShow: function(){
+			// summary: callback for when someone calls FloatingPane.show
+			var mb = dojo.html.getMarginBox(this.domNode);
+			this.resizeTo(mb.width, mb.height);
+		},
+
+		// summary: set the floating pane to the given size
+		resizeTo: function(/*Integer*/ width, /*Integer*/ height){
+			dojo.html.setMarginBox(this.domNode, { width: width, height: height });
+
+			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(width, height); }
+			this.onResized();
+		},
+
+		checkSize: function() {
+			// summary
+			//	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.
+		},
+		destroyFloatingPane: function() {
+			if(this.resizeHandle){
+				this.resizeHandle.destroy();
+				this.resizeHandle = null;
+			}
+		}
+	}
+);
+
+dojo.widget.defineWidget(
+	"dojo.widget.FloatingPane",
+	[dojo.widget.ContentPane, dojo.widget.FloatingPaneBase],
+{
+	// summary
+	//	A non-modal floating window.
+	//	Attaches to a Taskbar which has an icon for each window.
+	//	Must specify size (like style="width: 500px; height: 500px;"),
+
+	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();
+	},
+	destroy: function(){
+		this.destroyFloatingPane();
+		dojo.widget.FloatingPane.superclass.destroy.apply(this, arguments);
+	}
+});
+
+
+dojo.widget.defineWidget(
+	"dojo.widget.ModalFloatingPane",
+	[dojo.widget.FloatingPane, dojo.widget.ModalDialogBase],
+	{
+		// summary
+		//	A modal floating window.
+		//	This widget is similar to the Dialog widget, but the window, unlike the Dialog, can be moved.
+		//	Must specify size (like style="width: 500px; height: 500px;"),
+
+		windowState: "minimized",
+		displayCloseAction: true,
+		postCreate: function(){
+			dojo.widget.ModalDialogBase.prototype.postCreate.call(this);
+			dojo.widget.ModalFloatingPane.superclass.postCreate.call(this);
+		},
+		show: function(){
+			this.showModalDialog();
+			dojo.widget.ModalFloatingPane.superclass.show.apply(this, arguments);
+			//place the background div under this modal pane
+			this.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);
+		}
+	}
+);

Added: incubator/xap/trunk/codebase/src/dojo/src/widget/Form.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/dojo/src/widget/Form.js?view=auto&rev=518313
==============================================================================
--- incubator/xap/trunk/codebase/src/dojo/src/widget/Form.js (added)
+++ incubator/xap/trunk/codebase/src/dojo/src/widget/Form.js Wed Mar 14 13:36:44 2007
@@ -0,0 +1,313 @@
+/*
+	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.Form");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlWidget");
+
+dojo.widget.defineWidget("dojo.widget.Form", dojo.widget.HtmlWidget,
+	{
+		/*
+		summary: 
+			Widget for easily moving data to/from form
+		
+			description:
+				gets and sets data to and from js-object. With
+				this it's easy to create forms to application.
+				Just create empty form, then set it's values
+				with this and after user pushes submit,
+				getValues and send them as json-notation to
+				server.
+
+				Note: not all Form widgets are supported ATM
+					
+			usage: 
+				<form dojoType="Form" id="myForm">
+					Name: <input type="text" name="name" />
+				</form>
+				myObj={name: "John Doe"};
+				dojo.widget.byId('myForm').setValues(myObj);
+
+				myObj=dojo.widget.byId('myForm').getValues();
+
+		*/
+
+		isContainer: true,
+   		templateString: "<form dojoAttachPoint='containerNode' dojoAttachEvent='onSubmit:onSubmit'></form>",
+		formElements: [],
+		// ignoreNullValue:
+		//	if true, then only fields that has data is set to form
+		// 	if false, fields that does not have corresponding object, is set to empty
+		ignoreNullValues: false,
+
+		postCreate: function(args,frag){
+			for (var key in args) {
+				if (key == "dojotype") continue;
+				var attr= document.createAttribute(key);
+      				attr.nodeValue=args[key];
+      				this.containerNode.setAttributeNode(attr);
+    			}
+  		},
+		_createRepeaters: function (/*object*/obj, /*widget*/widget) {
+			for(var i=0; i<widget.children.length; ++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=new Array();
+					}
+					var rowCount = widget.children[i].getRowCount();
+					for (var j=0,len=rowCount; j<len; ++j) {
+						widget.children[i].deleteRow(0);
+					}
+					for (var j=0; j<myObj.length; j++) {
+    					 	widget.children[i].addRow(false);
+					}
+				}
+				if (widget.children[i].isContainer) {
+					this._createRepeaters(obj, widget.children[i]);
+				}
+			}
+		},
+ 
+		_createFormElements: function() {
+   			if(dojo.render.html.safari) {
+				// bug in safari (not registering form-elements)
+				this.formElements=[];
+				var elems = ["INPUT", "SELECT", "TEXTAREA"];
+				for (var k=0; k < elems.length; k++) {
+					var list = this.containerNode.getElementsByTagName(elems[k]);
+					for (var j=0,len2=list.length; j<len2; j++) {
+						this.formElements.push(list[j]);
+					}
+				}
+				// fixed in safari nightly
+			} else {
+				this.formElements=this.containerNode.elements;
+			}
+		},
+		onSubmit: function(/*event*/e) {
+    			e.preventDefault();
+  		},
+
+		submit: function() {
+			this.containerNode.submit();
+		},
+
+		_getFormElement: function(/*form elements name*/name) {
+			if(dojo.render.html.ie) {
+				for(var i=0, len=this.formElements.length; i<len; i++) {
+					var element = this.formElements[i];
+					if (element.name == name) {
+						return element;
+					} // if
+				} // for
+			} else {
+				var elem = this.formElements[name];
+				if (typeof(elem) != "undefined") {
+					return elem;
+				}
+			}
+			return null;
+		},
+
+		_getObject: function(/*object*/obj, /*string*/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 (/*object*/obj,/*widget*/widget) {
+			for(var i=0, len=widget.children.length; i<len; ++i) {
+				var currentWidget=widget.children[i];
+				if (currentWidget.widgetType == "Repeater") {
+        				for(var j=0,len=currentWidget.getRowCount(); j<len; ++j) {
+          					currentWidget._initRow(j);
+        				}
+				}
+
+				if (currentWidget.isContainer) {
+					this._setToContainers (obj, currentWidget);
+					continue;
+				}
+
+				switch(currentWidget.widgetType) {
+					case "Checkbox":
+						currentWidget.setValue(currentWidget.inputNode.checked);
+						break;
+					case "DropdownDatePicker":
+						currentWidget.setValue(currentWidget.getValue());
+						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(/*object*/obj) {
+			this._createFormElements();
+    			this._createRepeaters(obj,this);
+			for(var i=0, len=this.formElements.length; i<len; i++) {
+				var element = this.formElements[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=myObj[p];
+				}
+
+				if (typeof(myObj) == "undefined") {
+					continue;
+				}
+				if (typeof(myObj[name]) == "undefined" && this.ignoreNullValues) {
+					continue;
+				}
+				var type=element.type;
+				if (type == "hidden" || type == "text" || type == "textarea" || type == "password") {
+					type = "text";
+				}
+				switch(type) {
+					case "checkbox":
+						element.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":
+						element.checked=false;
+						if (typeof(myObj[name]) == 'undefined') {continue};
+						if (myObj[name] == element.value) {
+							element.checked=true;
+						}
+						break;
+					case "select-multiple":
+						element.selectedIndex=-1;
+						for (var j=0,len2=element.options.length; j<len2; ++j) {
+							for (var k=0,len3=myObj[name].length;k<len3;++k) {
+								if (element.options[j].value == myObj[name][k]) {
+									element.options[j].selected=true;
+								}
+							}
+						}
+						break;
+					case "select-one":
+						element.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]) != 'undefined') {
+							value = myObj[name];
+						}
+						element.value=value;
+						break;
+					default:
+						dojo.debug("Not supported type ("+type+")");
+						break;
+				}
+      			}
+			this._setToContainers(obj,this);
+		},
+		getValues: function() {
+			this._createFormElements();
+			var obj = { };
+
+			for(var i=0,len=this.formElements.length; i<len; i++) {
+				// FIXME: would be better to give it an attachPoint:
+				var elm = this.formElements[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 != "select-multiple" && 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);
+				} else if (elm.type == "select-multiple") {
+					if(typeof(myObj[name]) == 'undefined') {
+						myObj[name]=[ ];
+					}
+					for (var jdx=0,len3=elm.options.length; jdx<len3; ++jdx) {
+						if (elm.options[jdx].selected) {
+							myObj[name].push(elm.options[jdx].value);
+						}
+					}
+				} // if
+				name=undefined;
+			} // for
+		return obj;
+	}
+});

Added: incubator/xap/trunk/codebase/src/dojo/src/widget/GoogleMap.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/dojo/src/widget/GoogleMap.js?view=auto&rev=518313
==============================================================================
--- incubator/xap/trunk/codebase/src/dojo/src/widget/GoogleMap.js (added)
+++ incubator/xap/trunk/codebase/src/dojo/src/widget/GoogleMap.js Wed Mar 14 13:36:44 2007
@@ -0,0 +1,243 @@
+/*
+	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(){
+		// summary: A widget that wraps the Google Map API.
+		// description:
+		//		Implements and wraps the Google Map API so that you can easily create
+		//		and include Google Maps in your Dojo application.  Will parse an included
+		//		table for point information, but also exposes the underlying map via the
+		//		map property.
+		// map: GMap2
+		//		The actual Google Map object.
+		// geocoder: GClientGeocoder
+		//		A reference to the Google Geocoder object, for getting points for addresses.
+		// data: Object[]
+		//		Array of generated points plotted on the map
+		// datasrc: String
+		//		Reference to external (to the widget) source for points to plot on the map.
+		// controls: String[]
+		//		List of controls to plot on the map; shortened names correspond to Google Controls.
+		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(){
+		//	summary
+		//	Set any controls on the map in question.
+		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(/* GLatLngBounds */bounds){
+		//	summary
+		//	Returns the center point given the Bounds object.
+		if(this.data.length==1){
+			return (new GLatLng(this.data[0].lat, this.data[0].lng));	//	GLatLng
+		}
+		var clat=(bounds.getNorthEast().lat()+bounds.getSouthWest().lat())/2;
+		var clng=(bounds.getNorthEast().lng()+bounds.getSouthWest().lng())/2;
+		return (new GLatLng(clat,clng));	//	GLatLng
+	},
+
+	createPinpoint:function(/* GLatLng */pt, /* string? */overlay){
+		//	summary
+		//	Creates a marker at the given point, with an optional overlay HTML string.
+		var m=new GMarker(pt);
+		if(overlay){
+			GEvent.addListener(m,"click",function(){
+				m.openInfoWindowHtml("<div>"+overlay+"</div>");
+			});
+		}
+		return m;	//	GMarker
+	},
+	plot:function(/* object */obj){
+		//	summary
+		//	Plots a point at given lat/lng coordinate
+		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(/* string */address){
+		//	summary
+		//	Calls the Google Geocoder to get a lat/lng coordinate at string 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(/* HTMLTable */table){
+		//	summary
+		//	Parses the passed table for data to plot on this map.
+		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(){
+		//	summary
+		//	Plots all acutal points in the current data array.
+		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(/* object */args, /* object */frag){
+		//	summary
+		//	initializes the widget
+		if(this.datasrc){
+			this.parse(dojo.byId(this.datasrc));
+		}
+		else if(this.domNode.getElementsByTagName("table")[0]){
+			this.parse(this.domNode.getElementsByTagName("table")[0]);
+		}
+	},
+	postCreate:function(){
+		//	summary
+		//	Sets up and renders the widget.
+
+		//	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();
+	}
+});

Added: incubator/xap/trunk/codebase/src/dojo/src/widget/HtmlWidget.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/dojo/src/widget/HtmlWidget.js?view=auto&rev=518313
==============================================================================
--- incubator/xap/trunk/codebase/src/dojo/src/widget/HtmlWidget.js (added)
+++ incubator/xap/trunk/codebase/src/dojo/src/widget/HtmlWidget.js Wed Mar 14 13:36:44 2007
@@ -0,0 +1,192 @@
+/*
+	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, {								 
+	// summary
+	//	Base class for all browser based widgets, or at least "html" widgets.
+	//	The meaning of "html" has become unclear; in practice, all widgets derive from this class.
+	
+	// templateCssPath: String
+	//	Path to CSS file for this widget
+	templateCssPath: null,
+	
+	// templatePath: String
+	//	Path to template (HTML file) for this widget
+	templatePath: null,
+
+	// lang: String
+	//	Language to display this widget in (like en-us).
+	//	Defaults to brower's specified preferred language (typically the language of the OS)
+	lang: "",
+
+	// toggle: String
+	//	Controls animation effect for when show() and hide() (or toggle()) are called.
+	//	Possible values: "plain", "wipe", "fade", "explode"
+	toggle: "plain",
+
+	// toggleDuration: Integer
+	//	Number of milliseconds for toggle animation effect to complete
+	toggleDuration: 150,
+
+	initialize: function(args, frag){
+		// summary: called after the widget is rendered; most subclasses won't override or call this function
+	},
+
+	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;
+	},
+
+	createNodesFromText: function(txt, wrap){
+		return dojo.html.createNodesFromText(txt, wrap);
+	},
+
+	destroyRendering: function(finalize){
+		try{
+			if(this.bgIframe){
+				this.bgIframe.remove();
+				delete this.bgIframe;
+			}
+			if(!finalize && this.domNode){
+				dojo.event.browser.clean(this.domNode);
+			}
+			dojo.widget.HtmlWidget.superclass.destroyRendering.call(this);
+		}catch(e){ /* squelch! */ }
+	},
+
+	/////////////////////////////////////////////////////////
+	// Displaying/hiding the widget
+	/////////////////////////////////////////////////////////
+	isShowing: function(){
+		// summary
+		//	Tests whether widget is set to show-mode or hide-mode (see show() and 
+		//	hide() methods)
+		//
+		//	This function is poorly named.  Even if widget is in show-mode,
+		//	if it's inside a container that's hidden
+		//	(either a container widget, or just a domnode with display:none),
+		//	then it won't be displayed
+		return dojo.html.isShowing(this.domNode);	// Boolean
+	},
+
+	toggleShowing: function(){
+		// summary: show or hide the widget, to switch it's state
+		if(this.isShowing()){
+			this.hide();
+		}else{
+			this.show();
+		}
+	},
+
+	show: function(){
+		// summary: show the widget
+		if(this.isShowing()){ return; }
+		this.animationInProgress=true;
+		this.toggleObj.show(this.domNode, this.toggleDuration, null,
+			dojo.lang.hitch(this, this.onShow), this.explodeSrc);
+	},
+
+	onShow: function(){
+		// summary: called after the show() animation has completed
+		this.animationInProgress=false;
+		this.checkSize();
+	},
+
+	hide: function(){
+		// summary: hide the widget (ending up with display:none)
+		if(!this.isShowing()){ return; }
+		this.animationInProgress = true;
+		this.toggleObj.hide(this.domNode, this.toggleDuration, null,
+			dojo.lang.hitch(this, this.onHide), this.explodeSrc);
+	},
+
+	onHide: function(){
+		// summary: called after the hide() animation has completed
+		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
+	//////////////////////////////////////////////////////////////////////////////
+
+	_isResized: function(w, h){
+		// summary
+		//	Test if my size has changed.
+		//	If width & height are specified then that's my new size; otherwise,
+		//	query outerWidth/outerHeight of my domNode
+
+		// 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;
+	},
+
+	checkSize: function(){
+		// summary
+		//	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.
+		if(!this._isResized()){ return; }
+		this.onResized();
+	},
+
+	resizeTo: function(w, h){
+		// summary: explicitly set this widget's size (in pixels).
+		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(){
+		// summary
+		//	schedule onResized() to be called soon, after browser has had
+		//	a little more time to calculate the sizes
+		if(this.isShowing()){
+			dojo.lang.setTimeout(this, this.onResized, 0);
+		}
+	},
+
+	onResized: function(){
+		// summary
+		//	Called when my size has changed.
+		//	Must notify children if their size has (possibly) changed.
+		dojo.lang.forEach(this.children, function(child){ if(child.checkSize){child.checkSize();} });
+	}
+});

Added: incubator/xap/trunk/codebase/src/dojo/src/widget/InlineEditBox.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/dojo/src/widget/InlineEditBox.js?view=auto&rev=518313
==============================================================================
--- incubator/xap/trunk/codebase/src/dojo/src/widget/InlineEditBox.js (added)
+++ incubator/xap/trunk/codebase/src/dojo/src/widget/InlineEditBox.js Wed Mar 14 13:36:44 2007
@@ -0,0 +1,250 @@
+/*
+	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(){
+		// summary
+		//		Given node is displayed as-is (for example, an <h1 dojoType="InlineEditBox">
+		//		is displayed as an <h1>, but when you click on it, it turns into an
+		//		<input> or <textarea>, and the user can edit the value.
+
+		// 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"),
+
+	// mode: String
+	//		"text" is the default, and means that the node will convert it into a (single-line) <input>
+	//		when you click on it;
+	//		"textarea" means that the node will be converted into a multi-line <textarea> for editing.
+	mode: "text",
+	
+	// name: String
+	//		This is passed as the third argument to onSave().
+	name: "",
+
+	// minWidth:  Integer
+	//		Pixel minimum width of edit box
+	minWidth: 100,
+
+	// minHeight: Integer
+	//		Pixel minimum height of edit box, if it's a <textarea>
+	minHeight: 200,
+
+	// editing: Boolean
+	//		Is the node currently in edit mode?
+	editing: false,
+
+	// value: String
+	//		The text string displayed or edited.
+	//		Initial value can also be specified inline, like
+	//		<h1 dojoType="InlineEditBox">Hello world</h1>
+	value: "",
+
+	// deprecated
+	textValue: "",
+	defaultText: "",
+	
+	postMixInProperties: function(){
+		if(this.textValue){
+			dojo.deprecated("InlineEditBox: Use value parameter instead of textValue; will be removed in 0.5");
+			this.value=this.textValue;
+		}
+		if(this.defaultText){
+			dojo.deprecated("InlineEditBox: Use value parameter instead of defaultText; will be removed in 0.5");
+			this.value=this.defaultText;
+		}
+	},
+
+	onSave: function(newValue, oldValue, name){
+		// summary: Callback for when value is changed.
+	},
+	onUndo: function(value){
+		// summary: Callback for when editing is aborted (value reverts to pre-edit value).
+	},
+
+	postCreate: function(args, frag){
+		// put original node back in the document, and attach handlers
+		// which hide it and display the editor
+		// TODO: this has a number of issues including breaking programatic creation
+		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");
+		
+		// get value and display it
+		if(this.value){
+			this.editable.innerHTML = this.value;
+			return;
+		} else {
+			this.value = dojo.string.trim(this.editable.innerHTML);
+			this.editable.innerHTML = this.value;
+		}
+	},
+	
+	onMouseOver: function(){
+		if(!this.editing){
+			if (this.disabled){
+				dojo.html.addClass(this.editable, "editableRegionDisabled");
+			} else {
+				dojo.html.addClass(this.editable, "editableRegion");
+				if(this.mode == "textarea"){
+					dojo.html.addClass(this.editable, "editableTextareaRegion");
+				}
+			}
+		}
+	},
+	
+	onMouseOut: function(){
+		if(!this.editing){
+			dojo.html.removeClass(this.editable, "editableRegion");
+			dojo.html.removeClass(this.editable, "editableTextareaRegion");
+			dojo.html.removeClass(this.editable, "editableRegionDisabled");
+		}
+	},
+
+	_beginEdit: function(e){
+		// summary
+		// 		When user clicks the text, then start editing.
+		// 		Hide the text and display the form instead.
+
+		if(this.editing || this.disabled){ return; }
+		this.onMouseOut();
+		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.value);
+		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){
+		// summary: Callback when user presses "Save" button
+		e.preventDefault();
+		e.stopPropagation();
+		var ee = this[this.mode.toLowerCase()];
+		if((this.value != ee.value)&&
+			(dojo.string.trim(ee.value) != "")){
+			this.doFade = true;
+			this.history.push(this.value);
+			this.onSave(ee.value, this.value, this.name);
+			this.value = ee.value;
+			this.editable.innerHTML = "";
+			var textNode = document.createTextNode( this.value );
+			this.editable.appendChild( textNode );
+		}else{
+			this.doFade = false;
+		}
+		this._finishEdit(e);
+	},
+
+	cancelEdit: function(e){
+		// summary: Callback when user presses "Cancel" button
+		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){
+		dojo.deprecated("setText() is deprecated, call setValue() instead, will be removed in 0.5");
+		this.setValue(txt);
+	},
+	
+	setValue: function(/*String*/ txt){
+		// sets the text without informing the server
+		txt = "" + txt;
+		var tt = dojo.string.trim(txt);
+		this.value = tt
+		this.editable.innerHTML = tt;
+	},
+
+	undo: function(){
+		// summary: Revert to previous value in history list.
+		if(this.history.length > 0){
+			var curValue = this.value;
+			var value = this.history.pop();
+			this.editable.innerHTML = value;
+			this.value = value;
+			this.onUndo(value);
+			this.onSave(value, curValue, this.name);
+		}
+	},
+
+	checkForValueChange: function(){
+		// summary
+		//		Callback when user changes input value.
+		//		Enable save button if the text value is different than the original value.
+		var ee = this[this.mode.toLowerCase()];
+		if((this.value != 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.InlineEditBox.superclass.disable.apply(this, arguments);
+	},
+	
+	enable: function(){
+		this.checkForValueChange();
+		this.cancelButton.disabled = false;
+		var ee = this[this.mode.toLowerCase()];
+		ee.disabled = false;
+		
+		dojo.widget.InlineEditBox.superclass.enable.apply(this, arguments);
+	}
+});

Added: incubator/xap/trunk/codebase/src/dojo/src/widget/IntegerTextbox.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/dojo/src/widget/IntegerTextbox.js?view=auto&rev=518313
==============================================================================
--- incubator/xap/trunk/codebase/src/dojo/src/widget/IntegerTextbox.js (added)
+++ incubator/xap/trunk/codebase/src/dojo/src/widget/IntegerTextbox.js Wed Mar 14 13:36:44 2007
@@ -0,0 +1,72 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.widget.IntegerTextbox");
+
+dojo.require("dojo.widget.ValidationTextbox");
+dojo.require("dojo.validate.common");
+
+dojo.widget.defineWidget(
+	"dojo.widget.IntegerTextbox",
+	dojo.widget.ValidationTextbox,
+	{
+		// summary:
+		//		A subclass of ValidationTextbox.
+		//		Over-rides isValid/isInRange to test for integer input.
+		// signed: String
+		//		The leading plus-or-minus sign. Can be true or false, default is either.
+		/*=====
+		signed: "either",
+		// separator: "",
+		//		The character used as the thousands separator.  Default is no separator.
+		separator: "",
+		// min: Number
+		//		Minimum signed value.  Default is -Infinity
+		min: undefined,
+		// max: Number
+		//		Maximum signed value.  Default is +Infinity
+		max: undefined,
+		=====*/
+		mixInProperties: function(localProperties, frag){
+			// First initialize properties in super-class.
+			dojo.widget.IntegerTextbox.superclass.mixInProperties.apply(this, arguments);
+	
+			// Get properties from markup attributes, and assign to flags object.
+			if((localProperties.signed == "true")||
+				(localProperties.signed == "always")){
+				this.flags.signed = true;
+			}else if((localProperties.signed == "false")||
+					(localProperties.signed == "never")){
+				this.flags.signed = false;
+				this.flags.min = 0;
+			}else{
+				this.flags.signed = [ true, false ]; // optional
+			}
+			if(localProperties.separator){ 
+				this.flags.separator = localProperties.separator;
+			}
+			if(localProperties.min){ 
+				this.flags.min = parseInt(localProperties.min);
+			}
+			if(localProperties.max){ 
+				this.flags.max = parseInt(localProperties.max);
+			}
+		},
+
+		isValid: function(){
+			// summary: Over-ride for integer validation
+			return dojo.validate.isInteger(this.textbox.value, this.flags);
+		},
+		isInRange: function(){
+			// summary: Over-ride for integer validation
+			return dojo.validate.isInRange(this.textbox.value, this.flags);
+		}
+	}
+);

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

Added: incubator/xap/trunk/codebase/src/dojo/src/widget/LayoutContainer.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/dojo/src/widget/LayoutContainer.js?view=auto&rev=518313
==============================================================================
--- incubator/xap/trunk/codebase/src/dojo/src/widget/LayoutContainer.js (added)
+++ incubator/xap/trunk/codebase/src/dojo/src/widget/LayoutContainer.js Wed Mar 14 13:36:44 2007
@@ -0,0 +1,101 @@
+/*
+	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.LayoutContainer");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.html.layout");
+
+dojo.widget.defineWidget(
+	"dojo.widget.LayoutContainer",
+	dojo.widget.HtmlWidget,
+{
+	// summary
+	//	Provides Delphi-style panel layout semantics.
+	//
+	// details
+	//	A LayoutContainer is a box with a specified size (like style="width: 500px; height: 500px;"),
+	//	that contains children widgets marked with "layoutAlign" of "left", "right", "bottom", "top", and "client".
+	//	It takes it's children marked as left/top/bottom/right, and lays them out along the edges of the box,
+	//	and then it takes the child marked "client" and puts it into the remaining space in the middle.
+	//
+	//  Left/right positioning is similar to CSS's "float: left" and "float: right",
+	//	and top/bottom positioning would be similar to "float: top" and "float: bottom", if there were such
+	//	CSS.
+	//
+	//	Note that there can only be one client element, but there can be multiple left, right, top,
+	//	or bottom elements.
+	//
+	// usage
+	//	<style>
+	//		html, body{ height: 100%; width: 100%; }
+	//	</style>
+	//	<div dojoType="LayoutContainer" style="width: 100%; height: 100%">
+	//		<div dojoType="ContentPane" layoutAlign="top">header text</div>
+	//		<div dojoType="ContentPane" layoutAlign="left" style="width: 200px;">table of contents</div>
+	//		<div dojoType="ContentPane" layoutAlign="client">client area</div>
+	//	</div>
+
+	isContainer: true,
+
+	// layoutChildPriority: String
+	//	- If the value is "top-bottom", then LayoutContainer will first position the "top" and "bottom" aligned elements,
+	//	to and then put the left and right aligned elements in the remaining space, between the top and the bottom elements.
+	//	It aligns the client element at the very end, in the remaining space.
+	//
+	//	- If the value is "left-right", then it first positions the "left" and "right" elements, and then puts the
+	//	"top" and "bottom" elements in the remaining space, between the left and the right elements.
+	//	It aligns the client element at the very end, in the remaining space.
+	//
+	//	- If the value is "none", then it will lay out each child in the natural order the children occur in.
+	//	Basically each child is laid out into the "remaining space", where "remaining space" is initially
+	//	the content area of this widget, but is reduced to a smaller rectangle each time a child is added.
+	//	
+	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: String
+	//		"none", "left", "right", "bottom", "top", and "client".
+	//		See the LayoutContainer description for details on this parameter.
+	layoutAlign: 'none'
+});

Added: incubator/xap/trunk/codebase/src/dojo/src/widget/LinkPane.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/dojo/src/widget/LinkPane.js?view=auto&rev=518313
==============================================================================
--- incubator/xap/trunk/codebase/src/dojo/src/widget/LinkPane.js (added)
+++ incubator/xap/trunk/codebase/src/dojo/src/widget/LinkPane.js Wed Mar 14 13:36:44 2007
@@ -0,0 +1,43 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.widget.LinkPane");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.ContentPane");
+dojo.require("dojo.html.style");
+
+dojo.widget.defineWidget(
+	"dojo.widget.LinkPane",
+	dojo.widget.ContentPane,
+{
+	// summary
+	//	LinkPane is just a ContentPane that loads data remotely (via the href attribute),
+	//	and has markup similar to an anchor.  The anchor's body (the words between <a> and </a>)
+	//	become the label of the widget (used for TabContainer, AccordionContainer, etc.)
+	// usage
+	//	<a href="foo.html">my label</a>
+
+	// I'm using a template because the user may specify the input as
+	// <a href="foo.html">label</a>, in which case we need to get rid of the
+	// <a> because we don't want a link.
+	templateString: '<div class="dojoLinkPane"></div>',
+
+	fillInTemplate: function(args, frag){
+		var source = this.getFragNodeRef(frag);
+
+		// If user has specified node contents, they become the label
+		// (the link must be plain text)
+		this.label += source.innerHTML;
+
+		var source = this.getFragNodeRef(frag);
+		dojo.html.copyStyle(this.domNode, source);
+	}
+});

Added: incubator/xap/trunk/codebase/src/dojo/src/widget/Manager.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/dojo/src/widget/Manager.js?view=auto&rev=518313
==============================================================================
--- incubator/xap/trunk/codebase/src/dojo/src/widget/Manager.js (added)
+++ incubator/xap/trunk/codebase/src/dojo/src/widget/Manager.js Wed Mar 14 13:36:44 2007
@@ -0,0 +1,365 @@
+/*
+	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.*");
+
+// summary
+//	Manager class for the widgets.
+//	This is an internal class used by dojo; users shouldn't call this class directly.
+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) {
+		var widgetId;
+		do{
+			widgetId = widgetType + "_" + (widgetTypeCtr[widgetType] != undefined ?
+			++widgetTypeCtr[widgetType] : widgetTypeCtr[widgetType] = 0);
+		}while(this.getWidgetById(widgetId));
+		return widgetId;
+	}
+
+	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.ns+'_'+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.ns.get(ns);
+		if(!nsObj){
+			// default to <ns>.widget by convention
+			dojo.ns.register(ns, ns + '.widget');
+			nsObj = dojo.ns.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.module);
+		if(impl){return(imps[lowerCaseWidgetName] = impl)};
+
+		// try to load a manifest to resolve this implemenation
+		nsObj = dojo.ns.require(ns);
+		if((nsObj)&&(nsObj.resolver)){
+			nsObj.resolve(widgetName);
+			impl = findImplementation(lowerCaseWidgetName, nsObj.module);
+			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;
+})();



Mime
View raw message