You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jetspeed-dev@portals.apache.org by ta...@apache.org on 2005/12/06 20:30:51 UTC

svn commit: r354516 [10/15] - in /portals/jetspeed-2/trunk: applications/j2-admin/src/java/org/apache/jetspeed/portlets/customizer/ applications/j2-admin/src/webapp/WEB-INF/ applications/j2-admin/src/webapp/WEB-INF/view/customizer/ applications/j2-admi...

Added: portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/HtmlSplitPane.js
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/HtmlSplitPane.js?rev=354516&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/HtmlSplitPane.js (added)
+++ portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/HtmlSplitPane.js Tue Dec  6 11:29:56 2005
@@ -0,0 +1,512 @@
+dojo.provide("dojo.widget.SplitPane");
+dojo.provide("dojo.widget.SplitPanePanel");
+dojo.provide("dojo.widget.HtmlSplitPane");
+dojo.provide("dojo.widget.HtmlSplitPanePanel");
+
+//
+// TODO
+// make it prettier
+// active dragging upwards doesn't always shift other bars (direction calculation is wrong in this case)
+//
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlLayoutPane");
+dojo.require("dojo.html");
+dojo.require("dojo.style");
+dojo.require("dojo.dom");
+
+dojo.widget.HtmlSplitPane = function(){
+
+	dojo.widget.HtmlLayoutPane.call(this);
+
+	this.sizers = [];
+}
+
+dojo.inherits(dojo.widget.HtmlSplitPane, dojo.widget.HtmlLayoutPane);
+
+dojo.lang.extend(dojo.widget.HtmlSplitPane, {
+	widgetType: "SplitPane",
+	virtualSizer: null,
+	isHorizontal: 0,
+	paneBefore: null,
+	paneAfter: null,
+	isSizing: false,
+	dragOffset: null,
+	startPoint: null,
+	lastPoint: null,
+	sizingSplitter: null,
+	isActiveResize: 0,
+	offsetX: 0,
+	offsetY: 0,
+	isDraggingLeft: 0,
+	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlSplitPane.css"),
+	originPos: null,
+
+	activeSizing: '',
+	sizerWidth: 15,
+	orientation: 'horizontal',
+
+	debugName: '',
+
+	fillInTemplate: function(){
+
+		dojo.style.insertCssFile(this.templateCssPath);
+
+		this.domNode.style.position = 'relative';
+		this.paneWidth = dojo.style.getContentWidth(this.domNode);
+		this.paneHeight = dojo.style.getContentHeight(this.domNode);
+
+		this.isHorizontal = (this.orientation == 'horizontal') ? 1 : 0;
+		this.isActiveResize = (this.activeSizing == '1') ? 1 : 0;
+
+		//dojo.debug("fillInTemplate for "+this.debugName);
+	},
+
+	onResized: function(e){
+		this.paneWidth = dojo.style.getContentWidth(this.domNode);
+		this.paneHeight = dojo.style.getContentHeight(this.domNode);
+		this.layoutPanels();
+		this.notifyChildrenOfResize();	// notify children they've been moved/resized
+	},
+
+	postCreate: function(args, fragment, parentComp){
+
+		// dojo.debug("post create for "+this.debugName);
+
+		// attach the children
+
+		for(var i=0; i<this.children.length; i++){
+			with(this.children[i].domNode.style){
+				position = "absolute";
+				overflow = "hidden";
+			}
+			dojo.html.addClass(this.children[i].domNode, 
+				"dojoHtmlSplitterPanePanel");
+		}
+
+		// create the draggers
+
+		for(var i=0; i<this.children.length-1; i++){
+
+			// i still don't understand this closure black magic :) [CH]
+			var self = this;
+			var handler = (function(){ var sizer_i = i; return function(e){ self.beginSizing(e, sizer_i); } })();
+
+			this.sizers[i] = document.createElement('div');
+			this.sizers[i].style.position = 'absolute';
+			this.sizers[i].onmousedown = handler;
+			this.sizers[i].className = this.isHorizontal ? 'dojoHtmlSplitPaneSizerH' : 'dojoHtmlSplitPaneSizerV';
+			this.domNode.appendChild(this.sizers[i]);
+
+			dojo.html.disableSelection(this.sizers[i]);
+
+		}
+
+		// create the fake dragger
+
+		this.virtualSizer = document.createElement('div');
+		this.virtualSizer.style.position = 'absolute';
+		this.virtualSizer.style.display = 'none';
+		//this.virtualSizer.style.backgroundColor = 'lime';
+		this.virtualSizer.style.zIndex = 10;
+		this.virtualSizer.className = this.isHorizontal ? 'dojoHtmlSplitPaneVirtualSizerH' : 'dojoHtmlSplitPaneVirtualSizerV';
+		this.domNode.appendChild(this.virtualSizer);
+
+		dojo.html.disableSelection(this.virtualSizer);
+
+		//
+		// size the panels once the browser has caught up
+		//
+		this.resizeSoon();
+	},
+
+
+	layoutPanels: function(){
+
+		//
+		// calculate space
+		//
+
+		var space = this.isHorizontal ? this.paneWidth : this.paneHeight;
+
+		if (this.children.length > 1){
+
+			space -= this.sizerWidth * (this.children.length - 1);
+		}
+
+
+		//
+		// calculate total of SizeShare values
+		//
+
+		var out_of = 0;
+
+		for(var i=0; i<this.children.length; i++){
+
+			out_of += this.children[i].sizeShare;
+		}
+
+
+		//
+		// work out actual pixels per sizeshare unit
+		//
+
+		var pix_per_unit = space / out_of;
+
+
+		//
+		// set the SizeActual member of each pane
+		//
+
+		var total_size = 0;
+
+		for(var i=0; i<this.children.length-1; i++){
+
+			var size = Math.round(pix_per_unit * this.children[i].sizeShare);
+			this.children[i].sizeActual = size;
+			total_size += size;
+		}
+		this.children[this.children.length-1].sizeActual = space - total_size;
+
+		//
+		// make sure the sizes are ok
+		//
+
+		this.checkSizes();
+
+
+		//
+		// now loop, positioning each pane
+		//
+
+		var pos = 0;
+		var size = this.children[0].sizeActual;
+		this.movePanel(this.children[0].domNode, pos, size);
+		this.children[0].position = pos;
+		this.children[0].sizeSet(size);
+		pos += size;
+
+		for(var i=1; i<this.children.length; i++){
+
+			// first we position the sizing handle before this pane
+			this.movePanel(this.sizers[i-1], pos, this.sizerWidth);
+			this.sizers[i-1].position = pos;
+			pos += this.sizerWidth;
+
+			size = this.children[i].sizeActual;
+			this.movePanel(this.children[i].domNode, pos, size);
+			this.children[i].position = pos;
+			this.children[i].sizeSet(size);
+			pos += size;
+		}
+		
+		//
+		// if children are widgets, then let them resize themselves (if they want to)
+		//
+		for(var i=0; i<this.children.length; i++){
+			this.children[i].onResized();
+		}
+	},
+
+	movePanel: function(panel, pos, size){
+		if (this.isHorizontal){
+			panel.style.left = pos + 'px';
+			panel.style.top = 0;
+
+			dojo.style.setOuterWidth(panel, size);
+			dojo.style.setOuterHeight(panel, this.paneHeight);
+		}else{
+			panel.style.left = 0;
+			panel.style.top = pos + 'px';
+
+			dojo.style.setOuterWidth(panel, this.paneWidth);
+			dojo.style.setOuterHeight(panel, size);
+		}
+	},
+
+	growPane: function(growth, pane){
+
+		if (growth > 0){
+			if (pane.sizeActual > pane.sizeMin){
+				if ((pane.sizeActual - pane.sizeMin) > growth){
+
+					// stick all the growth in this pane
+					pane.sizeActual = pane.sizeActual - growth;
+					growth = 0;
+				}else{
+					// put as much growth in here as we can
+					growth -= pane.sizeActual - pane.sizeMin;
+					pane.sizeActual = pane.sizeMin;
+				}
+			}
+		}
+		return growth;
+	},
+
+	checkSizes: function(){
+
+		var total_min_size = 0;
+		var total_size = 0;
+
+		for(var i=0; i<this.children.length; i++){
+
+			total_size += this.children[i].sizeActual;
+			total_min_size += this.children[i].sizeMin;
+		}
+
+		// only make adjustments if we have enough space for all the minimums
+
+		if (total_min_size <= total_size){
+
+			var growth = 0;
+
+			for(var i=0; i<this.children.length; i++){
+
+				if (this.children[i].sizeActual < this.children[i].sizeMin){
+
+					growth += this.children[i].sizeMin - this.children[i].sizeActual;
+					this.children[i].sizeActual = this.children[i].sizeMin;
+				}
+			}
+
+			if (growth > 0){
+				if (this.isDraggingLeft){
+					for(var i=this.children.length-1; i>=0; i--){
+						growth = this.growPane(growth, this.children[i]);
+					}
+				}else{
+					for(var i=0; i<this.children.length; i++){
+						growth = this.growPane(growth, this.children[i]);
+					}
+				}
+			}
+		}else{
+
+			for(var i=0; i<this.children.length; i++){
+				this.children[i].sizeActual = Math.round(total_size * (this.children[i].sizeMin / total_min_size));
+			}
+		}
+	},
+
+	beginSizing: function(e, i){
+		var clientX = window.event ? window.event.offsetX : e.layerX;
+		var clientY = window.event ? window.event.offsetY : e.layerY;
+		var screenX = window.event ? window.event.clientX : e.pageX;
+		var screenY = window.event ? window.event.clientY : e.pageY;
+
+		this.paneBefore = this.children[i];
+		this.paneAfter = this.children[i+1];
+
+		this.isSizing = true;
+		this.sizingSplitter = this.sizers[i];
+		this.originPos = dojo.style.getAbsolutePosition(this.domNode, true);
+		this.dragOffset = {'x':clientX, 'y':clientY};
+		this.startPoint  = {'x':screenX, 'y':screenY};
+		this.lastPoint  = {'x':screenX, 'y':screenY};
+
+		this.offsetX = screenX - clientX;
+		this.offsetY = screenY - clientY;
+
+		if (!this.isActiveResize){
+			this.showSizingLine();
+		}
+		
+		//
+		// attach mouse events
+		//
+
+		dojo.event.connect(document.documentElement, "onmousemove", this, "changeSizing");
+		dojo.event.connect(document.documentElement, "onmouseup", this, "endSizing");
+	},
+
+	changeSizing: function(e){
+
+		// FIXME: is this fixed in connect()?
+		var screenX = window.event ? window.event.clientX : e.pageX;
+		var screenY = window.event ? window.event.clientY : e.pageY;
+
+		if (this.isActiveResize){
+			this.lastPoint = {'x':screenX, 'y':screenY};
+			this.movePoint();
+			this.updateSize();
+		}else{
+			this.lastPoint = {'x':screenX, 'y':screenY};
+			this.movePoint();
+			this.moveSizingLine();
+		}
+	},
+
+	endSizing: function(e){
+
+		if (!this.isActiveResize){
+			this.hideSizingLine();
+		}
+
+		this.updateSize();
+
+		this.isSizing = false;
+
+		dojo.event.disconnect(document.documentElement, "onmousemove", this, "changeSizing");
+		dojo.event.disconnect(document.documentElement, "onmouseup", this, "endSizing");
+	},
+
+	movePoint: function(){
+
+		// make sure FLastPoint is a legal point to drag to
+		p = this.screenToMainClient(this.lastPoint);
+
+		if (this.isHorizontal){
+
+			var a = p.x - this.dragOffset.x;
+			a = this.legaliseSplitPoint(a);
+			p.x = a + this.dragOffset.x;
+		}else{
+			var a = p.y - this.dragOffset.y;
+			a = this.legaliseSplitPoint(a);
+			p.y = a + this.dragOffset.y;
+		}
+
+		this.lastPoint = this.mainClientToScreen(p);
+	},
+
+	screenToClient: function(pt){
+
+		pt.x -= (this.offsetX + this.sizingSplitter.position);
+		pt.y -= (this.offsetY + this.sizingSplitter.position);
+
+		return pt;
+	},
+
+	clientToScreen: function(pt){
+
+		pt.x += (this.offsetX + this.sizingSplitter.position);
+		pt.y += (this.offsetY + this.sizingSplitter.position);
+
+		return pt;
+	},
+
+	screenToMainClient: function(pt){
+
+		pt.x -= this.offsetX;
+		pt.y -= this.offsetY;
+
+		return pt;
+	},
+
+	mainClientToScreen: function(pt){
+
+		pt.x += this.offsetX;
+		pt.y += this.offsetY;
+
+		return pt;
+	},
+
+	legaliseSplitPoint: function(a){
+
+		a += this.sizingSplitter.position;
+
+		this.isDraggingLeft = (a > 0) ? 1 : 0;
+
+		if (!this.isActiveResize){
+
+			if (a < this.paneBefore.position + this.paneBefore.sizeMin){
+
+				a = this.paneBefore.position + this.paneBefore.sizeMin;
+			}
+
+			if (a > this.paneAfter.position + (this.paneAfter.sizeActual - (this.sizerWidth + this.paneAfter.sizeMin))){
+
+				a = this.paneAfter.position + (this.paneAfter.sizeActual - (this.sizerWidth + this.paneAfter.sizeMin));
+			}
+		}
+
+		a -= this.sizingSplitter.position;
+
+		this.checkSizes();
+
+		return a;
+	},
+
+	updateSize: function(){
+
+		var p = this.clientToScreen(this.lastPoint);
+		var p = this.screenToClient(this.lastPoint);
+
+		var pos = this.isHorizontal ? p.x - (this.dragOffset.x + this.originPos.x) : p.y - (this.dragOffset.y + this.originPos.y);
+
+		var start_region = this.paneBefore.position;
+		var end_region   = this.paneAfter.position + this.paneAfter.sizeActual;
+
+		this.paneBefore.sizeActual = pos - start_region;
+		this.paneAfter.position    = pos + this.sizerWidth;
+		this.paneAfter.sizeActual  = end_region - this.paneAfter.position;
+
+		for(var i=0; i<this.children.length; i++){
+
+			this.children[i].sizeShare = this.children[i].sizeActual;
+		}
+
+		this.layoutPanels();
+	},
+
+	showSizingLine: function(){
+
+		this.moveSizingLine();
+
+		if (this.isHorizontal){
+			dojo.style.setOuterWidth(this.virtualSizer, this.sizerWidth);
+			dojo.style.setOuterHeight(this.virtualSizer, this.paneHeight);
+		}else{
+			dojo.style.setOuterWidth(this.virtualSizer, this.paneWidth);
+			dojo.style.setOuterHeight(this.virtualSizer, this.sizerWidth);
+		}
+
+		this.virtualSizer.style.display = 'block';
+	},
+
+	hideSizingLine: function(){
+
+		this.virtualSizer.style.display = 'none';
+	},
+
+	moveSizingLine: function(){
+
+		var origin = {'x':0, 'y':0};
+
+		if (this.isHorizontal){
+			origin.x += (this.lastPoint.x - this.startPoint.x) + this.sizingSplitter.position;
+		}else{
+			origin.y += (this.lastPoint.y - this.startPoint.y) + this.sizingSplitter.position;
+		}
+
+		this.virtualSizer.style.left = origin.x + 'px';
+		this.virtualSizer.style.top = origin.y + 'px';
+	}
+});
+
+dojo.widget.HtmlSplitPanePanel = function(){
+	dojo.widget.HtmlLayoutPane.call(this);
+}
+
+dojo.inherits(dojo.widget.HtmlSplitPanePanel, dojo.widget.HtmlLayoutPane);
+
+dojo.lang.extend(dojo.widget.HtmlSplitPanePanel, {
+
+	widgetType: "SplitPanePanel",
+	sizeActual: 0,
+	position: 0,
+
+	sizeMin: 10,
+	sizeShare: 10,
+
+	sizeSet: function(height){
+	},
+
+	fillInTemplate: function(args, frag) {
+		this.domNode.style.position="relative";	// in case my child does a height=100%
+	}
+});
+
+
+dojo.widget.tags.addParseTreeHandler("dojo:SplitPane");
+dojo.widget.tags.addParseTreeHandler("dojo:SplitPanePanel");

Added: portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/HtmlTabSet.js
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/HtmlTabSet.js?rev=354516&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/HtmlTabSet.js (added)
+++ portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/HtmlTabSet.js Tue Dec  6 11:29:56 2005
@@ -0,0 +1,129 @@
+dojo.provide("dojo.widget.HtmlTabSet");
+dojo.provide("dojo.widget.HtmlTab");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlLayoutPane");
+dojo.require("dojo.event.*");
+dojo.require("dojo.html");
+dojo.require("dojo.style");
+
+//////////////////////////////////////////
+// TabSet -- a set of Tabs
+//////////////////////////////////////////
+dojo.widget.HtmlTabSet = function() {
+	dojo.widget.HtmlLayoutPane.call(this);
+}
+dojo.inherits(dojo.widget.HtmlTabSet, dojo.widget.HtmlLayoutPane);
+
+dojo.lang.extend(dojo.widget.HtmlTabSet, {
+
+	widgetType: "TabSet",
+
+	labelPosition: "top",
+
+	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlTabSet.css"),
+
+	selectedTab: "",		// currently selected tab's widgetId, later widget
+
+	fillInTemplate: function(args, frag) {
+		dojo.widget.HtmlTabSet.superclass.fillInTemplate.call(this, args, frag);
+		
+		// TODO: prevent multiple includes of the same CSS file, when there are multiple
+		// TabSets on the same screen.
+		dojo.style.insertCssFile(this.templateCssPath);
+
+		// Create panel to hold the tab labels (as a <ul> with special formatting)
+		// TODO: set "bottom" css tag if label is on bottom
+		this.filterAllowed('labelPosition', ['top', 'bottom']);
+		this.labelPanel = dojo.widget.fromScript("LayoutPane", {layoutAlign: this.labelPosition});
+		this.ul = document.createElement("ul");
+		dojo.html.addClass(this.ul, "tabs");
+		dojo.html.addClass(this.ul, this.labelPosition);
+		this.labelPanel.domNode.appendChild(this.ul);
+		this.addPane(this.labelPanel);
+	},
+
+	registerChild: function(child, insertionIndex){
+		// registerChild will be called for each tab, and also for the
+		// top pane (layoutAlign="top") that holds all the tab labels
+
+		dojo.widget.HtmlTabSet.superclass.registerChild.call(this, child, insertionIndex);
+
+		if ( child.widgetType == "Tab" ){
+			this.ul.appendChild(child.li);
+	
+			if (this.selectedTab==child.widgetId ||
+					child.selected) {
+				this.onSelected(child);
+			}
+		}
+	},
+
+	onSelected: function(tab) {
+		// Deselect old tab and select new one
+		if (this.selectedTab && this.selectedTab.widgetId) {
+			this.selectedTab.hide();
+		}
+		tab.show();
+		this.selectedTab = tab;		// becomes widget rather than string
+	},
+	
+	onResized: function() {
+		// If none of the tabs were specified as selected, catch that here
+		// and just select the first one
+		if ( !this.selectedTab.widgetId ) {
+			this.onSelected(this.children[0]);
+		}
+		dojo.widget.HtmlTabSet.superclass.onResized.call(this);
+	}
+});
+dojo.widget.tags.addParseTreeHandler("dojo:TabSet");
+
+//////////////////////////////////////////////////////
+// Tab - a single tab
+//////////////////////////////////////////////////////
+dojo.widget.HtmlTab = function() {
+	dojo.widget.HtmlLayoutPane.call(this);
+}
+dojo.inherits(dojo.widget.HtmlTab, dojo.widget.HtmlLayoutPane);
+
+dojo.lang.extend(dojo.widget.HtmlTab, {
+	widgetType: "Tab",
+	
+	label: "",
+	url: "inline",
+	handler: "none",
+	selected: false,	// is this tab currently selected?
+	
+	fillInTemplate: function(args, frag) {
+		this.layoutAlign = "client";
+		dojo.widget.HtmlTab.superclass.fillInTemplate.call(this, args, frag);
+		dojo.html.prependClass(this.domNode, "dojoTabPanel");
+		this.domNode.style.display="none";
+
+		// Create label
+		this.li = document.createElement("li");
+		var span = document.createElement("span");
+		span.innerHTML = this.label;
+		this.li.appendChild(span);
+		dojo.event.connect(this.li, "onclick", this, "onSelected");
+	},
+	
+	onSelected: function() {
+		this.parent.onSelected(this);
+	},
+	
+	show: function() {
+		dojo.html.addClass(this.li, "current");
+		this.selected=true;
+		dojo.widget.HtmlTab.superclass.show.call(this);
+	},
+
+	hide: function() {
+		dojo.html.removeClass(this.li, "current");
+		this.selected=false;
+		dojo.widget.HtmlTab.superclass.hide.call(this);
+	}	
+});
+dojo.widget.tags.addParseTreeHandler("dojo:Tab");
+

Added: portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/HtmlTabs.js
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/HtmlTabs.js?rev=354516&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/HtmlTabs.js (added)
+++ portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/HtmlTabs.js Tue Dec  6 11:29:56 2005
@@ -0,0 +1,277 @@
+dojo.provide("dojo.widget.Tabs");
+dojo.provide("dojo.widget.HtmlTabs");
+
+dj_deprecated("HtmlTabs is deprecated, use HtmlTabSet.js");
+
+dojo.require("dojo.io.*");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.dom");
+dojo.require("dojo.html");
+
+dojo.widget.HtmlTabs = function() {
+	dojo.widget.HtmlWidget.call(this);
+	this.tabs = [];
+	this.panels = [];
+}
+dojo.inherits(dojo.widget.HtmlTabs, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.HtmlTabs, {
+
+	widgetType: "Tabs",
+	isContainer: true,
+
+	templatePath: null, // prolly not
+	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlTabs.css"),
+
+	domNode: null,
+	containerNode: null,
+
+	selected: -1,
+
+	tabTarget: "",
+	extractContent: false, // find the bits inside <body>
+	parseContent: false, // parse externally loaded pages for widgets
+
+	buildRendering: function(args, frag) {
+		dojo.style.insertCssFile(this.templateCssPath);
+		this.domNode = frag["dojo:"+this.widgetType.toLowerCase()]["nodeRef"];
+		if(!this.domNode) { dj_error("HTMLTabs: No node reference"); }
+
+		if(args["tabtarget"]) {
+			this.tabtarget = args["tabtarget"];
+			this.containerNode = document.getElementById(args["tabtarget"]);
+		} else {
+			this.containerNode = document.createElement("div");
+			var next = this.domNode.nextSibling;
+			if(next) {
+				this.domNode.parentNode.insertBefore(this.containerNode, next);
+			} else {
+				this.domNode.parentNode.appendChild(this.containerNode);
+			}
+		}
+		dojo.html.addClass(this.containerNode, "dojoTabPanelContainer");
+
+		var li = dojo.dom.getFirstChildElement(this.domNode);
+		while(li) {
+			var a = li.getElementsByTagName("a").item(0);
+			this.addTab(a);
+			li = dojo.dom.getNextSiblingElement(li);
+		}
+
+		if(this.selected == -1) { this.selected = 0; }
+		this.selectTab(null, this.tabs[this.selected]);
+	},
+
+	addTab: function(title, url, tabId, tabHandler) {
+		// TODO: make this an object proper
+		var panel = {
+			url: null,
+			title: null,
+			isLoaded: false,
+			id: null,
+			isLocal: false
+		};
+
+		function isLocal(a) {
+			var url = a.getAttribute("href");
+			var hash = url.indexOf("#");
+			if(hash == 0) {
+				return true;
+			}
+			var loc = location.href.split("#")[0];
+			var url2 = url.split("#")[0];
+			if(loc == url2) {
+				return true;
+			}
+			if(unescape(loc) == url2) {
+				return true;
+			}
+			var outer = a.outerHTML;
+			if(outer && /href=["']?#/i.test(outer)) {
+				return true;
+			}
+			return false;
+		}
+
+		if(title && title.tagName && title.tagName.toLowerCase() == "a") {
+			// init case
+			var a = title;
+			var li = a.parentNode;
+			title = a.innerHTML;
+			url = a.getAttribute("href");
+			var id = null;
+			var hash = url.indexOf("#");
+			if(isLocal(a)) {
+				id = url.split("#")[1];
+				dj_debug("setting local id:", id);
+				url = "#" + id;
+				panel.isLocal = true;
+			} else {
+				id = a.getAttribute("tabid");
+			}
+
+			panel.url = url;
+			panel.title = title;
+			panel.id = id || dojo.html.getUniqueId();
+			dj_debug("panel id:", panel.id, "url:", panel.url);
+		} else {
+			// programmatically adding
+			var li = document.createElement("li");
+			var a = document.createElement("a");
+			a.innerHTML = title;
+			a.href = url;
+			li.appendChild(a);
+			this.domNode.appendChild(li);
+
+			panel.url = url;
+			panel.title = title;
+			panel.id = tabId || dojo.html.getUniqueId();
+			dj_debug("prg tab:", panel.id, "url:", panel.url);
+		}
+
+		if(panel.isLocal) {
+			var node = document.getElementById(id);
+			node.style.display = "none";
+			this.containerNode.appendChild(node);
+		} else {
+			var node = document.createElement("div");
+			node.style.display = "none";
+			node.id = panel.id;
+			this.containerNode.appendChild(node);
+		}
+
+		var handler = a.getAttribute("tabhandler") || tabHandler;
+		if(handler) {
+			this.setPanelHandler(handler, panel);
+		}
+
+		dojo.event.connect(a, "onclick", this, "selectTab");
+
+		this.tabs.push(li);
+		this.panels.push(panel);
+
+		if(this.selected == -1 && dojo.html.hasClass(li, "current")) {
+			this.selected = this.tabs.length-1;
+		}
+
+		return { "tab": li, "panel": panel };
+	},
+
+	selectTab: function(e, target) {
+		if(dojo.lang.isNumber(e)) {
+			target = this.tabs[e];
+		}
+		else if(e) {
+			if(e.target) {
+				target = e.target;
+				while(target && (target.tagName||"").toLowerCase() != "li") {
+					target = target.parentNode;
+				}
+			}
+			if(e.preventDefault) { e.preventDefault(); }
+		}
+
+		dojo.html.removeClass(this.tabs[this.selected], "current");
+
+		for(var i = 0; i < this.tabs.length; i++) {
+			if(this.tabs[i] == target) {
+				dojo.html.addClass(this.tabs[i], "current");
+				this.selected = i;
+				break;
+			}
+		}
+
+		var panel = this.panels[this.selected];
+		if(panel) {
+			this.getPanel(panel);
+			this.hidePanels(panel);
+			document.getElementById(panel.id).style.display = "";
+		}
+	},
+
+	setPanelHandler: function(handler, panel) {
+		var fcn = dojo.lang.isFunction(handler) ? handler : window[handler];
+		if(!dojo.lang.isFunction(fcn)) {
+			throw new Error("Unable to set panel handler, '" + handler + "' not a function.");
+			return;
+		}
+		this["tabHandler" + panel.id] = function() {
+			return fcn.apply(this, arguments);
+		}
+	},
+
+	runPanelHandler: function(panel) {
+		if(dojo.lang.isFunction(this["tabHandler" + panel.id])) {
+			this["tabHandler" + panel.id](panel, document.getElementById(panel.id));
+			return false;
+		}
+		return true;
+		/*
+		// in case we want to honor the return value?
+		var ret = true;
+		if(dojo.lang.isFunction(this["tabhandler" + panel.id])) {
+			var val = this["tabhandler" + panel.id](this, panel);
+			if(!dojo.lang.isUndefined(val)) {
+				ret = val;
+			}
+		}
+		return ret;
+		*/
+	},
+
+	getPanel: function(panel) {
+		if(this.runPanelHandler(panel)) {
+			if(panel.isLocal) {
+				// do nothing?
+			} else {
+				if(!panel.isLoaded || !this.useCache) {
+					this.setExternalContent(panel, panel.url, this.useCache);
+				}
+			}
+		}
+	},
+
+	setExternalContent: function(panel, url, useCache) {
+		var node = document.getElementById(panel.id);
+		node.innerHTML = "Loading...";
+
+		var extract = this.extractContent;
+		var parse = this.parseContent;
+
+		dojo.io.bind({
+			url: url,
+			useCache: useCache,
+			mimetype: "text/html",
+			handler: function(type, data, e) {
+				if(type == "load") {
+					if(extract) {
+						var matches = data.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
+						if(matches) { data = matches[1]; }
+					}
+					node.innerHTML = data;
+					panel.isLoaded = true;
+					if(parse) {
+						var parser = new dojo.xml.Parse();
+						var frag = parser.parseElement(node, null, true);
+						dojo.widget.getParser().createComponents(frag);
+					}
+				} else {
+					node.innerHTML = "Error loading '" + panel.url + "' (" + e.status + " " + e.statusText + ")";
+				}
+			}
+		});
+	},
+
+	hidePanels: function(except) {
+		for(var i = 0; i < this.panels.length; i++) {
+			if(this.panels[i] != except && this.panels[i].id) {
+				var p = document.getElementById(this.panels[i].id);
+				if(p) {
+					p.style.display = "none";
+				}
+			}
+		}
+	}
+});
+
+dojo.widget.tags.addParseTreeHandler("dojo:tabs");

Added: portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/HtmlTemplatedContainer.js
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/HtmlTemplatedContainer.js?rev=354516&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/HtmlTemplatedContainer.js (added)
+++ portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/HtmlTemplatedContainer.js Tue Dec  6 11:29:56 2005
@@ -0,0 +1,40 @@
+dojo.provide("dojo.widget.TemplatedContainer");
+dojo.provide("dojo.widget.HtmlTemplatedContainer");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlWidget");
+
+dojo.widget.HtmlTemplatedContainer = function(){
+	dojo.widget.HtmlWidget.call(this);
+}
+
+dojo.inherits(dojo.widget.HtmlTemplatedContainer, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.HtmlTemplatedContainer, {
+	widgetType: "TemplatedContainer",
+
+	isContainer: true,
+	templateString: '<div><div dojoAttachPoint="header"><hr></div><div dojoAttachPoint="containerNode"></div><div dojoAttachPoint="footer"><hr></div></div>',
+	header: null,
+	containerNode: null,
+	footer: null,
+	domNode: null,
+
+	onResized: function() {
+		// Clients should override this function to do special processing,
+		// then call this.notifyChildrenOfResize() to notify children of resize
+		this.notifyChildrenOfResize();
+	},
+	
+	notifyChildrenOfResize: function() {
+		for(var i=0; i<this.children.length; i++) {
+			var child = this.children[i];
+			//dojo.debug(this.widgetId + " resizing child " + child.widgetId);
+			if ( child.onResized ) {
+				child.onResized();
+			}
+		}
+	}
+});
+
+dojo.widget.tags.addParseTreeHandler("dojo:TemplatedContainer");

Added: portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/HtmlWidget.js
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/HtmlWidget.js?rev=354516&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/HtmlWidget.js (added)
+++ portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/HtmlWidget.js Tue Dec  6 11:29:56 2005
@@ -0,0 +1,185 @@
+dojo.provide("dojo.widget.HtmlWidget");
+dojo.require("dojo.widget.DomWidget");
+dojo.require("dojo.html");
+dojo.require("dojo.string");
+
+dojo.widget.HtmlWidget = function(args){
+	// mixin inheritance
+	dojo.widget.DomWidget.call(this);
+}
+
+dojo.inherits(dojo.widget.HtmlWidget, dojo.widget.DomWidget);
+
+dojo.lang.extend(dojo.widget.HtmlWidget, {
+	templateCssPath: null,
+	templatePath: null,
+	allowResizeX: true,
+	allowResizeY: true,
+
+	resizeGhost: null,
+	initialResizeCoords: null,
+	// this.templateString = null;
+
+	// for displaying/hiding widget
+	toggle: "plain",
+	toggleDuration: 150,
+
+	initialize: function(args, frag){
+	},
+
+	postMixInProperties: function(args, frag){
+		// now that we know the setting for toggle, define show()&hide()
+		dojo.lang.mixin(this,
+			dojo.widget.HtmlWidget.Toggle[dojo.string.capitalize(this.toggle)] ||
+			dojo.widget.HtmlWidget.Toggle.Plain);
+	},
+
+	getContainerHeight: function(){
+		// NOTE: container height must be returned as the INNER height
+		dj_unimplemented("dojo.widget.HtmlWidget.getContainerHeight");
+	},
+
+	getContainerWidth: function(){
+		return this.parent.domNode.offsetWidth;
+	},
+
+	setNativeHeight: function(height){
+		var ch = this.getContainerHeight();
+	},
+
+	startResize: function(coords){
+		// get the left and top offset of our dom node
+		coords.offsetLeft = dojo.html.totalOffsetLeft(this.domNode);
+		coords.offsetTop = dojo.html.totalOffsetTop(this.domNode);
+		coords.innerWidth = dojo.html.getInnerWidth(this.domNode);
+		coords.innerHeight = dojo.html.getInnerHeight(this.domNode);
+		if(!this.resizeGhost){
+			this.resizeGhost = document.createElement("div");
+			var rg = this.resizeGhost;
+			rg.style.position = "absolute";
+			rg.style.backgroundColor = "white";
+			rg.style.border = "1px solid black";
+			dojo.html.setOpacity(rg, 0.3);
+			dojo.html.body().appendChild(rg);
+		}
+		with(this.resizeGhost.style){
+			left = coords.offsetLeft + "px";
+			top = coords.offsetTop + "px";
+		}
+		this.initialResizeCoords = coords;
+		this.resizeGhost.style.display = "";
+		this.updateResize(coords, true);
+	},
+
+	updateResize: function(coords, override){
+		var dx = coords.x-this.initialResizeCoords.x;
+		var dy = coords.y-this.initialResizeCoords.y;
+		with(this.resizeGhost.style){
+			if((this.allowResizeX)||(override)){
+				width = this.initialResizeCoords.innerWidth + dx + "px";
+			}
+			if((this.allowResizeY)||(override)){
+				height = this.initialResizeCoords.innerHeight + dy + "px";
+			}
+		}
+	},
+
+	endResize: function(coords){
+		// FIXME: need to actually change the size of the widget!
+		var dx = coords.x-this.initialResizeCoords.x;
+		var dy = coords.y-this.initialResizeCoords.y;
+		with(this.domNode.style){
+			if(this.allowResizeX){
+				width = this.initialResizeCoords.innerWidth + dx + "px";
+			}
+			if(this.allowResizeY){
+				height = this.initialResizeCoords.innerHeight + dy + "px";
+			}
+		}
+		this.resizeGhost.style.display = "none";
+	},
+
+
+	createNodesFromText: function(txt, wrap){
+		return dojo.html.createNodesFromText(txt, wrap);
+	},
+
+	_old_buildFromTemplate: dojo.widget.DomWidget.prototype.buildFromTemplate,
+
+	buildFromTemplate: function(args, frag){
+		dojo.widget.buildFromTemplate(this);
+		this._old_buildFromTemplate(args, frag);
+	},
+
+	destroyRendering: function(finalize){
+		try{
+			var tempNode = this.domNode.parentNode.removeChild(this.domNode);
+			if(!finalize){
+				dojo.event.browser.clean(tempNode);
+			}
+			delete tempNode;
+		}catch(e){ /* squelch! */ }
+	},
+
+	// Displaying/hiding the widget
+
+	isVisible: function(){
+		return dojo.html.isVisible(this.domNode);
+	},
+	doToggle: function(){
+		this.isVisible() ? this.hide() : this.show();
+	},
+	show: function(){
+		this.showMe();
+	},
+	hide: function(){
+		this.hideMe();
+	}		
+});
+
+
+/**** 
+	Strategies for displaying/hiding widget
+*****/
+
+dojo.widget.HtmlWidget.Toggle={}
+
+dojo.widget.HtmlWidget.Toggle.Plain = {
+	showMe: function(){
+		dojo.html.show(this.domNode);
+	},
+
+	hideMe: function(){
+		dojo.html.hide(this.domNode);
+	}
+}
+
+dojo.widget.HtmlWidget.Toggle.Fade = {
+	showMe: function(){
+		dojo.fx.html.fadeShow(this.domNode, this.toggleDuration);
+	},
+
+	hideMe: function(){
+		dojo.fx.html.fadeHide(this.domNode, this.toggleDuration);
+	}
+}
+
+dojo.widget.HtmlWidget.Toggle.Wipe = {
+	showMe: function(){
+		dojo.fx.html.wipeIn(this.domNode, this.toggleDuration);
+	},
+
+	hideMe: function(){
+		dojo.fx.html.wipeOut(this.domNode, this.toggleDuration);
+	}
+}
+
+dojo.widget.HtmlWidget.Toggle.Explode = {
+	showMe: function(){
+		dojo.fx.html.explode(this.explodeSrc, this.domNode, this.toggleDuration);
+	},
+
+	hideMe: function(){
+		dojo.fx.html.implode(this.domNode, this.explodeSrc, this.toggleDuration);
+	}
+}

Added: portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/Manager.js
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/Manager.js?rev=354516&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/Manager.js (added)
+++ portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/Manager.js Tue Dec  6 11:29:56 2005
@@ -0,0 +1,254 @@
+dojo.provide("dojo.widget.Manager");
+dojo.require("dojo.lang");
+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);
+		// 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){
+		var tw = this.widgets[widgetIndex].widgetId;
+		delete this.widgetIds[tw];
+		this.widgets.splice(widgetIndex, 1);
+	}
+	
+	// FIXME: suboptimal performance
+	this.removeById = function(id) {
+		for (var i=0; i<this.widgets.length; i++){
+			if(this.widgets[i].widgetId == id){
+				this.remove(i);
+				break;
+			}
+		}
+	}
+
+	this.getWidgetById = function(id){
+		return this.widgetIds[id];
+	}
+
+	this.getWidgetsByType = function(type){
+		var lt = type.toLowerCase();
+		var ret = [];
+		dojo.lang.forEach(this.widgets, function(x){
+			if(x.widgetType.toLowerCase() == lt){
+				ret.push(x);
+			}
+		});
+		return ret;
+	}
+
+	this.getWidgetsOfType = function (id) {
+		dj_deprecated("getWidgetsOfType is depecrecated, use getWidgetsByType");
+		return dojo.widget.manager.getWidgetsByType(id);
+	}
+
+	this.getWidgetsByFilter = function(unaryFunc){
+		var ret = [];
+		dojo.lang.forEach(this.widgets, function(x){
+			if(unaryFunc(x)){
+				ret.push(x);
+			}
+		});
+		return ret;
+	}
+
+	this.getAllWidgets = function() {
+		return this.widgets.concat();
+	}
+
+	// shortcuts, baby
+	this.byId = this.getWidgetById;
+	this.byType = this.getWidgetsByType;
+	this.byFilter = this.getWidgetsByFilter;
+
+	// map of previousally discovered implementation names to constructors
+	var knownWidgetImplementations = {};
+
+	// support manually registered widget packages
+	var widgetPackages = ["dojo.widget", "dojo.webui.widgets"];
+	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){
+		// try and find a name for the widget
+		var impl = this.getImplementationName(widgetName);
+		if(impl){ 
+			// var tic = new Date();
+			var ret = new impl(ctorObject);
+			// dojo.debug(new Date() - tic);
+			return ret;
+		}
+	}
+
+	this.getImplementationName = function(widgetName){
+		/*
+		 * This is the overly-simplistic implemention of getImplementation (har
+		 * har). In the future, we are going to want something that allows more
+		 * freedom of expression WRT to specifying different specializations of
+		 * a widget.
+		 *
+		 * Additionally, this implementation treats widget names as case
+		 * insensitive, which does not necessarialy mesh with the markup which
+		 * can construct a widget.
+		 */
+
+		var lowerCaseWidgetName = widgetName.toLowerCase();
+
+		var impl = knownWidgetImplementations[lowerCaseWidgetName];
+		if(impl){
+			return impl;
+		}
+
+		// first store a list of the render prefixes we are capable of rendering
+		if(!renderPrefixCache.length){
+			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("");
+		}
+
+		// look for a rendering-context specific version of our widget name
+		for(var i = 0; i < widgetPackages.length; i++){
+			var widgetPackage = dojo.evalObjPath(widgetPackages[i]);
+			if(!widgetPackage) { continue; }
+
+			for (var j = 0; j < renderPrefixCache.length; j++) {
+				if (!widgetPackage[renderPrefixCache[j]]) { continue; }
+				for (var widgetClass in widgetPackage[renderPrefixCache[j]]) {
+					if (widgetClass.toLowerCase() != lowerCaseWidgetName) { continue; }
+					knownWidgetImplementations[lowerCaseWidgetName] =
+						widgetPackage[renderPrefixCache[j]][widgetClass];
+					return knownWidgetImplementations[lowerCaseWidgetName];
+				}
+			}
+
+			for (var j = 0; j < renderPrefixCache.length; j++) {
+				for (var widgetClass in widgetPackage) {
+					if (widgetClass.toLowerCase() !=
+						(renderPrefixCache[j] + lowerCaseWidgetName)) { continue; }
+	
+					knownWidgetImplementations[lowerCaseWidgetName] =
+						widgetPackage[widgetClass];
+					return knownWidgetImplementations[lowerCaseWidgetName];
+				}
+			}
+		}
+		
+		throw new Error('Could not locate "' + widgetName + '" class');
+	}
+
+	// FIXME: does it even belong in this name space?
+	// NOTE: this method is implemented by DomWidget.js since not all
+	// hostenv's would have an implementation.
+	/*this.getWidgetFromPrimitive = function(baseRenderType){
+		dj_unimplemented("dojo.widget.manager.getWidgetFromPrimitive");
+	}
+
+	this.getWidgetFromEvent = function(nativeEvt){
+		dj_unimplemented("dojo.widget.manager.getWidgetFromEvent");
+	}*/
+
+	// Catch window resize events and notify top level widgets
+	this.onResized = function() {
+		for(var id in this.topWidgets) {
+			var child = this.topWidgets[id];
+			//dojo.debug("root resizing child " + child.widgetId);
+			if ( child.onResized ) {
+				child.onResized();
+			}
+		}
+	}
+	if(typeof window != "undefined") {
+		dojo.addOnLoad(this, 'onResized');							// initial sizing
+		dojo.event.connect(window, 'onresize', this, 'onResized');	// window resize
+	}
+
+	// FIXME: what else?
+}
+
+// copy the methods from the default manager (this) to the widget namespace
+dojo.widget.getUniqueId = function () { return dojo.widget.manager.getUniqueId.apply(dojo.widget.manager, arguments); }
+dojo.widget.addWidget = function () { return dojo.widget.manager.add.apply(dojo.widget.manager, arguments); }
+dojo.widget.destroyAllWidgets = function () { return dojo.widget.manager.destroyAll.apply(dojo.widget.manager, arguments); }
+dojo.widget.removeWidget = function () { return dojo.widget.manager.remove.apply(dojo.widget.manager, arguments); }
+dojo.widget.removeWidgetById = function () { return dojo.widget.manager.removeById.apply(dojo.widget.manager, arguments); }
+dojo.widget.getWidgetById = function () { return dojo.widget.manager.getWidgetById.apply(dojo.widget.manager, arguments); }
+dojo.widget.getWidgetsByType = function () { return dojo.widget.manager.getWidgetsByType.apply(dojo.widget.manager, arguments); }
+dojo.widget.getWidgetsByFilter = function () { return dojo.widget.manager.getWidgetsByFilter.apply(dojo.widget.manager, arguments); }
+dojo.widget.byId = function () { return dojo.widget.manager.getWidgetById.apply(dojo.widget.manager, arguments); }
+dojo.widget.byType = function () { return dojo.widget.manager.getWidgetsByType.apply(dojo.widget.manager, arguments); }
+dojo.widget.byFilter = function () { return dojo.widget.manager.getWidgetsByFilter.apply(dojo.widget.manager, arguments); }
+dojo.widget.all = function () { return dojo.widget.manager.getAllWidgets.apply(dojo.widget.manager, arguments); }
+dojo.widget.registerWidgetPackage = function () { return dojo.widget.manager.registerWidgetPackage.apply(dojo.widget.manager, arguments); }
+dojo.widget.getWidgetImplementation = function () { return dojo.widget.manager.getImplementation.apply(dojo.widget.manager, arguments); }
+dojo.widget.getWidgetImplementationName = function () { return dojo.widget.manager.getImplementationName.apply(dojo.widget.manager, arguments); }
+
+dojo.widget.widgets = dojo.widget.manager.widgets;
+dojo.widget.widgetIds = dojo.widget.manager.widgetIds;
+dojo.widget.root = dojo.widget.manager.root;

Added: portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/Menu.js
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/Menu.js?rev=354516&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/Menu.js (added)
+++ portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/Menu.js Tue Dec  6 11:29:56 2005
@@ -0,0 +1,88 @@
+dojo.provide("dojo.widget.Menu");
+dojo.provide("dojo.widget.DomMenu");
+dojo.provide("dojo.widget.HtmlMenu");
+
+dojo.require("dojo.widget.Widget");
+dojo.require("dojo.widget.DomWidget");
+dojo.require("dojo.widget.HtmlWidget");
+
+
+dojo.widget.tags.addParseTreeHandler("dojo:menu");
+
+/* Menu
+ *******/
+
+dojo.widget.Menu = function () {
+	dojo.widget.Menu.superclass.constructor.call(this);
+}
+dojo.inherits(dojo.widget.Menu, dojo.widget.Widget);
+
+dojo.lang.extend(dojo.widget.Menu, {
+	widgetType: "Menu",
+	isContainer: true,
+	
+	items: [],
+	push: function(item){
+		dojo.connect.event(item, "onSelect", this, "onSelect");
+		this.items.push(item);
+	},
+	onSelect: function(){}
+});
+
+
+/* DomMenu
+ **********/
+
+dojo.widget.DomMenu = function(){
+	dojo.widget.DomMenu.superclass.constructor.call(this);
+}
+dojo.inherits(dojo.widget.DomMenu, dojo.widget.DomWidget);
+
+dojo.lang.extend(dojo.widget.DomMenu, {
+	widgetType: "Menu",
+	isContainer: true,
+
+	push: function (item) {
+		dojo.widget.Menu.call(this, item);
+		this.domNode.appendChild(item.domNode);
+	}
+});
+
+
+/* HtmlMenu
+ ***********/
+ 
+dojo.widget.HtmlMenu = function(){
+	dojo.widget.HtmlMenu.superclass.constructor.call(this);
+	this.items = [];
+}
+dojo.inherits(dojo.widget.HtmlMenu, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.HtmlMenu, {
+	widgetType: "Menu",
+	isContainer: true,
+
+	// copy children widgets output directly to parent (this node), to avoid
+	// errors trying to insert an <li> under a <div>
+	snarfChildDomOutput: true,
+
+	templateString: '<ul></ul>',
+	templateCssPath: dojo.uri.dojoUri("src/widget/templates/Menu.css"),
+	
+	fillInTemplate: function (args, frag){
+		//dojo.widget.HtmlMenu.superclass.fillInTemplate.apply(this, arguments);
+		this.domNode.className = "dojoMenu";
+	},
+	
+ 
+	_register: function (item ) {
+		dojo.event.connect(item, "onSelect", this, "onSelect");
+		this.items.push(item);
+	},
+
+	push: function (item) {
+		this.domNode.appendChild(item.domNode);
+		this._register(item);
+	}
+
+});

Added: portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/MenuItem.js
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/MenuItem.js?rev=354516&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/MenuItem.js (added)
+++ portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/MenuItem.js Tue Dec  6 11:29:56 2005
@@ -0,0 +1,85 @@
+dojo.provide("dojo.widget.MenuItem");
+dojo.provide("dojo.widget.DomMenuItem");
+dojo.provide("dojo.widget.HtmlMenuItem");
+
+dojo.require("dojo.string");
+dojo.require("dojo.widget.Widget");
+dojo.require("dojo.widget.DomWidget");
+dojo.require("dojo.widget.HtmlWidget");
+
+dojo.require("dojo.html");
+
+dojo.widget.tags.addParseTreeHandler("dojo:MenuItem");
+
+/* MenuItem
+ ***********/
+ 
+dojo.widget.MenuItem = function(){
+	dojo.widget.MenuItem.superclass.constructor.call(this);
+}
+dojo.inherits(dojo.widget.MenuItem, dojo.widget.Widget);
+
+dojo.lang.extend(dojo.widget.MenuItem, {
+	widgetType: "MenuItem",
+	isContainer: true
+});
+
+
+/* DomMenuItem
+ **************/
+dojo.widget.DomMenuItem = function(){
+	dojo.widget.DomMenuItem.superclass.constructor.call(this);
+}
+dojo.inherits(dojo.widget.DomMenuItem, dojo.widget.DomWidget);
+
+dojo.lang.extend(dojo.widget.DomMenuItem, {
+	widgetType: "MenuItem"
+});
+
+/* HtmlMenuItem
+ ***************/
+
+dojo.widget.HtmlMenuItem = function(){
+	dojo.widget.HtmlWidget.call(this);
+}
+dojo.inherits(dojo.widget.HtmlMenuItem, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.HtmlMenuItem, {
+	widgetType: "MenuItem",
+	templateString: '<li class="dojoMenuItem" dojoAttachEvent="onMouseOver; onMouseOut; onMouseDown; onMouseUp; onClick;"></li>',
+	title: "",
+
+	fillInTemplate: function(args, frag){
+		dojo.html.disableSelection(this.domNode);
+
+		if(!dojo.string.isBlank(this.title)){
+			this.domNode.appendChild(document.createTextNode(this.title));
+		}else{
+			this.domNode.appendChild(frag["dojo:"+this.widgetType.toLowerCase()]["nodeRef"]);
+		}
+	},
+	
+	onMouseOver: function(e){
+		dojo.html.addClass(this.domNode, "dojoMenuItemHover");
+	},
+	
+	onMouseOut: function(e){
+		dojo.html.removeClass(this.domNode, "dojoMenuItemHover");
+	},
+	
+	onClick: function(e){ this.onSelect(this, e); },
+	onMouseDown: function(e){},
+	onMouseUp: function(e){},
+	
+	// By default, when I am clicked, click the item inside of me
+	onSelect: function (item, e) {
+		var child = dojo.dom.getFirstChildElement(this.domNode);
+		if(child){
+			if(child.click){
+				child.click();
+			}else if(child.href){
+				location.href = child.href;
+			}
+		}
+	}
+});

Added: portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/Parse.js
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/Parse.js?rev=354516&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/Parse.js (added)
+++ portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/Parse.js Tue Dec  6 11:29:56 2005
@@ -0,0 +1,312 @@
+dojo.provide("dojo.widget.Parse");
+
+dojo.require("dojo.widget.Manager");
+dojo.require("dojo.string");
+dojo.require("dojo.dom");
+
+dojo.widget.Parse = function(fragment) {
+	this.propertySetsList = [];
+	this.fragment = fragment;
+
+	/*	createComponents recurses over a raw JavaScript object structure,
+			and calls the corresponding handler for its normalized tagName if it exists
+	*/
+	this.createComponents = function(fragment, parentComp){
+		var djTags = dojo.widget.tags;
+		var returnValue = [];
+		// this allows us to parse without having to include the parent
+		// it is commented out as it currently breaks the existing mechanism for
+		// adding widgets programmatically.  Once that is fixed, this can be used
+		/*if( (fragment["tagName"])&&
+			(fragment != fragment["nodeRef"])){
+			var tn = new String(fragment["tagName"]);
+			// we split so that you can declare multiple
+			// non-destructive widgets from the same ctor node
+			var tna = tn.split(";");
+			for(var x=0; x<tna.length; x++){
+				var ltn = dojo.text.trim(tna[x]).toLowerCase();
+				if(djTags[ltn]){
+					fragment.tagName = ltn;
+					returnValue.push(djTags[ltn](fragment, this, parentComp, count++));
+				}else{
+					if(ltn.substr(0, 5)=="dojo:"){
+						dj_debug("no tag handler registed for type: ", ltn);
+					}
+				}
+			}
+		}*/
+		for(var item in fragment){
+			var built = false;
+			// if we have items to parse/create at this level, do it!
+			try{
+				if( fragment[item] && (fragment[item]["tagName"])&&
+					(fragment[item] != fragment["nodeRef"])){
+					var tn = new String(fragment[item]["tagName"]);
+					// we split so that you can declare multiple
+					// non-destructive widgets from the same ctor node
+					var tna = tn.split(";");
+					for(var x=0; x<tna.length; x++){
+						var ltn = dojo.string.trim(tna[x]).toLowerCase();
+						if(djTags[ltn]){
+							built = true;
+							// var tic = new Date();
+							fragment[item].tagName = ltn;
+							returnValue.push(djTags[ltn](fragment[item], this, parentComp, fragment[item]["index"]));
+						}else{
+							if(ltn.substr(0, 5)=="dojo:"){
+								dojo.debug("no tag handler registed for type: ", ltn);
+							}
+						}
+					}
+				}
+			}catch(e){
+				dojo.debug(e);
+				// throw(e);
+				// IE is such a bitch sometimes
+			}
+
+			// if there's a sub-frag, build widgets from that too
+			if( (!built) && (typeof fragment[item] == "object")&&
+				(fragment[item] != fragment.nodeRef)&&
+				(fragment[item] != fragment["tagName"])){
+				returnValue.push(this.createComponents(fragment[item], parentComp));
+			}
+		}
+		return returnValue;
+	}
+
+	/*  parsePropertySets checks the top level of a raw JavaScript object
+			structure for any propertySets.  It stores an array of references to 
+			propertySets that it finds.
+	*/
+	this.parsePropertySets = function(fragment) {
+		return [];
+		var propertySets = [];
+		for(var item in fragment){
+			if(	(fragment[item]["tagName"] == "dojo:propertyset") ) {
+				propertySets.push(fragment[item]);
+			}
+		}
+		// FIXME: should we store these propertySets somewhere for later retrieval
+		this.propertySetsList.push(propertySets);
+		return propertySets;
+	}
+	
+	/*  parseProperties checks a raw JavaScript object structure for
+			properties, and returns an array of properties that it finds.
+	*/
+	this.parseProperties = function(fragment) {
+		var properties = {};
+		for(var item in fragment){
+			// FIXME: need to check for undefined?
+			// case: its a tagName or nodeRef
+			if((fragment[item] == fragment["tagName"])||
+				(fragment[item] == fragment.nodeRef)){
+				// do nothing
+			}else{
+				if((fragment[item]["tagName"])&&
+					(dojo.widget.tags[fragment[item].tagName.toLowerCase()])){
+					// TODO: it isn't a property or property set, it's a fragment, 
+					// so do something else
+					// FIXME: needs to be a better/stricter check
+					// TODO: handle xlink:href for external property sets
+				}else if((fragment[item][0])&&(fragment[item][0].value!="")){
+					try{
+						// FIXME: need to allow more than one provider
+						if(item.toLowerCase() == "dataprovider") {
+							var _this = this;
+							this.getDataProvider(_this, fragment[item][0].value);
+							properties.dataProvider = this.dataProvider;
+						}
+						properties[item] = fragment[item][0].value;
+						var nestedProperties = this.parseProperties(fragment[item]);
+						// FIXME: this kind of copying is expensive and inefficient!
+						for(var property in nestedProperties){
+							properties[property] = nestedProperties[property];
+						}
+					}catch(e){ dj_debug(e); }
+				}
+			}
+		}
+		return properties;
+	}
+
+	/* getPropertySetById returns the propertySet that matches the provided id
+	*/
+	
+	this.getDataProvider = function(objRef, dataUrl) {
+		// FIXME: this is currently sync.  To make this async, we made need to move 
+		//this step into the widget ctor, so that it is loaded when it is needed 
+		// to populate the widget
+		dojo.io.bind({
+			url: dataUrl,
+			load: function(type, evaldObj){
+				if(type=="load"){
+					objRef.dataProvider = evaldObj;
+				}
+			},
+			mimetype: "text/javascript",
+			sync: true
+		});
+	}
+
+	
+	this.getPropertySetById = function(propertySetId){
+		for(var x = 0; x < this.propertySetsList.length; x++){
+			if(propertySetId == this.propertySetsList[x]["id"][0].value){
+				return this.propertySetsList[x];
+			}
+		}
+		return "";
+	}
+	
+	/* getPropertySetsByType returns the propertySet(s) that match(es) the
+	 * provided componentClass
+	 */
+	this.getPropertySetsByType = function(componentType){
+		var propertySets = [];
+		for(var x=0; x < this.propertySetsList.length; x++){
+			var cpl = this.propertySetsList[x];
+			var cpcc = cpl["componentClass"]||cpl["componentType"]||null;
+			if((cpcc)&&(propertySetId == cpcc[0].value)){
+				propertySets.push(cpl);
+			}
+		}
+		return propertySets;
+	}
+	
+	/* getPropertySets returns the propertySet for a given component fragment
+	*/
+	this.getPropertySets = function(fragment){
+		var ppl = "dojo:propertyproviderlist";
+		var propertySets = [];
+		var tagname = fragment["tagName"];
+		if(fragment[ppl]){ 
+			var propertyProviderIds = fragment[ppl].value.split(" ");
+			// FIXME: should the propertyProviderList attribute contain #
+			// 		  syntax for reference to ids or not?
+			// FIXME: need a better test to see if this is local or external
+			// FIXME: doesn't handle nested propertySets, or propertySets that
+			// 		  just contain information about css documents, etc.
+			for(propertySetId in propertyProviderIds){
+				if((propertySetId.indexOf("..")==-1)&&(propertySetId.indexOf("://")==-1)){
+					// get a reference to a propertySet within the current parsed structure
+					var propertySet = this.getPropertySetById(propertySetId);
+					if(propertySet != ""){
+						propertySets.push(propertySet);
+					}
+				}else{
+					// FIXME: add code to parse and return a propertySet from
+					// another document
+					// alex: is this even necessaray? Do we care? If so, why?
+				}
+			}
+		}
+		// we put the typed ones first so that the parsed ones override when
+		// iteration happens.
+		return (this.getPropertySetsByType(tagname)).concat(propertySets);
+	}
+	
+	/* 
+		nodeRef is the node to be replaced... in the future, we might want to add 
+		an alternative way to specify an insertion point
+
+		componentName is the expected dojo widget name, i.e. Button of ContextMenu
+
+		properties is an object of name value pairs
+	*/
+	this.createComponentFromScript = function(nodeRef, componentName, properties, fastMixIn){
+		var frag = {};
+		var tagName = "dojo:" + componentName.toLowerCase();
+		frag[tagName] = {};
+		var bo = {};
+		properties.dojotype = componentName;
+		for(var prop in properties){
+			if(typeof bo[prop] == "undefined"){
+				frag[tagName][prop] = [{value: properties[prop]}];
+			}
+		}
+		frag[tagName].nodeRef = nodeRef;
+		frag.tagName = tagName;
+		var fragContainer = [frag];
+		if(fastMixIn){
+			fragContainer[0].fastMixIn = true;
+		}
+		// FIXME: should this really return an array?
+		return this.createComponents(fragContainer);
+	}
+}
+
+
+dojo.widget._parser_collection = {"dojo": new dojo.widget.Parse() };
+dojo.widget.getParser = function(name){
+	if(!name){ name = "dojo"; }
+	if(!this._parser_collection[name]){
+		this._parser_collection[name] = new dojo.widget.Parse();
+	}
+	return this._parser_collection[name];
+}
+
+/**
+ * Creates widget.
+ *
+ * @param name     The name of the widget to create
+ * @param props    Key-Value pairs of properties of the widget
+ * @param refNode  If the last argument is specified this node is used as
+ *                 a reference for inserting this node into a DOM tree else
+ *                 it beomces the domNode
+ * @param position The position to insert this widget's node relative to the
+ *                 refNode argument
+ * @return The new Widget object
+ */
+ dojo.widget.fromScript = function(name, props, refNode, position){
+	if(	(typeof name != "string")&&
+		(typeof props == "string")){
+		// we got called with the old function signature, so just pass it on through
+		// use full deref in case we're called from an alias
+		return dojo.widget._oldFromScript(name, props, refNode);
+	}
+	/// otherwise, we just need to keep working a bit...
+	props = props||{};
+	var notRef = false;
+	var tn = null;
+	var h = dojo.render.html.capable;
+	if(h){
+		tn = document.createElement("span");
+	}
+	if(!refNode){
+		notRef = true;
+		refNode = tn;
+		if(h){
+			dojo.html.body().appendChild(refNode);
+		}
+	}else if(position){
+		dojo.dom.insertAtPosition(tn, refNode, position);
+	}else{ // otherwise don't replace, but build in-place
+		tn = refNode;
+	}
+	var widgetArray = dojo.widget._oldFromScript(tn, name, props);
+	if (!widgetArray[0] || typeof widgetArray[0].widgetType == "undefined") {
+		throw new Error("Creation of \"" + name + "\" widget fromScript failed.");
+	}
+	if (notRef) {
+		if (widgetArray[0].domNode.parentNode) {
+			widgetArray[0].domNode.parentNode.removeChild(widgetArray[0].domNode);
+		}
+	}
+	return widgetArray[0]; // not sure what the array wrapper is for, but just return the widget
+}
+
+dojo.widget._oldFromScript = function(placeKeeperNode, name, props){
+	var ln = name.toLowerCase();
+	var tn = "dojo:"+ln;
+	props[tn] = { 
+		dojotype: [{value: ln}],
+		nodeRef: placeKeeperNode,
+		fastMixIn: true
+	};
+	var ret = dojo.widget.getParser().createComponentFromScript(placeKeeperNode, name, props, true);
+	return ret;
+}
+
+

Added: portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/PopUpButton.js
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/PopUpButton.js?rev=354516&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/PopUpButton.js (added)
+++ portals/jetspeed-2/trunk/applications/j2-admin/src/webapp/dojo/src/widget/PopUpButton.js Tue Dec  6 11:29:56 2005
@@ -0,0 +1,180 @@
+dojo.provide("dojo.widget.PopUpButton");
+dojo.provide("dojo.widget.DomPopUpButton");
+dojo.provide("dojo.widget.HtmlPopUpButton");
+
+//dojo.require("dojo.widget.Button");
+//dojo.require("dojo.widget.HtmlButton");
+
+dojo.require("dojo.widget.Menu");
+dojo.require("dojo.widget.MenuItem");
+
+dojo.require("dojo.html");
+
+dojo.widget.tags.addParseTreeHandler("dojo:PopUpButton");
+
+/* PopUpButton
+ **************/
+ 
+dojo.widget.PopUpButton = function () {
+	dojo.widget.PopUpButton.superclass.constructor.call(this);
+}
+dojo.inherits(dojo.widget.PopUpButton, dojo.widget.Widget);
+
+dojo.lang.extend(dojo.widget.PopUpButton, {
+	widgetType: "PopUpButton",
+	
+	label: ""
+});
+
+
+/* DomPopUpButton
+ *****************/
+dojo.widget.DomPopUpButton = function(){
+	dojo.widget.DomPopUpButton.superclass.constructor.call(this);
+}
+dojo.inherits(dojo.widget.DomPopUpButton, dojo.widget.DomWidget);
+
+dojo.lang.extend(dojo.widget.DomPopUpButton, {
+	widgetType: dojo.widget.PopUpButton.prototype.widgetType
+});
+
+
+/* HtmlPopUpButton
+ ******************/
+
+dojo.widget.HtmlPopUpButton = function () {
+	dojo.widget.HtmlPopUpButton.superclass.constructor.call(this);
+}
+dojo.inherits(dojo.widget.HtmlPopUpButton, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.HtmlPopUpButton, {
+	widgetType: dojo.widget.PopUpButton.prototype.widgetType,
+	templateString: null,
+	templateCssPath: dojo.uri.dojoUri("src/widget/templates/PopUpButton.css"),
+	
+	buildRendering: function (args, frag) {
+		dojo.html.insertCssFile(this.templateCssPath, null, true);
+	
+		this.domNode = document.createElement("a");
+		this.domNode.className = "PopUpButton";
+		dojo.event.connect(this.domNode, "onmousedown", this, "onMouseDown");
+		
+		// draw the arrow
+		var arrow = document.createElement("img");
+		arrow.src = dojo.uri.dojoUri("src/widget/templates/images/dropdownButtonsArrow.gif");
+		dojo.html.setClass(arrow, "downArrow");
+		this.domNode.appendChild(arrow);
+
+		this.menu = dojo.widget.fromScript("Menu");
+		dojo.html.addClass(this.menu.domNode, "PopUpButtonMenu");
+		dojo.event.connect(this.menu, "onSelect", this, "onSelect");
+		
+		if (frag["dojo:" + this.widgetType.toLowerCase()].nodeRef) {
+			var node = frag["dojo:" + this.widgetType.toLowerCase()].nodeRef;
+			var options = node.getElementsByTagName("option");
+			for (var i = 0; i < options.length; i++) {
+				var properties = {
+					title: dojo.dom.textContent(options[i]),
+					value: options[i].value
+				}
+				this.addItem(dojo.widget.fromScript("MenuItem", properties));
+			}
+		}
+	},
+
+	addItem: function (item) {
+		// TODO: should be dojo.widget.MenuItem
+		if (item instanceof dojo.widget.HtmlMenuItem) {
+			this.menu.push(item);
+		} else {
+			// TODO: create one
+			var menuItem = dojo.widget.fromScript("MenuItem", {title: item});
+			this.menu.push(menuItem);
+		}
+	},
+	
+	
+/* Enabled utility methods
+ **************************/
+	
+	_enabled: true,
+	
+	isEnabled: function() { return this._enabled; },
+	
+	setEnabled: function(enabled, force, preventEvent) {
+		enabled = Boolean(enabled);
+		if (force || this._enabled != enabled) {
+			this._enabled = enabled;
+			if (!preventEvent) {
+				this._fireEvent(this._enabled ? "onEnable" : "onDisable");
+				this._fireEvent("onChangeEnabled");
+			}
+		}
+		
+		dojo.html[(this._enabled ? "add" : "remove")
+			+ "Class"](this.domNode, "disabled");
+		
+		return this._enabled;
+	},
+	
+	enable: function(force, preventEvent) {
+		return this.setEnabled(true, force, preventEvent);
+	},
+	
+	disable: function(force, preventEvent) {
+		return this.setEnabled(false, force, preventEvent);
+	},
+	
+	toggleEnabled: function(force, preventEvent) {
+		return this.setEnabled(!this._enabled, force, preventEvent);
+	},
+
+
+/* Select utility methods
+ **************************/
+
+	onSelect: function (item, e) {
+		this.domNode.firstChild.nodeValue = item.title;
+	},
+	
+	onMouseDown: function (e) {
+		if (!this._menuVisible) {
+			this._showMenu(e);
+			dojo.lang.setTimeout(dojo.event.connect, 1, document, "onmousedown", this, "_hideMenu");
+		}
+	},
+	
+	
+	_fireEvent: function(evt) {
+		if(typeof this[evt] == "function") {
+			var args = [this];
+			for(var i = 1; i < arguments.length; i++) {
+				args.push(arguments[i]);
+			}
+			this[evt].apply(this, args);
+		}
+	},
+
+	
+	_showMenu: function (e) {
+		if (!this._enabled) { return; }
+		this._menuVisible = true;
+		with (dojo.html) {
+			var y = getAbsoluteY(this.domNode) + getInnerHeight(this.domNode);
+			var x = getAbsoluteX(this.domNode);
+		}
+	
+		dojo.html.body().appendChild(this.menu.domNode);
+		with (this.menu.domNode.style) {
+			top = y + "px";
+			left = x + "px";
+		}
+	},
+	
+	_hideMenu: function (e) {
+		this.menu.domNode.parentNode.removeChild(this.menu.domNode);
+		dojo.event.disconnect(document, "onmousedown", this, "_hideMenu");
+		this._menuVisible = false;
+	}
+
+});



---------------------------------------------------------------------
To unsubscribe, e-mail: jetspeed-dev-unsubscribe@portals.apache.org
For additional commands, e-mail: jetspeed-dev-help@portals.apache.org