You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xap-commits@incubator.apache.org by mt...@apache.org on 2006/08/21 16:07:09 UTC

svn commit: r433271 [2/2] - /incubator/xap/trunk/dist/zimbra.js

Modified: incubator/xap/trunk/dist/zimbra.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/dist/zimbra.js?rev=433271&r1=433270&r2=433271&view=diff
==============================================================================
--- incubator/xap/trunk/dist/zimbra.js (original)
+++ incubator/xap/trunk/dist/zimbra.js Mon Aug 21 09:07:06 2006
@@ -1,4 +1,4 @@
-/**** Autoinclude function file:./zimbra/js/msgs/AjxMsg.js****/
+/** auto include file:./zimbra/js/msgs/AjxMsg.js **/
 function launch() {
 	// DBG = new AjxDebug( AjxDebug.NONE, null, false );
 }
@@ -338,7 +338,7 @@
 /* Global ELEMENT declarations */
 
 function ExMsg() {}
-/**** Autoinclude function file:./zimbra/js/core/AjxEnv.js****/
+/** auto include file:./zimbra/js/core/AjxEnv.js **/
 /*
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
@@ -557,7 +557,7 @@
 		};
 	}
 }
-/**** Autoinclude function file:./zimbra/js/util/AjxUtil.js****/
+/** auto include file:./zimbra/js/util/AjxUtil.js **/
 /*
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
@@ -1031,7 +1031,7 @@
 			newList.push(list[i]);
 	return newList;
 };
-/**** Autoinclude function file:./zimbra/js/core/AjxCore.js****/
+/** auto include file:./zimbra/js/core/AjxCore.js **/
 /*
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
@@ -1251,7 +1251,7 @@
 
 	AjxCore.addListener(window, "onunload", action);
 };
-/**** Autoinclude function file:./zimbra/js/soap/AjxSoapFault.js****/
+/** auto include file:./zimbra/js/soap/AjxSoapFault.js **/
 /*
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
@@ -1328,7 +1328,7 @@
 AjxSoapFault.MUST_UNDERSTAND = -4;
 AjxSoapFault.DATA_ENCODING_UNKNOWN = -5;
 AjxSoapFault.UNKNOWN = -6;
-/**** Autoinclude function file:./zimbra/js/util/AjxCookie.js****/
+/** auto include file:./zimbra/js/util/AjxCookie.js **/
 /*
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
@@ -1400,49 +1400,7 @@
 	((path) ? "; path=" + path : "") +
 	((domain) ? "; domain=" + domain : "") + "; expires=Fri, 31 Dec 1999 23:59:59 GMT";
 }
-/**** Autoinclude function file:./zimbra/js/soap/AjxSoapException.js****/
-/*
-* ***** BEGIN LICENSE BLOCK *****
-* Version: MPL 1.1
-*
-* The contents of this file are subject to the Mozilla Public
-* License Version 1.1 ("License"); you may not use this file except in
-* compliance with the License. You may obtain a copy of the License at
-* http://www.zimbra.com/license
-*
-* Software distributed under the License is distributed on an "AS IS"
-* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-* the License for the specific language governing rights and limitations
-* under the License.
-*
-* The Original Code is: Zimbra AJAX Toolkit.
-*
-* The Initial Developer of the Original Code is Zimbra, Inc.
-* Portions created by Zimbra are Copyright (C) 2005 Zimbra, Inc.
-* All Rights Reserved.
-*
-* Contributor(s):
-*
-* ***** END LICENSE BLOCK *****
-*/
-
-
-function AjxSoapException(msg, code, method, detail) {
-	AjxException.call(this, msg, code, method, detail);
-}
-
-AjxSoapException.prototype.toString = 
-function() {
-	return "AjxSoapException";
-}
-
-AjxSoapException.prototype = new AjxException;
-AjxSoapException.prototype.constructor = AjxSoapException;
-
-AjxSoapException.INTERNAL_ERROR 	= "INTERNAL_ERROR";
-AjxSoapException.INVALID_PDU 		= "INVALID_PDU";
-AjxSoapException.ELEMENT_EXISTS 	= "ELEMENT_EXISTS";
-/**** Autoinclude function file:./zimbra/js/util/AjxCallback.js****/
+/** auto include file:./zimbra/js/debug/AjxDebug.js **/
 /*
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
@@ -1470,782 +1428,885 @@
 
 
 /**
-* Creates a callback which consists of at least a function reference, and possibly also
-* an object to call it from.
+* Creates a new debug window. The document inside is not kept open.  All the 
+  output goes into a single <div> element.
 * @constructor
 * @class
-* This class represents a callback function which can be called standalone, or from a
-* given object. What the callback takes as arguments and what it returns are left to the
-* client.
+* This class pops up a debug window and provides functions to send output there 
+* in various ways. The output is continuously appended to the bottom of the 
+* window. The document is left unopened so that the browser doesn't think it's 
+* continuously loading and keep its little icon flailing forever. Also, the DOM 
+* tree can't be manipulated on an open document. All the output is added to the 
+* window by appending it the DOM tree. Another method of appending output is to 
+* open the document and use document.write(), but then the document is left open.
+* <p>
+* Any client that uses this class can turn off debugging by changing the first 
+* argument to the constructor to AjxDebug.NONE.
 *
 * @author Conrad Damon
-* @param obj	[Object]				the object to call the function from
-* @param func	[function]				the callback function
-* @param args   [primitive or Array]	default arguments
+* @author Ross Dargahi
+* @param level	 	debug level for the current debugger (no window will be displayed for a level of NONE)
+* @param name 		the name of the window. Defaults to "debug_" prepended to the calling window's URL.
+* @param showTime	a boolean that toggles the display of timestamps before debug messages
 */
-function AjxCallback(obj, func, args) {
-	if (arguments.length == 0) return;
+function AjxDebug(level, name, showTime) {
+	this._dbgName = "AjxDebugWin_" + location.hostname.replace(/\./g,'_');
+	this._level = level;
+	this._showTime = showTime;
+	this._enabled = (this._level != AjxDebug.NONE);
+	this._showTiming = false;
+	this._startTimePt = this._lastTimePt = 0;
+	this._dbgWindowInited = false;
 
-	this.obj = obj;
-	this.func = func;
-	this.args = args;
-}
+	this._msgQueue = new Array();
+	AjxDebug._CONTENT_FRAME_ID = AjxDebug._CONTENT_FRAME_ID;
+	this._isPrevWinOpen = false;
+	if (!this._enabled) return;
 
-AjxCallback.prototype.toString =
+	this._openDebugWindow();
+};
+
+
+AjxDebug.NONE = "DBG0"; // no debugging (window will not come up)
+AjxDebug.DBG1 = "DBG1"; // minimal debugging
+AjxDebug.DBG2 = "DBG2"; // moderate debugging
+AjxDebug.DBG3 = "DBG3"; // anything goes
+AjxDebug.PERF = "PERF"; // performance timings
+
+// map from number to debug level
+AjxDebug.DBG = new Object();
+AjxDebug.DBG[-1] = AjxDebug.PERF;
+AjxDebug.DBG[0] = AjxDebug.NONE;
+AjxDebug.DBG[1] = AjxDebug.DBG1;
+AjxDebug.DBG[2] = AjxDebug.DBG2;
+AjxDebug.DBG[3] = AjxDebug.DBG3;
+
+// map from debug level to number
+AjxDebug.GBD = {};
+AjxDebug.GBD[AjxDebug.PERF] = -1;
+AjxDebug.GBD[AjxDebug.NONE] = 0;
+AjxDebug.GBD[AjxDebug.DBG1] = 1;
+AjxDebug.GBD[AjxDebug.DBG2] = 2;
+AjxDebug.GBD[AjxDebug.DBG3] = 3;
+
+AjxDebug.MAX_OUT = 25000; // max length capable of outputting
+
+AjxDebug._LINK_FRAME_ID = "AjxDebug_LF";
+AjxDebug._CONTENT_FRAME_ID = "AjxDebug_CF";
+AjxDebug._BUTTON_FRAME_ID = "AjxDebug_BF";
+
+AjxDebug._id = 0;
+AjxDebug._openErrors = 0;
+
+AjxDebug.prototype.toString = 
 function() {
-	return "AjxCallback";
+	return "AjxDebug";
 }
 
 /**
-* Runs the callback function, from within the object if there is one. The
-* called function passed arguments are the concatenation of the argument
-* array passed to this object's constructor and the argument array passed
-* to the <code>run</code> method. Whatever the called function returns is
-* returned to the caller.
+* Set debug level. May open or close the debug window if moving to or from level NONE.
 *
-* @param arg1	The first argument which will be appended to the argument
-*				array passed to this object's constructor. Any number of
-*				arguments may be passed to the <code>run</code> method.
+* @param level	 	debug level for the current debugger
 */
-AjxCallback.prototype.run =
-function(/* arg1 ... argN */) {
-	// combine original args with new ones
-	var args = [];
+AjxDebug.prototype.setDebugLevel = 
+function(level) {
+	if (level == this._level) return;
 
-	// sometimes we want to pass a null or false argument, so simply
-	// checking for if (this.args) won't do.
-	if (typeof this.args != "undefined") {
-		if (this.args instanceof Array)
-			// NOTE: We must NOT use this.args directly if this method's
-			//       params are gonna be pushed onto the array because it
-			//       will change the original args!
-			args = arguments.length > 0 ? args.concat(this.args) : this.args;
-		else
-			args.push(this.args);
+	this._level = level;
+	if (level == AjxDebug.NONE) {
+		this._enabled = false;
+		this._debugWindow.close();
+		this._debugWindow = null;
+	} else {
+		this._enabled = true;
+		if (this._debugWindow == null || this._debugWindow.closed)
+			this._openDebugWindow();
 	}
+};
 
-	for (var i = 0; i < arguments.length; ++i)
-		args.push(arguments[i]);
+AjxDebug.prototype.getDebugLevel = 
+function(level) {
+	return this._level;
+};
 
-	// invoke function
-	return this.func.apply(this.obj || window, args);
+AjxDebug.prototype.isShowTiming = 
+function() {
+	return this._showTiming;
 };
 
 /**
- * The following function is what an AjxCallback should be *all* about.  It
- * returns a plain function that will call your supplied "func" in the context
- * of "obj" and pass to it, in this order, any additional arguments that you
- * pass to simpleClosure and the arguments that were passed to it at the call
- * time.
- *
- * An example should do:
- *
- *   div.onclick = AjxCallback.simpleClosure(this.handler, this, "some data");
- *   ...
- *   this.handler = function(data, event) {
- *      // event will be passed for DOM2 compliant browsers
- *      // and data is "some data"
- *   };
- *
- * [this is one of the most useful functions I ever wrote :D  -mihai@zimbra.com]
- */
-AjxCallback.simpleClosure = function(func, obj) {
-	var args = [];
-	for (var i = 2; i < arguments.length; ++i)
-		args.push(arguments[i]);
-	return function() {
-		var args2 = [];
-		for (var i = 0; i < arguments.length; ++i)
-			args2.push(arguments[i]);
-		func.apply(obj || this, args.concat(args2));
-	};
-};
-/**** Autoinclude function file:./zimbra/js/util/AjxSelectionManager.js****/
-/*
-* ***** BEGIN LICENSE BLOCK *****
-* Version: MPL 1.1
-*
-* The contents of this file are subject to the Mozilla Public
-* License Version 1.1 ("License"); you may not use this file except in
-* compliance with the License. You may obtain a copy of the License at
-* http://www.zimbra.com/license
-*
-* Software distributed under the License is distributed on an "AS IS"
-* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-* the License for the specific language governing rights and limitations
-* under the License.
-*
-* The Original Code is: Zimbra AJAX Toolkit.
-*
-* The Initial Developer of the Original Code is Zimbra, Inc.
-* Portions created by Zimbra are Copyright (C) 2005 Zimbra, Inc.
-* All Rights Reserved.
-*
-* Contributor(s):
+* Turn the display of timing statements on/off. Timing starts over any time it's turned on.
 *
-* ***** END LICENSE BLOCK *****
+* @param on		whether to display timing statements
 */
+AjxDebug.prototype.showTiming = 
+function(on, level, msg) {
+	this._showTiming = on;
 
+	if (on) {
+		this._startTimePt = this._lastTimePt = 0;
 
-/**
- * This requires an "owner" which is the object that owns the full set of items, implmenting:
- * getItemCount() to return the number of items
- * getItem(index) to return the item at a given index.
- * 
- * And optionally implementing
- * itemSelectionChanged(item, index, isSelected) which is called
- *         for each item that is selected or deselected
- * selectionChanged() which is called after a batch of items have
- *         been selected or deselected with select()
- *
- */
-	
-AjxSelectionManager = function(anOwner) {
-	this._owner = anOwner;
-};
+		var a = [];
+		for (var i = 1; i < arguments.length; i++)
+			a.push(arguments[i]);
 
-// -----------------------------------------------------------
-// Constants
-// -----------------------------------------------------------
+		var args = this._handleArgs(a);
+		if (args) {
+			var msgLevel = AjxDebug.DBG1;
+			if (String(level).match(/^DBG|PERF/))
+				msgLevel = level;
 
-// Actions for select()
-AjxSelectionManager.SELECT_ONE_CLEAR_OTHERS = 0;
-AjxSelectionManager.TOGGLE_ONE_LEAVE_OTHERS = 1;
-AjxSelectionManager.SELECT_TO_ANCHOR = 2;
-AjxSelectionManager.DESELECT_ALL = 3;
-AjxSelectionManager.SELECT_ALL = 4;
-
-// -----------------------------------------------------------
-// API Methods
-// -----------------------------------------------------------
-
-/**
- * returns an AjxVector
- */
-AjxSelectionManager.prototype.getItems = function() {
-	if (this._selectedItems == null) {
-		this._selectedItems = this._createItemsCollection();
+			this.println(msgLevel, " ----- " + args[0] + " ----- ");
+		}
 	}
-	return this._selectedItems;
+	this._startTimePt = this._lastTimePt = new Date().getTime();
 };
 
 /**
- * returns the number of selected items
- */	
-AjxSelectionManager.prototype.getLength = function() {
-	return this.getItems().length;
-};
-	
-/**
- * returns the anchor, unless nothing is selected
- */
-AjxSelectionManager.prototype.getAnchor = function() {
-	if (this._anchor == null) {
-		var items = this.getItems();
-		if (items.length > 0) {
-			this._anchor = items[0];
-		}
+* Prints a debug message. Any HTML will be rendered, and a line break is added.
+*
+* @param level	 	debug level for the current debugger
+* @param msg		the text to display
+*/
+AjxDebug.prototype.println = 
+function(level, msg, linkName) {
+	if (this.isDisabled() || this._debugWindow.closed) return;
+	var args = this._handleArgs(arguments, linkName);
+	if (!args) return;
+
+	msg = args.join("");
+	/*** DEBUG ***
+	if (String(level).match(/^DBG|PERF/)) {
+		msg = level + ": " + msg;
 	}
-	return this._anchor;
+	/*** DEBUG ***/
+	this._add(this._timestamp() + msg + "<br>", null, null, null, linkName);
 };
-    
-/**
- * The cursor probably changes when the users navigates with 
- * the keyboard. This returns the item that is currently the cursor,
- * and null if nothing is selected.
- */
-AjxSelectionManager.prototype.getCursor = function() {
-	if (this._cursor == null) {
-		this._cursor = this.getAnchor();
-	}
-	return this._cursor;
+
+AjxDebug.prototype.isDisabled = 
+function () {
+	return !this._enabled;
 };
-    
-    
+
 /**
- * Returns true if the given item is selected.
- */
-AjxSelectionManager.prototype.isSelected = function(item) {
-	return this.getItems().binarySearch(item) != -1;
-};
-    
-AjxSelectionManager.prototype.selectOneItem = function(item) {
-	this.select(item, AjxSelectionManager.SELECT_ONE_CLEAR_OTHERS);
-};
-    
-AjxSelectionManager.prototype.toggleItem = function(item) {
-	this.select(item, AjxSelectionManager.TOGGLE_ONE_LEAVE_OTHERS);
-};
-	
-AjxSelectionManager.prototype.selectFromAnchorToItem = function(item) {
-	this.select(item, AjxSelectionManager.SELECT_TO_ANCHOR);
-};
-    
-AjxSelectionManager.prototype.deselectAll = function() {
-	this.select(null, AjxSelectionManager.DESELECT_ALL);
-};
-	
-AjxSelectionManager.prototype.selectAll = function() {
-	this.select(null, AjxSelectionManager.SELECT_ALL);
+* Prints an object into a table, with a column for properties and a column for values. Above the table is a header with the object
+* class and the CSS class (if any). The properties are sorted (numerically if they're all numbers). Creating and appending table 
+* elements worked in Mozilla but not IE. Using the insert* methods works for both. Properties that are function 
+* definitions are skipped.
+*
+* @param level	 	debug level for the current debugger
+* @param obj		the object to be printed
+* @param showFuncs	whether to show props that are functions
+*/
+AjxDebug.prototype.dumpObj = 
+function(level, obj, showFuncs, linkName) {
+	if (this.isDisabled() || this._debugWindow.closed)return;
+	var args = this._handleArgs(arguments, linkName);
+	if (!args) return;
+	obj = args[0];
+	if (!obj) return;
+	this._showFuncs = args[1];
+
+	AjxDebug._visited = new AjxVector();
+	this._add(null, obj);
+	this._showFuncs = null;
 };
-    
-    
+
 /**
- * This method will notify the owner of any changes by calling
- * itemSelectionChanged() (if the owner defines it) for each item whose
- * selection changes and also by calling selectionChanged() (if the
- * owner defines it) once at the end, if anything changed selection.
- *
- */
-AjxSelectionManager.prototype.select = function(item, action) {
-	
-	// Update the anchor and cursor, if necessary
-	this._setAnchorAndCursor(item, action);
-    
-	// save off the old set of selected items
-	var oldItems = this._selectedItems;
-	var oldItemsCount = (oldItems == null) ? 0 : oldItems.length;
-	
-	// create a fresh set of selected items
-	this._selectedItems = null;
-	this._selectedItems = this._createItemsCollection();
+* Dumps a bunch of text into a &lt;textarea&gt;, so that it is wrapped and scrollable. HTML will not be rendered.
+*
+* @param level	 	debug level for the current debugger
+* @param text		the text to output as is
+*/
+AjxDebug.prototype.printRaw = 
+function(level, text, linkName) {
+	if (this.isDisabled() || this._debugWindow.closed) return;
+	var args = this._handleArgs(arguments, linkName);
+	if (!args) return;
+	text = args[0];
 	
-	// Now update the selection
-	var itemCount = this._owner.getItemCount();
-	var needsSort = false;
-	var selectionChanged = false;
-	var selecting = false;
-	for (var i = 0; i < itemCount; ++i) {
-		var testItem = this._owner.getItem(i);
-		var oldSelectionExists = this._isItemOldSelection(testItem, oldItems);
-		var newSelectionExists = oldSelectionExists;
-		
-		switch (action) {
-		case AjxSelectionManager.SELECT_TO_ANCHOR:
-			if (this._anchor == null) {
-				// If we have no anchor, let it be the first item
-				// in the list
-				this._anchor = testItem;
-			}
-			var atEdge = (testItem == this._anchor || testItem == item);
-			var changed = false;
-			// mark the beginning of the selection for the iteration
-			if (!selecting && atEdge) {
-				selecting = true;
-				changed = true;
-			}
-			newSelectionExists = selecting;
-			// mark the end of the selection if we're there
-			if ((!changed || this._anchor == item) 
-				&& selecting && atEdge) {
-				selecting = false;
-			}
-
-			break;
-		case AjxSelectionManager.SELECT_ONE_CLEAR_OTHERS:
-			newSelectionExists = (testItem == item);
-			break;
-		case AjxSelectionManager.TOGGLE_ONE_LEAVE_OTHERS:
-			if (testItem == item) {
-				newSelectionExists = !oldSelectionExists ;
-			}
-			break;
-		case AjxSelectionManager.DESELECT_ALL:
-			newSelectionExists = false;
-			break;
-		case AjxSelectionManager.SELECT_ALL:
-			newSelectionExists = true;
-			break;
-		}
-
-		if (newSelectionExists) {
-			this._selectedItems.add(testItem);
-			needsSort = (this._selectedItems.length > 1);
-		}
+	this._add(null, text, false, true);
+};
 
-		if ( newSelectionExists != oldSelectionExists) {
-			// Something changed so notify the owner.
-			if (this._owner.itemSelectionChanged != null) {
-				this._owner.itemSelectionChanged(testItem, 
-												 i, newSelectionExists);
-			}
-			selectionChanged = true;
-		}
-	}
-	selectionChanged = selectionChanged || (oldItemsCount != 
-											this._selectedItems.length);
+/**
+* Pretty-prints a chunk of XML, doing color highlighting for different types of nodes.
 
-	if (needsSort) this._selectedItems.sort();
+* @param level	 	debug level for the current debugger
+* @param text		some XML
+*/
+AjxDebug.prototype.printXML = 
+function(level, text, linkName) {
+	if (this.isDisabled() || this._debugWindow.closed) return;
+	var args = this._handleArgs(arguments, linkName);
+	if (!args) return;
+	text = args[0];
+	if (!text) return;
 	
-	if (selectionChanged && this._owner.selectionChanged != null) {
-		this._owner.selectionChanged(item);
+	// skip generating pretty xml if theres too much data
+	if (AjxEnv.isSafari || text.length > AjxDebug.MAX_OUT) {
+		this.printRaw(text);
+		return;
 	}
+	this._add(null, text, true, false);
 };
 
 /**
- * Remove an item from the selection managers selected items
- * collection if it exists.
- */
-AjxSelectionManager.prototype.removeItem = function(item) {
-	if (this._selectedItems) {
-		var index = this._selectedItems.binarySearch(item);
-		if (index > -1) this._selectedItems.removeAt(index);
-	}
+* Reveals white space in text by replacing it with tags.
+*
+* @param level	 	debug level for the current debugger
+* @param text		the text to be displayed
+*/
+AjxDebug.prototype.display =
+function(level, text) {
+	if (this.isDisabled() || this._debugWindow.closed) return;
+	var args = this._handleArgs(arguments);
+	if (!args) return;
+	text = args[0];
+
+	text = text.replace(/\r?\n/g, '[crlf]');
+	text = text.replace(/ /g, '[space]');
+	text = text.replace(/\t/g, '[tab]');
+	this.printRaw(level, text);
 };
 
-// -----------------------------------------------------------
-// Internal Methods
-// -----------------------------------------------------------
+AjxDebug.prototype.timePt =
+function(level, msg) {
+	if (!this._showTiming || !this._enabled || this._debugWindow.closed) return;
 	
-/**
- * Creates an array suitable for use as the sorted list of selected
- * items and returns it.
- */
-AjxSelectionManager.prototype._createItemsCollection = function() {
-	return new AjxVector();
-};
+	var args = this._handleArgs(arguments);
+	if (!args) return;
+	var msg = args[0];
+	
+	var now = new Date().getTime();
+	var elapsed = now - this._startTimePt;
+	var interval = now - this._lastTimePt;
+	this._lastTimePt = now;
+	var text = "[" + elapsed + " / " + interval + "]";
+	if (msg)
+		text += " " + msg;
+	html = "<div>" + text + "</div>";
+	extraType = typeof(text);
 
-AjxSelectionManager.prototype._isItemOldSelection = function (testItem, oldItems) {
-	var ret = false;
-	if (oldItems) {
-		var oldSelectionIndex = oldItems.binarySearch(testItem);
-		if (oldSelectionIndex > -1) {
-			oldItems.removeAt(oldSelectionIndex);
-		}
-		ret = (oldSelectionIndex != -1);
-	}
-	return ret;
+    var myMsg = new DebugMessage(html);
+	
+    // Add the message to our stack
+    this._addMessage(myMsg);
+	return interval;
 };
 
-AjxSelectionManager.prototype._setAnchorAndCursor = function (item, action) {
-	switch (action) {
-	case AjxSelectionManager.SELECT_TO_ANCHOR:
-		this._cursor = item;
-		break;
-	case AjxSelectionManager.SELECT_ONE_CLEAR_OTHERS:		
-		this._anchor = item;
-		this._cursor = item;
-		break;
-	case AjxSelectionManager.TOGGLE_ONE_LEAVE_OTHERS:
-		this._anchor = item;
-		this._cursor = item;
-		break;
-	case AjxSelectionManager.DESELECT_ALL:
-		this._anchor = null;
-		this._cursor = null;
-		break;
-	case AjxSelectionManager.SELECT_ALL:
-		return;
-	}
-};
-/**** Autoinclude function file:./zimbra/js/soap/AjxSoapDoc.js****/
-/*
-* ***** BEGIN LICENSE BLOCK *****
-* Version: MPL 1.1
-*
-* The contents of this file are subject to the Mozilla Public
-* License Version 1.1 ("License"); you may not use this file except in
-* compliance with the License. You may obtain a copy of the License at
-* http://www.zimbra.com/license
-*
-* Software distributed under the License is distributed on an "AS IS"
-* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-* the License for the specific language governing rights and limitations
-* under the License.
-*
-* The Original Code is: Zimbra AJAX Toolkit.
-*
-* The Initial Developer of the Original Code is Zimbra, Inc.
-* Portions created by Zimbra are Copyright (C) 2005 Zimbra, Inc.
-* All Rights Reserved.
-*
-* Contributor(s):
-*
-* ***** END LICENSE BLOCK *****
-*/
 
+// Private methods
 
-// Don't directly instantiate SoapDoc, use one of the create factory methods instead
-function AjxSoapDoc() {
-}
+AjxDebug.prototype._getHtmlForObject = 
+function(anObj, isXml, isRaw) {
+	var html = new Array();
+	var idx = 0;
 
-AjxSoapDoc.prototype.toString =
-function() {
-	return "AjxSoapDoc";
+	if (AjxUtil.isUndefined(anObj)) {
+		html[idx++] = "<span>Undefined</span>";
+	} else if (AjxUtil.isNull(anObj)) {
+		html[idx++] = "<span>NULL</span>";
+	} else if (AjxUtil.isBoolean(anObj)) {
+		html[idx++] = "<span>" + anObj + "</span>";
+	} else if (AjxUtil.isNumber(anObj)) {
+		html[idx++] = "<span>" + anObj +"</span>";
+	} else {
+		if (isRaw) {
+			html[idx++] = this._timestamp();
+			html[idx++] = "<textarea rows='25' style='width:100%' readonly='true'>";
+			html[idx++] = anObj;
+			html[idx++] = "</textarea>";
+			html[idx++] = "<p></p>";
+		} else if (isXml) {
+			var xmldoc = new AjxDebugXmlDocument;
+			var doc = xmldoc.create();
+			doc.loadXML(anObj);
+			html[idx++] = "<div style='border-width:2px; border-style:inset; width:100%; height:300px; overflow:auto'>";
+			html[idx++] = this._createXmlTree(doc, 0);
+			html[idx++] = "</div>";
+		} else {
+			html[idx++] = "<div style='border-width:2px; border-style:inset; width:100%; height:300px; overflow:auto'>";
+			html[idx++] = "<pre>";
+			html[idx++] = this._dump(anObj, true);
+			html[idx++] = "</div>";
+			html[idx++] = "</pre>";
+		}
+	}
+	return html.join("");
 };
 
-AjxSoapDoc._SOAP_URI = "http://www.w3.org/2003/05/soap-envelope";
-// AjxSoapDoc._SOAP_URI = "http://schemas.xmlsoap.org/soap/envelope/";
-AjxSoapDoc._XMLNS_URI = "http://www.w3.org/2000/xmlns";
-
-AjxSoapDoc.create =
-function(method, namespace, namespaceId, soapURI) {
-	var sd = new AjxSoapDoc();
-	sd._xmlDoc = AjxXmlDoc.create();
-	var d = sd._xmlDoc.getDoc();
-	var envEl = d.createElement("soap:Envelope");
-
-	if (!soapURI)
-		soapURI = AjxSoapDoc._SOAP_URI;
-	envEl.setAttribute("xmlns:soap", soapURI);
+// Pretty-prints a Javascript object
+AjxDebug.prototype._dump =
+function(obj, recurse) {
 
-	d.appendChild(envEl);
+	var indentLevel = 0;
+	var showBraces = false;
+	var stopRecursion = false;
+	if (arguments.length > 2) {
+		indentLevel = arguments[2];
+		showBraces = arguments[3];
+		stopRecursion = arguments[4];
+	}
 
-	var bodyEl = d.createElement("soap:Body");
-	envEl.appendChild(bodyEl);
+	if (AjxUtil.isObject(obj)) {
+		if (obj.toString() == "ZmAppCtxt"){
+			return "[ZmAppCtxt]";
+		}
+		if (AjxDebug._visited.contains(obj))
+			return "[visited object]";
+		else
+			AjxDebug._visited.add(obj);
+	}	
 
-	sd._methodEl = d.createElement(method);
-	if (namespaceId == null)
-		sd._methodEl.setAttribute("xmlns", namespace);
-	else
-		sd._methodEl.setAttribute("xmlns:" + namespaceId, namespace);
+	var indent = AjxStringUtil.repeat(" ", indentLevel);
+	var text = "";
+	
+	if (AjxUtil.isUndefined(obj)) {
+		text += "[undefined]";
+	} else if (AjxUtil.isNull(obj)) {
+		text += "[null]";
+	} else if (AjxUtil.isBoolean(obj)) {
+		text += obj ? "true" : "false";
+	} else if (AjxUtil.isString(obj)) {
+	//	obj = obj.replace(/\r/g, "\\r");
+	//	obj = obj.replace(/\n/g, "\\n");
+	//	obj = obj.replace(/\t/g, "\\t");
+		text += '"' + AjxDebug._escapeForHTML(obj) + '"';
+	} else if (AjxUtil.isNumber(obj)) {
+		text += obj;
+	} else if (AjxUtil.isObject(obj)) {
+		var isArray = AjxUtil.isArray(obj);
+		if (stopRecursion) {
+			text += isArray ? "[Array]" : obj.toString();
+		} else {
+			stopRecursion = !recurse;
+			var keys = new Array();
+			for (var i in obj)
+				keys.push(i);
 
-	bodyEl.appendChild(sd._methodEl);
-	return sd;
-};
+			isArray ? keys.sort(function(a,b) {return a - b;}) : keys.sort();	
+	
 
-AjxSoapDoc.createFromDom =
-function(doc) {
-	var sd = new AjxSoapDoc();
-	sd._xmlDoc = AjxXmlDoc.createFromDom(doc);
-	sd._methodEl = sd._check(sd._xmlDoc);
-	return sd;
-};
+			if (showBraces)
+				text += isArray ? "[" : "{";
+			for (var i = 0; i < keys.length; i++) {
+				var key = keys[i];
+				var nextObj = obj[key];
+				var value = null;
+				// 5/31/05 EMC:
+				// For dumping events, and dom elements, though I may not want to
+				// traverse the node, I do want to know what the attribute is.
+				if (nextObj == window || nextObj == document || (!AjxEnv.isIE && nextObj instanceof Node)){
+					value = nextObj.toString();
+				} 
+				if ((typeof(nextObj) == "function")){
+					if (this._showFuncs) {
+						value = "[function]";
+					} else {
+						continue;
+					}
+				}
 
-AjxSoapDoc.createFromXml =
-function(xml) {
-	var sd = new AjxSoapDoc();
-	sd._xmlDoc = AjxXmlDoc.createFromXml(xml);
-	sd._methodEl = sd._check(sd._xmlDoc);
-	return sd;
+				if (i > 0) text += ",";
+				text += "\n" + indent;
+				if (value != null) {
+					text += key + ": " + value;
+				} else {
+					text += key + ": " + this._dump(nextObj, recurse, indentLevel + 2, true, stopRecursion);
+				}
+			}
+			if (i > 0)
+				text += "\n" + AjxStringUtil.repeat(" ", indentLevel - 1);
+			if (showBraces)
+				text += isArray ? "]" : "}";
+		}
+	}
+	return text;
 };
 
-AjxSoapDoc.element2FaultObj =
-function(el) {
-	// If the element is not a SOAP fault, then return null
-	var faultEl = el.firstChild;
-	// Safari is bad at handling namespaces
-	if (!AjxEnv.isSafari) {
-		if (faultEl != null && faultEl.namespaceURI != AjxSoapDoc._SOAP_URI || faultEl.nodeName != (el.prefix + ":Fault"))
-			return null;
-	} else {
-		if (faultEl != null && faultEl.nodeName != (el.prefix + ":Fault"))
-			return null;
+// If the first arg is a debug level, check it and then strip it.
+AjxDebug.prototype._handleArgs =
+function(args, linkNameSpecified) {
+	if (this._level == AjxDebug.NONE) return;
+	
+	var levelSpecified = false;
+	var curLevel = AjxDebug.GBD[this._level];
+	var msgLevel = AjxDebug.GBD[AjxDebug.DBG1];
+	if (typeof args[0] == "string" && String(args[0]).match(/^DBG|PERF/)) {
+		msgLevel = AjxDebug.GBD[args[0]];
+		levelSpecified = true;
 	}
-	return new AjxSoapFault(faultEl);
-};
-
-AjxSoapDoc.prototype.setMethodAttribute =
-function(name, value) {
-	this._methodEl.setAttribute(name, value);
+	if (msgLevel > curLevel) return;
+	
+	// NOTE: Can't just slice the items we want because args is not an Array
+	var array = new Array(args.length);
+	var len = (linkNameSpecified) ? args.length - 1 : args.length;
+	for (var i = 0; i < len; i++) {
+		array[i] = args[i];
+	}
+	if (levelSpecified) { array.shift(); }
+	return array;
 };
 
-/**
- * Creates arguments to pass within the envelope.  "value" can be a JS object
- * or a scalar (string, number, etc.).
- *
- * When "value" is a JS object, set() will call itself recursively in order to
- * create a complex data structure.  Don't pass a "way-too-complicated" object
- * ("value" should only contain references to simple JS objects, or better put,
- * hashes--don't include a reference to the "window" object as it will kill
- * your browser).
- *
- * Example:
- *
- *    soapDoc.set("user_auth", {
- *       user_name : "foo",
- *       password  : "bar"
- *    });
- *
- * will create an XML like this under the method tag:
- *
- *    <user_auth>
- *      <user_name>foo</user_name>
- *      <password>bar</password>
- *    </user_auth>
- *
- * Of course, nesting other hashes is allowed and will work as expected.
- *
- * NOTE: you can pass null for "name", in which case "value" is expected to be
- * an object whose properties will be created directly under the method el.
- */
-AjxSoapDoc.prototype.set = 
-function(name, value, parent) {
-	var	doc = this.getDoc();
-	var	p = name
-		? doc.createElement(name)
-		: doc.createDocumentFragment();
-
-	if (value != null) {
-		if (typeof value == "object") {
-			for (i in value)
-				this.set(i, value[i], p);
+AjxDebug.prototype._getCookieVal =
+function (cookieName) {
+	var myRE = cookieName  + "=([^;]+)";
+	var myVals = document.cookie.match(new RegExp(myRE));
+	var val = null;
+	// Return the last value defined (if found)
+	if (myVals && (myVals.length > 0)) {
+		var valStr = myVals[myVals.length-1];
+		if (valStr == "true") {
+			val = true;
+		} else if (valStr == "false") {
+			val = false;
 		} else {
-			if (AjxEnv.isSafari) value = AjxStringUtil.xmlEncode(value);
-			p.appendChild(doc.createTextNode(value));
+			val = valStr;
 		}
 	}
-	if (!parent)
-		parent = this._methodEl;
-	return parent.appendChild(p);
+	return val;
 };
 
-AjxSoapDoc.prototype.getMethod =
+AjxDebug.prototype._openDebugWindow =
 function() {
-	return this._methodEl;
+	this._enabled = true;
+	// check if there is a debug window already open
+	this._isPrevWinOpen = this._getCookieVal("AjxDebugWinOpen");
+	if (!this._isPrevWinOpen) {
+		this._debugWindow = AjxWindowOpener.openBlank(this._dbgName, "width=600,height=400,resizable=yes,scrollbars=yes", this._initWindow, this);
+	} else {
+		this._debugWindow = window.open("" , this._dbgName, "width=600,height=400,resizable=yes,scrollbars=yes");
+		this._initWindow();
+	}
 };
 
-AjxSoapDoc.prototype.createHeaderElement =
+
+AjxDebug.prototype._initWindow =
 function() {
-	var d = this._xmlDoc.getDoc();
-	var envEl = d.firstChild;
-	var header = this.getHeader();
-	if (header != null) {
-		throw new AjxSoapException("SOAP header already exists", AjxSoapException.ELEMENT_EXISTS, "AjxSoapDoc.prototype.createHeaderElement");
+	if (this._debugWindow == null) {
+		this._enabled = false;
+		return;
 	}
-	header = d.createElement("soap:Header")
-	envEl.insertBefore(header, envEl.firstChild);
-	return header;
-};
+	
+	try {
+		this._document = this._debugWindow.document;
+		this._document.title = "Debug";
 
-AjxSoapDoc.prototype.getHeader =
-function() {
-	// would love to use getElementsByTagNameNS, but IE does not support it
-	var d = this._xmlDoc.getDoc();
-	var nodeList = AjxEnv.isIE
-		? (d.getElementsByTagName(d.firstChild.prefix + ":Header"))
-		: (d.getElementsByTagNameNS(AjxSoapDoc._SOAP_URI, "Header"));
+		if (!this._isPrevWinOpen) {
+			this._document.write([
+				"<html>",
+					"<head>",
+						"<script>",
+							"function blank() {return [",
+								"'<html><head><style type=\"text/css\">',",
+									"'P, TD, DIV, SPAN, SELECT, INPUT, TEXTAREA, BUTTON {',",
+											"'font-family: Tahoma, Arial, Helvetica, sans-serif;',",
+											"'font-size:11px;}',",
+									"'.Link {cursor: pointer;color:blue;text-decoration:underline;white-space:nowrap;width:100%;}',",		
+									"'.Mark {color:white; background-color:black; width:100%;font-size:14px;font-weight:bold;}',",
+									"'.MarkLink {cursor: pointer;color:white;background-color:black;text-decoration:underline;font-weight:bold;white-space:nowrap;width:100%;}',",
+									"'.Run {color:black; background-color:red;width:100%;font-size:18px;font-weight:bold;}',",
+									"'.RunLink {cursor: pointer;color:black;background-color:red;text-decoration:underline;font-weight:bold;white-space:nowrap;width:100%;}',",
+								"'</style></head><body></body></html>'].join(\"\");}",
+						"</script>",
+					"</head>",
+					"<frameset cols='125, *'>",
+						"<frameset rows='*,40'>",
+							"<frame name='", AjxDebug._LINK_FRAME_ID, "' id='", AjxDebug._LINK_FRAME_ID, "' src='javascript:parent.parent.blank();'>",
+							"<frame name='", AjxDebug._BUTTON_FRAME_ID, "' id='", AjxDebug._BUTTON_FRAME_ID, "' src='javascript:parent.parent.blank();'>",
+						"</frameset>",
+						"<frame name='", AjxDebug._CONTENT_FRAME_ID, "' id='", AjxDebug._CONTENT_FRAME_ID, "' src='javascript:parent.blank();'>",
+					"</frameset>",
+				"</html>"].join(""));
+			var ta = new AjxTimedAction(this, AjxDebug.prototype._finishInitWindow);
+			AjxTimedAction.scheduleAction(ta, 250);
+		} else {
+			this._contentFrame = this._document.getElementById(AjxDebug._CONTENT_FRAME_ID);
+			this._linkFrame = this._document.getElementById(AjxDebug._LINK_FRAME_ID);
+			this._createLinkNContent(this, "RunLink", "NEW RUN", "Run", "NEW RUN");
+			
+			// Firefox allows us to attach an event listener, and runs it even
+			// though the window with the code is gone ... odd, but nice. IE,
+			// though will not run the handler, so we make sure, even if we're
+			// coming back to the window, to attach the onunload handler. In general
+			// reattach all handlers for IE
+			if (AjxEnv.isIE) {
+				this._debugWindow.attachEvent('onunload', AjxDebug.unloadHandler);
+				this._markBtn.onclick = AjxDebug._mark;
+				this._clearBtn.onclick = AjxDebug._clear;
+			}		
+				
+			this._dbgWindowInited = true;
+			// show any messages that have been queued up, while the window loaded.
+			this._showMessages();
+		}
+	} catch (ex) {
+		AjxDebug.deleteWindowCookie();
+		this._debugWindow.close();
 
-	return nodeList ? nodeList[0] : null;
+		// If we've exceeded a certain # of errors, just close window and bail.
+		if (AjxDebug._openErrors < 5) {
+			AjxDebug._openErrors++;
+			this._openDebugWindow();
+		}
+	}
 };
 
-AjxSoapDoc.prototype.getBody =
+AjxDebug.prototype._finishInitWindow =
 function() {
-	// would love to use getElementsByTagNameNS, but IE does not support it
-	var d = this._xmlDoc.getDoc();
-	var nodeList = AjxEnv.isIE
-		? (d.getElementsByTagName(d.firstChild.prefix + ":Body"))
-		: (d.getElementsByTagNameNS(AjxSoapDoc._SOAP_URI, "Body"));
+	this._contentFrame = this._document.getElementById(AjxDebug._CONTENT_FRAME_ID);
+	this._linkFrame = this._document.getElementById(AjxDebug._LINK_FRAME_ID);
 
-	return nodeList ? nodeList[0] : null;
-};
+	// Create the mark and clear buttons
+	var buttonFrame = this._document.getElementById(AjxDebug._BUTTON_FRAME_ID);
+	var buttonFrameDoc = buttonFrame.contentWindow.document;
+	var buttonFrameBody = buttonFrameDoc.body;
+	
+	var markBtn = this._markBtn = buttonFrameDoc.createElement("button");
+	markBtn.innerHTML = "Mark";
+	markBtn._dbg = this;
+	markBtn.onclick = AjxDebug._mark;
 
-AjxSoapDoc.prototype.getByTagName =
-function(type) {
-	if (type.indexOf(":") == -1)
-		type = "soap:" + type;
+	var clearBtn = this._markBtn = buttonFrameDoc.createElement("button");
+	clearBtn._contentFrameId = AjxDebug._CONTENT_FRAME_ID;
+	clearBtn._linkFrameId = AjxDebug._LINK_FRAME_ID;
+	clearBtn.innerHTML = "Clear";
+	clearBtn._dbg = this;
+	clearBtn.onclick = AjxDebug._clear;
+	
+	buttonFrameBody.appendChild(markBtn);
+	buttonFrameBody.appendChild(buttonFrameDoc.createTextNode(" "));
+	buttonFrameBody.appendChild(clearBtn);
 
-	var a = this.getDoc().getElementsByTagName(type);
 
-	if (a.length == 1)		return a[0];
-	else if (a.length > 0)	return a;
-	else					return null;
-};
+	// If we're not using a div
+	// Set a cookie telling ourselves that a debug window is already open
+	document.cookie = "AjxDebugWinOpen=true";
+	
+	// setup an onunload method
+	if (!AjxEnv.isIE) {
+		this._debugWindow.onunload = AjxDebug.unloadHandler;
+		window.addEventListener('unload', AjxDebug.myWindowUnloadHandler, true);
+	} else {
+		this._debugWindow.attachEvent('onunload', AjxDebug.unloadHandler);
+		window.attachEvent = AjxDebug.myWindowUnloadHandler;
+	}
 
-// gimme a header, no exceptions.
-AjxSoapDoc.prototype.ensureHeader =
-function() {
-	return (this.getByTagName("Header") || this.createHeaderElement());
+	this._dbgWindowInited = true;
+	this._showMessages();
 };
 
-AjxSoapDoc.prototype.getDoc =
-function() {
-	return this._xmlDoc.getDoc();
-};
 
-AjxSoapDoc.prototype.getXml =
+/**
+* Scrolls to the bottom of the window. How it does that depends on the browser.
+*
+* @private
+*/
+AjxDebug.prototype._scrollToBottom = 
 function() {
-	return AjxEnv.isSafari
-		? (AjxXmlDoc.getXml(this._xmlDoc.getDoc()))
-		: this._xmlDoc.getDoc().xml;
-};
-
-// Very simple checking of soap doc. Should be made more comprehensive
-AjxSoapDoc.prototype._check =
-function(xmlDoc) {
-	var doc = xmlDoc.getDoc();
-	if (doc.childNodes.length != 1)
-		throw new AjxSoapException("Invalid SOAP PDU", AjxSoapException.INVALID_PDU, "AjxSoapDoc.createFromXml:1");
-
-	// Check to make sure we have a soap envelope
-	var el = doc.firstChild;
-
-	// Safari is bad at handling namespaces
-	if (!AjxEnv.isSafari) {
-		if (el.namespaceURI != AjxSoapDoc._SOAP_URI ||
-		    el.nodeName != (el.prefix + ":Envelope") ||
-		    (el.childNodes.length < 1 || el.childNodes.length > 2))
-		{
-			DBG.println("<font color=red>XML PARSE ERROR on RESPONSE:</font>");
-			DBG.printRaw(doc.xml);
-			throw new AjxSoapException("Invalid SOAP PDU", AjxSoapException.INVALID_PDU, "AjxSoapDoc.createFromXml:2");
-		}
+	if (AjxEnv.isIE) {
+		this._contentFrame.contentWindow.document.body.scrollIntoView(false);
+		this._linkFrame.contentWindow.document.body.scrollIntoView(false);
 	} else {
-		if (el.nodeName != (el.prefix + ":Envelope"))
-			throw new AjxSoapException("Invalid SOAP PDU", AjxSoapException.INVALID_PDU, "AjxSoapDoc.createFromXml:2");
+		this._contentFrame.contentWindow.scrollTo(0, this._contentFrame.contentWindow.document.body.offsetHeight);
+		this._linkFrame.contentWindow.scrollTo(0, this._linkFrame.contentWindow.document.body.offsetHeight);
 	}
 };
-/**** Autoinclude function file:./zimbra/js/net/AjxRpcRequest.js****/
-/*
-* ***** BEGIN LICENSE BLOCK *****
-* Version: MPL 1.1
-*
-* The contents of this file are subject to the Mozilla Public
-* License Version 1.1 ("License"); you may not use this file except in
-* compliance with the License. You may obtain a copy of the License at
-* http://www.zimbra.com/license
-*
-* Software distributed under the License is distributed on an "AS IS"
-* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-* the License for the specific language governing rights and limitations
-* under the License.
-*
-* The Original Code is: Zimbra AJAX Toolkit.
-*
-* The Initial Developer of the Original Code is Zimbra, Inc.
-* Portions created by Zimbra are Copyright (C) 2005 Zimbra, Inc.
-* All Rights Reserved.
-*
-* Contributor(s):
-*
-* ***** END LICENSE BLOCK *****
-*/
-
 
 /**
-* Creates a new AjxRpcRequest. The request object is an ActiveX object
-* for IE, and an XMLHttpRequest object otherwise.
-* @constructor
-* @class
-* This class represents an XML HTTP request, hiding differences between
-* browsers. The internal request object depends on the browser.
-*
-* @param id		[string]	unique ID for this request
-* @param ctxt	[_RpcCtxt]	owning context
-**/
-function AjxRpcRequest(id, ctxt) {
-	if (!AjxRpcRequest._inited) 
-		AjxRpcRequest._init();
-	
-	this.id = id;
-	this.ctxt = ctxt;
-	if (AjxEnv.isIE) {
-		this._httpReq = new ActiveXObject(AjxRpcRequest._msxmlVers);
-	} else if (AjxEnv.isSafari || AjxEnv.isNav) {
-		this._httpReq =  new XMLHttpRequest();
-	}
+* Returns a timestamp string, if we are showing them.
+* @private
+*/
+AjxDebug.prototype._timestamp = 
+function() {
+	return this._showTime 
+		? AjxDateFormat.getTimeInstance().format(new Date()) + ": " 
+		: "";
 };
 
-AjxRpcRequest._inited = false;
-AjxRpcRequest._msxmlVers = null;
-
-AjxRpcRequest.prototype.toString = 
-function() {
-	return "AjxRpcRequest";
+AjxDebug.prototype.setShowTimestamps = 
+function(show) {
+	this._showTime = show;
 };
 
-/**
-* Sends this request to the target URL. If there is a callback, the request is
-* performed asynchronously.
-*
-* @param requestStr		[string]		HTTP request string/document
-* @param serverUrl		[string]		request target
-* @param requestHeaders	[Array]*		HTTP request headers
-* @param callback		[AjxCallback]*	callback (for async requests)
-* @param useGet			[boolean]*		if true use GET method, else use POST
-*/
-AjxRpcRequest.prototype.invoke =
-function(requestStr, serverUrl, requestHeaders, callback, useGet, timeout) {
+// this function takes an xml node and returns an html string that displays that node
+// the indent argument is used to describe what depth the node is at so that
+// the html code can create a nice indention
+AjxDebug.prototype._createXmlTree = 
+function (node, indent) {
 
-	var asyncMode = (callback != null);
+	if (node == null)
+		return "";
+	var str = "";
 	
-	// exception here will be caught by AjxRpc.invoke
-	this._httpReq.open((useGet) ? "get" : "post", serverUrl, asyncMode);
-
-	if (asyncMode) {
-		this._callback = callback;
-		var tempThis = this;
-		DBG.println(AjxDebug.DBG3, "Async RPC request");
-		this._httpReq.onreadystatechange = function(ev) {AjxRpcRequest._handleResponse(tempThis, callback);};
-	} else {
-		// IE appears to run handler even on sync requests, so we need to clear it
-		this._httpReq.onreadystatechange = function(ev) {};
-	}
-
-	if (requestHeaders) {
-		for (var i in requestHeaders) {
-			this._httpReq.setRequestHeader(i, requestHeaders[i]);
-			DBG.println(AjxDebug.DBG3, "Async RPC request: Add header " + i + " - " + requestHeaders[i]);
-		}
-	}
+	switch (node.nodeType) {
+		case 1:	// Element
+			str += "<div style='color: blue; padding-left: 16px;'>&lt;<span style='color: DarkRed;'>" + node.nodeName + "</span>";
+			
+			var attrs = node.attributes;
+			for (var i = 0; i < attrs.length; i++)
+				str += this._createXmlAttribute(attrs[i]);
+			
+			if (!node.hasChildNodes())
+				return str + "/&gt;</div>";
+			
+			str += "&gt;<br />";
+			
+			var cs = node.childNodes;
+			for (var i = 0; i < cs.length; i++)
+				str += this._createXmlTree(cs[i], indent + 3);
+			
+			str += "&lt;/<span style='color: DarkRed;'>" + node.nodeName + "</span>&gt;</div>";
+			break;
 	
-	this._httpReq.send(requestStr);
-	if (asyncMode) {
-		return this.id;
-	} else {
-		if (this._httpReq.status == 200) {
-			return {text: this._httpReq.responseText, xml: this._httpReq.responseXML, success: true};
-		} else {
-			return {text: this._httpReq.responseText, xml: this._httpReq.responseXML, success: false, status: this._httpReq.status};
-		}
+		case 9:	// Document
+			var cs = node.childNodes;
+			for (var i = 0; i < cs.length; i++)
+				str += this._createXmlTree(cs[i], indent);
+			break;
+	
+		case 3:	// Text
+			if (!/^\s*$/.test(node.nodeValue)) {
+				var val = node.nodeValue.replace(/</g, "&lt;").replace(/>/g, "&gt;");
+				str += "<span style='color: WindowText; padding-left: 16px;'>" + val + "</span><br />";
+			}
+			break;
+	
+		case 7:	// ProcessInstruction
+			str += "&lt;?" + node.nodeName;
+		
+			var attrs = node.attributes;
+			for (var i = 0; i < attrs.length; i++)
+				str += this._createXmlAttribute(attrs[i]);
+			
+			str+= "?&gt;<br />"
+			break;
+	
+		case 4:	// CDATA
+			str = "<div style=''>&lt;![CDATA[<span style='color: WindowText; font-family: \"Courier New\"; white-space: pre; display: block; border-left: 1px solid Gray; padding-left: 16px;'>" + 
+				node.nodeValue +
+			"</span>]" + "]></div>";
+			break;
+			
+		case 8:	// Comment
+			str = "<div style='color: blue; padding-left: 16px;'>&lt;!--<span style='white-space: pre; font-family: \"Courier New\"; color: Gray; display: block;'>" + 
+				node.nodeValue +
+			"</span>--></div>";
+			break;
+		
+		case 10:
+				str = "<div style='color: blue; padding-left: 16px'>&lt;!DOCTYPE " + node.name;
+				if (node.publicId) {
+					str += " PUBLIC \"" + node.publicId + "\"";
+					if (node.systemId) 
+						str += " \"" + node.systemId + "\"";
+				}
+				else if (node.systemId) {
+					str += " SYSTEM \"" + node.systemId + "\"";
+				}
+				str += "&gt;</div>";
+				
+				// TODO: Handle custom DOCTYPE declarations (ELEMENT, ATTRIBUTE, ENTITY)
+				
+				break;
+		
+		default:
+			//alert(node.nodeType + "\n" + node.nodeValue);
+			this._inspect(node);
 	}
+	
+	return str;
 };
 
-/*
-* Handler that runs when an asynchronous response has been received. It runs a
-* callback to initiate the response handling.
-*
-* @param req		[AjxRpcRequest]		request that generated the response
-* @param callback	[AjxCallback]		callback to run after response is received
-*/
-AjxRpcRequest._handleResponse =
-function(req, callback) {
-	if (!req) {
-		// If IE receives a 500 error, the object reference can be lost
-		DBG.println(AjxDebug.DBG1, "Async RPC request: Lost request object!!!");
-		callback.run( {text: null, xml: null, success: false, status: 500} );
-		return;
-	}
-
-	DBG.println(AjxDebug.DBG3, "Async RPC request: ready state = " + req._httpReq.readyState);
-	if (req._httpReq.readyState == 4) {
-		if (DBG.getDebugLevel() >= AjxDebug.DBG3)
-			DBG.println("Async RPC request: HTTP status = " + req._httpReq.status);
-		if (req._httpReq.status == 200) {
-			callback.run( {text: req._httpReq.responseText, xml: req._httpReq.responseXML, success: true} );				
-		} else {
-			callback.run( {text: req._httpReq.responseText, xml: req._httpReq.responseXML, success: false, status: req._httpReq.status} );				
-		}
-		req.ctxt.busy = false;
-	}
+AjxDebug.prototype._createXmlAttribute = 
+function(a) {
+	return " <span style='color: red'>" + a.nodeName + "</span><span style='color: blue'>=\"" + a.nodeValue + "\"</span>";
 };
 
-AjxRpcRequest.prototype.cancel =
-function() {
-	DBG.println(AjxDebug.DBG1, "Aborting HTTP request");
-	this._httpReq.abort();
+AjxDebug.prototype._inspect = 
+function(obj) {
+	var str = "";
+	for (var k in obj)
+		str += "obj." + k + " = " + obj[k] + "\n";
+	window.alert(str);
 };
 
-AjxRpcRequest._init =
-function() {
-	if (AjxEnv.isIE) {
-		var msxmlVers = ["MSXML2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"];
-		for (var i = 0; i < msxmlVers.length; i++) {
-			try {
-				// search for the xml version on user's machine
-				var x = new ActiveXObject(msxmlVers[i]);
-				AjxRpcRequest._msxmlVers = msxmlVers[i];
-				break;
-			} catch (ex) {
-				// do nothing
+AjxDebug.prototype._add = 
+function (aMsg, extraInfo, isXml, isRaw, linkName){
+	var extraType = typeof(extraInfo);
+
+	if (AjxUtil.isSpecified(extraInfo))
+		extraInfo = this._getHtmlForObject(extraInfo, isXml, isRaw);
+
+    // Add the message to our stack
+    this._addMessage(new DebugMessage(aMsg, null, null, null, extraInfo, linkName));
+
+};
+
+AjxDebug.prototype._addMessage = 
+function (aMsg) {
+	this._msgQueue[this._msgQueue.length] = aMsg;
+	this._showMessages();
+};
+
+donola=false;
+AjxDebug.prototype._showMessages = 
+function () {
+	if (!this._dbgWindowInited) {
+		// For now, don't show the messages-- assuming that this case only 
+		// happens at startup, and many  messages will be written
+		return;
+	}
+	
+	if (this._msgQueue.length > 0) {
+		var msg;
+		var contentDiv;
+		var linkDiv;
+		var contentFrameDoc = this._contentFrame.contentWindow.document;
+		var linkFrameDoc = this._linkFrame.contentWindow.document;
+		
+		for (var i = 0 ; i < this._msgQueue.length ; ++i ) {
+			var now = new Date();
+			msg = this._msgQueue[i];
+			contentDiv = contentFrameDoc.createElement('div');
+			contentDiv.innerHTML = [msg.message, msg.eHtml].join("");
+			if (msg.linkName) {
+				linkDiv = linkFrameDoc.createElement('div');
+				linkDiv._targetId = contentDiv.id = [AjxDebug._getNextId(), now.getMilliseconds()].join("");
+				linkDiv._dbg = this;
+				linkDiv.className = "Link";
+				linkDiv.onclick = AjxDebug._linkClicked;
+				linkDiv.innerHTML = msg.linkName  + " - [" + AjxDebug._getTimeStamp(now) + "]";;	
+				linkFrameDoc.body.appendChild(linkDiv);
+				//linkFrameDoc.body.appendChild(linkFrameDoc.createElement("br"));
 			}
+			contentFrameDoc.body.appendChild(contentDiv);		
 		}
-		if (AjxRpcRequest._msxmlVers == null)
-			throw new AjxException("MSXML not installed", AjxException.INTERNAL_ERROR, "AjxRpc._init");
 	}
-	AjxRpcRequest._inited = true;
+
+	this._msgQueue.length = 0;
+	this._scrollToBottom();
+};
+
+AjxDebug._linkClicked =
+function() {
+	var el = this._dbg._contentFrame.contentWindow.document.getElementById(this._targetId);
+	var y = 0;
+	while (el) {
+		y += el.offsetTop;
+		el = el.offsetParent;
+	}
+	
+	this._dbg._contentFrame.contentWindow.scrollTo(0, y);	
+};
+
+AjxDebug._getNextId =
+function() {
+	return "AjxDebug_" + AjxDebug._id++;
+};
+
+AjxDebug.prototype._parseHtmlFragment = 
+function (htmlStr) {
+	var div = this._contentFrame.contentWindow.document.createElement('div');	
+	div.innerHTML = htmlStr;
+	return div;
+};
+
+
+// Static methods
+
+AjxDebug._mark = 
+function() {
+	this._dbg._createLinkNContent(this._dbg, "MarkLink", "MARK", "Mark", "MARK");
+};
+
+AjxDebug.prototype._createLinkNContent =
+function(ajxDbgObj, linkClass, linkLabel, contentClass, contentLabel) {
+	var now = new Date();
+	var timeStamp = [" - [", AjxDebug._getTimeStamp(now), "]"].join("");
+	var linkFrameDoc = ajxDbgObj._linkFrame.contentWindow.document;
+	var div = linkFrameDoc.createElement("div");
+	div.className = linkClass;
+	div.innerHTML = linkLabel + timeStamp;
+	var id = "Lnk_" + now.getMilliseconds();
+	div._targetId = id;
+	div._dbg = ajxDbgObj;
+	div.onclick = AjxDebug._linkClicked
+	linkFrameDoc.body.appendChild(div);
+	//linkFrameDoc.body.appendChild(linkFrameDoc.createElement("br"));
+	
+	var contentFrameDoc = ajxDbgObj._contentFrame.contentWindow.document;
+	div = contentFrameDoc.createElement("div");
+	div.className = contentClass;
+	div.id = id;
+	div.innerHTML = contentLabel + timeStamp;
+	div._dbg = ajxDbgObj;
+	contentFrameDoc.body.appendChild(contentFrameDoc.createElement("p"));
+	contentFrameDoc.body.appendChild(div);
+	contentFrameDoc.body.appendChild(contentFrameDoc.createElement("p"));
+};
+
+AjxDebug._clear = 
+function() {
+	this._dbg._contentFrame.contentWindow.document.body.innerHTML = "";
+	this._dbg._linkFrame.contentWindow.document.body.innerHTML = "";	
+};
+
+AjxDebug.myWindowUnloadHandler = 
+function() {
+	if (AjxEnv.isNav) {
+		DBG._debugWindow.onunload = null;
+	} else {
+		DBG._debugWindow.detachEvent('onunload', AjxDebug.unloadHandler);
+	}
+};
+
+AjxDebug.unloadHandler = 
+function() {
+	try {
+		window.AjxDebug.deleteWindowCookie();
+	} catch (ex) {
+		// do nothing. This might be caused by the unload handler
+		// firing while the window is changing domains.
+	}
+};
+
+AjxDebug.deleteWindowCookie = 
+function() {
+    var expiredDate = new Date('Fri, 31 Dec 1999 23:59:59 GMT'); // I18n???
+	document.cookie = "AjxDebugWinOpen=false;expires=" + expiredDate.toGMTString();
+};
+
+AjxDebug._escapeForHTML = 
+function(str){
+	if (typeof(str) != 'string') return str;
+	var s = str;
+	s = s.replace(/\&/g, '&amp;');
+	s = s.replace(/\</g, '&lt;');
+	s = s.replace(/\>/g, '&gt;');
+	s = s.replace(/\"/g, '&quot;');
+	s = s.replace(/\xA0/g, '&nbsp;');	
+	return s;
+};
+
+AjxDebug._getTimeStamp =
+function(date) {
+	date = (date) ? date : new Date();
+	return AjxStringUtil.htmlEncode([AjxDateUtil.getTimeStr(date, "%H:%m:%s"), ".", date.getMilliseconds()].join(""), true);
+};
+
+/**
+ * Simple wrapper for log messages
+ */
+DebugMessage = function(aMsg, aType, aCategory, aTime, extraHtml, linkName) {
+    this.message = (AjxUtil.isSpecified(aMsg)) ? aMsg : '';
+    this.type = aType ? aType : null;
+    this.category = aCategory ? aCategory : '';
+    this.time = aTime ? aTime : (new Date().getTime());
+    this.eHtml = extraHtml ? extraHtml : '';
+    this.linkName = linkName;
 };
-/**** Autoinclude function file:./zimbra/js/dwt/events/DwtHtmlEditorStateEvent.js****/
+/** auto include file:./zimbra/js/soap/AjxSoapException.js **/
 /*
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
@@ -2272,39 +2333,22 @@
 */
 
 
-function DwtHtmlEditorStateEvent(init) {
-	if (arguments.length == 0) return;
-	DwtEvent.call(this, true);
-	this.reset();
+function AjxSoapException(msg, code, method, detail) {
+	AjxException.call(this, msg, code, method, detail);
 }
 
-DwtHtmlEditorStateEvent.prototype = new DwtEvent;
-DwtHtmlEditorStateEvent.prototype.constructor = DwtHtmlEditorStateEvent;
-
-DwtHtmlEditorStateEvent.prototype.toString = 
+AjxSoapException.prototype.toString = 
 function() {
-	return "DwtHtmlEditorStateEvent";
+	return "AjxSoapException";
 }
 
-DwtHtmlEditorStateEvent.prototype.reset =
-function() {
-	this.isBold = null;
-	this.isItalic = null;
-	this.isUnderline = null;
-	this.isStrikeThru = null;
-	this.isSuperscript = null;
-	this.isSubscript = null;
-	this.isOrderedList = null;
-	this.isNumberedList = null;
-	this.fontName = null;
-	this.fontSize = null;
-	this.style = null;
-	this.backgroundColor = null;
-	this.color = null;
-	this.justification = null;
-	this.direction = null;
-}
-/**** Autoinclude function file:./zimbra/js/dwt/events/DwtKeyEvent.js****/
+AjxSoapException.prototype = new AjxException;
+AjxSoapException.prototype.constructor = AjxSoapException;
+
+AjxSoapException.INTERNAL_ERROR 	= "INTERNAL_ERROR";
+AjxSoapException.INVALID_PDU 		= "INVALID_PDU";
+AjxSoapException.ELEMENT_EXISTS 	= "ELEMENT_EXISTS";
+/** auto include file:./zimbra/js/util/AjxCallback.js **/
 /*
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
@@ -2331,65 +2375,98 @@
 */
 
 
-function DwtKeyEvent() {
-	DwtUiEvent.call(this, true);
-	this.reset(true);
-}
+/**
+* Creates a callback which consists of at least a function reference, and possibly also
+* an object to call it from.
+* @constructor
+* @class
+* This class represents a callback function which can be called standalone, or from a
+* given object. What the callback takes as arguments and what it returns are left to the
+* client.
+*
+* @author Conrad Damon
+* @param obj	[Object]				the object to call the function from
+* @param func	[function]				the callback function
+* @param args   [primitive or Array]	default arguments
+*/
+function AjxCallback(obj, func, args) {
+	if (arguments.length == 0) return;
 
+	this.obj = obj;
+	this.func = func;
+	this.args = args;
+}
 
-DwtKeyEvent.KEY_END_OF_TEXT =  0x03;
-DwtKeyEvent.KEY_TAB = 0x09;
-DwtKeyEvent.KEY_RETURN = 0x0D;
-DwtKeyEvent.KEY_ENTER = 0x0D;
-DwtKeyEvent.KEY_ESCAPE = 0x1B;
+AjxCallback.prototype.toString =
+function() {
+	return "AjxCallback";
+}
 
-DwtKeyEvent.prototype = new DwtUiEvent;
-DwtKeyEvent.prototype.constructor = DwtKeyEvent;
-
-DwtKeyEvent.prototype.toString = 
-function() {
-	return "DwtKeyEvent";
-}
-
-DwtKeyEvent.isKeyEvent =
-function(ev) {
-	return (ev.type.search(/^key/i) != -1);
-}
-
-DwtKeyEvent.isKeyPressEvent =
-function(ev) {
-	return (AjxEnv.isIE && ev.type == "keydown") || (ev.type == "keypress");
-}
-
-DwtKeyEvent.prototype.reset =
-function(dontCallParent) {
-	if (!dontCallParent)
-		DwtUiEvent.prototype.reset.call(this);
-	this.keyCode = 0;
-	this.charCode = 0;
-}
+/**
+* Runs the callback function, from within the object if there is one. The
+* called function passed arguments are the concatenation of the argument
+* array passed to this object's constructor and the argument array passed
+* to the <code>run</code> method. Whatever the called function returns is
+* returned to the caller.
+*
+* @param arg1	The first argument which will be appended to the argument
+*				array passed to this object's constructor. Any number of
+*				arguments may be passed to the <code>run</code> method.
+*/
+AjxCallback.prototype.run =
+function(/* arg1 ... argN */) {
+	// combine original args with new ones
+	var args = [];
 
+	// sometimes we want to pass a null or false argument, so simply
+	// checking for if (this.args) won't do.
+	if (typeof this.args != "undefined") {
+		if (this.args instanceof Array)
+			// NOTE: We must NOT use this.args directly if this method's
+			//       params are gonna be pushed onto the array because it
+			//       will change the original args!
+			args = arguments.length > 0 ? args.concat(this.args) : this.args;
+		else
+			args.push(this.args);
+	}
 
-DwtKeyEvent.prototype.setFromDhtmlEvent =
-function(ev) {
-	ev = DwtUiEvent.prototype.setFromDhtmlEvent.call(this, ev);
-	this.charCode = (ev.charCode) ? ev.charCode : ev.keyCode;
-	this.keyCode = ev.keyCode;
-}
+	for (var i = 0; i < arguments.length; ++i)
+		args.push(arguments[i]);
 
-DwtKeyEvent.getCharCode =
-function(ev) {
-	ev = DwtUiEvent.getEvent(ev);
-	return AjxEnv.isSafari ? ev.keyCode : (ev.charCode || ev.keyCode);
-}
+	// invoke function
+	return this.func.apply(this.obj || window, args);
+};
 
-DwtKeyEvent.copy = 
-function(dest, src) {
-	DwtUiEvent.copy(dest, src);
-	dest.charCode = src.charCode;
-	dest.keyCode = src.keyCode;
-}
-/**** Autoinclude function file:./zimbra/js/dwt/widgets/DwtListView.js****/
+/**
+ * The following function is what an AjxCallback should be *all* about.  It
+ * returns a plain function that will call your supplied "func" in the context
+ * of "obj" and pass to it, in this order, any additional arguments that you
+ * pass to simpleClosure and the arguments that were passed to it at the call
+ * time.
+ *
+ * An example should do:
+ *
+ *   div.onclick = AjxCallback.simpleClosure(this.handler, this, "some data");
+ *   ...
+ *   this.handler = function(data, event) {
+ *      // event will be passed for DOM2 compliant browsers
+ *      // and data is "some data"
+ *   };
+ *
+ * [this is one of the most useful functions I ever wrote :D  -mihai@zimbra.com]
+ */
+AjxCallback.simpleClosure = function(func, obj) {
+	var args = [];
+	for (var i = 2; i < arguments.length; ++i)
+		args.push(arguments[i]);
+	return function() {
+		var args2 = [];
+		for (var i = 0; i < arguments.length; ++i)
+			args2.push(arguments[i]);
+		func.apply(obj || this, args.concat(args2));
+	};
+};
+/** auto include file:./zimbra/js/util/AjxSelectionManager.js **/
 /*
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
@@ -2416,903 +2493,1732 @@
 */
 
 
-function DwtListView(parent, className, posStyle, headerList, noMaximize) {
-
-	if (arguments.length == 0) return;
-	className = className || "DwtListView";
-	DwtComposite.call(this, parent, className, posStyle);
+/**
+ * This requires an "owner" which is the object that owns the full set of items, implmenting:
+ * getItemCount() to return the number of items
+ * getItem(index) to return the item at a given index.
+ * 
+ * And optionally implementing
+ * itemSelectionChanged(item, index, isSelected) which is called
+ *         for each item that is selected or deselected
+ * selectionChanged() which is called after a batch of items have
+ *         been selected or deselected with select()
+ *
+ */
+	
+AjxSelectionManager = function(anOwner) {
+	this._owner = anOwner;
+};
 
-	if (headerList) {
-		var htmlElement = this.getHtmlElement();
+// -----------------------------------------------------------
+// Constants
+// -----------------------------------------------------------
 
-		this._listColDiv = document.createElement("div");
-		this._listColDiv.id = Dwt.getNextId();
-		this._listColDiv.className = "DwtListView-ColHeader";
-		htmlElement.appendChild(this._listColDiv);
+// Actions for select()
+AjxSelectionManager.SELECT_ONE_CLEAR_OTHERS = 0;
+AjxSelectionManager.TOGGLE_ONE_LEAVE_OTHERS = 1;
+AjxSelectionManager.SELECT_TO_ANCHOR = 2;
+AjxSelectionManager.DESELECT_ALL = 3;
+AjxSelectionManager.SELECT_ALL = 4;
 
-		this._listDiv = document.createElement("div");
-		this._listDiv.id = Dwt.getNextId();
-		this._listDiv.className = "DwtListView-Rows";
-		htmlElement.appendChild(this._listDiv);
+// -----------------------------------------------------------
+// API Methods
+// -----------------------------------------------------------
 
-		// setup vars needed for sorting
-		this._bSortAsc = false;
-		this._currentColId = null;
-		this._sortingEnabled = true;
-	} else {
-		this.setScrollStyle(DwtControl.SCROLL); // auto scroll
+/**
+ * returns an AjxVector
+ */
+AjxSelectionManager.prototype.getItems = function() {
+	if (this._selectedItems == null) {
+		this._selectedItems = this._createItemsCollection();
 	}
-		
-	this._setMouseEventHdlrs();
-	this.setCursor("default");
-
-	this._listenerMouseOver = new AjxListener(this, this._mouseOverListener);
-	this._listenerMouseOut = new AjxListener(this, this._mouseOutListener);
-	this._listenerMouseDown = new AjxListener(this, this._mouseDownListener);
-	this._listenerMouseUp = new AjxListener(this, this._mouseUpListener);
-	this._listenerMouseMove = new AjxListener(this, this._mouseMoveListener);
-	this._listenerDoubleClick = new AjxListener(this, this._doubleClickListener);
-	this.addListener(DwtEvent.ONMOUSEOVER, this._listenerMouseOver);
-	this.addListener(DwtEvent.ONMOUSEOUT, this._listenerMouseOut);
-	this.addListener(DwtEvent.ONMOUSEDOWN, this._listenerMouseDown);
-	this.addListener(DwtEvent.ONMOUSEUP, this._listenerMouseUp);
-	this.addListener(DwtEvent.ONMOUSEMOVE, this._listenerMouseMove);
-	this.addListener(DwtEvent.ONDBLCLICK, this._listenerDoubleClick);
+	return this._selectedItems;
+};
 
-	this._evtMgr = new AjxEventMgr();
-	this._selectedItems = new AjxVector();
-	this._selAnchor = null; 
-	this._selEv = new DwtSelectionEvent(true);
-	this._actionEv = new DwtListViewActionEvent(true);
-	this._stateChangeEv = new DwtEvent(true);
-	this._headerList = headerList;
-	this._noMaximize = noMaximize;
-	this._parentEl = this._headerList ? this._listDiv : this.getHtmlElement();
+/**
+ * returns the number of selected items
+ */	
+AjxSelectionManager.prototype.getLength = function() {
+	return this.getItems().length;
+};
 	
-	this._list = null;
-	this._offset = 0;
-	this._headerColCreated = false;
-	this._firstSelIndex = -1;
-
-	this.setMultiSelect(true);
-}
-
-DwtListView.ITEM_SELECTED 		= 1;
-DwtListView.ITEM_DESELECTED 	= 2;
-DwtListView.ITEM_DBL_CLICKED 	= 3;
-DwtListView._LAST_REASON 		= 3;
-
-DwtListView._TOOLTIP_DELAY 		= 250;
-
-DwtListView.HEADERITEM_HEIGHT 	= 24;
-DwtListView.HEADERITEM_ARROW  	= "arr--";
-DwtListView.HEADER_ID			= "crr--";
-DwtListView.HEADERITEM_LABEL 	= "drr--";
-
-DwtListView.TYPE_HEADER_ITEM 	= "1";
-DwtListView.TYPE_LIST_ITEM 		= "2";
-DwtListView.TYPE_HEADER_SASH 	= "3";
-
-DwtListView.DEFAULT_LIMIT = 25;
-DwtListView.MAX_REPLENISH_THRESHOLD = 10;
-DwtListView.MIN_COLUMN_WIDTH = 10;
-DwtListView.COL_MOVE_THRESHOLD = 3;
-
-DwtListView.prototype = new DwtComposite;
-DwtListView.prototype.constructor = DwtListView;
-
-DwtListView.prototype.toString = 
-function() {
-	return "DwtListView";
-}
-
-DwtListView.prototype.setEnabled = 
-function(enabled) {
-	DwtComposite.prototype.setEnabled.call(this, enabled);
-	// always remove listeners to avoid adding listeners multiple times
-	this.removeListener(DwtEvent.ONMOUSEOVER, this._listenerMouseOver);
-	this.removeListener(DwtEvent.ONMOUSEOUT, this._listenerMouseOut);
-	this.removeListener(DwtEvent.ONMOUSEDOWN, this._listenerMouseDown);
-	this.removeListener(DwtEvent.ONMOUSEUP, this._listenerMouseUp);
-	this.removeListener(DwtEvent.ONMOUSEMOVE, this._listenerMouseMove);
-	this.removeListener(DwtEvent.ONDBLCLICK, this._listenerDoubleClick);
-	// now re-add listeners, if needed
-	if (enabled) {
-		this.addListener(DwtEvent.ONMOUSEOVER, this._listenerMouseOver);
-		this.addListener(DwtEvent.ONMOUSEOUT, this._listenerMouseOut);
-		this.addListener(DwtEvent.ONMOUSEDOWN, this._listenerMouseDown);
-		this.addListener(DwtEvent.ONMOUSEUP, this._listenerMouseUp);
-		this.addListener(DwtEvent.ONMOUSEMOVE, this._listenerMouseMove);
-		this.addListener(DwtEvent.ONDBLCLICK, this._listenerDoubleClick);
+/**
+ * returns the anchor, unless nothing is selected
+ */
+AjxSelectionManager.prototype.getAnchor = function() {
+	if (this._anchor == null) {
+		var items = this.getItems();
+		if (items.length > 0) {
+			this._anchor = items[0];
+		}
 	}
-	// modify selection classes
-	var selection = this.getSelectedItems();
-	if (selection) {
-		var elements = selection.getArray();
-		for (var i = 0; i < elements.length; i++) {
-			var element = elements[i];
-			element.className = enabled 
-				? Dwt.getAttr(element, "_selectedStyleClass") 
-				: Dwt.getAttr(element, "_selectedDisabledStyleClass");
-		}
+	return this._anchor;
+};
+    
+/**
+ * The cursor probably changes when the users navigates with 
+ * the keyboard. This returns the item that is currently the cursor,
+ * and null if nothing is selected.
+ */
+AjxSelectionManager.prototype.getCursor = function() {
+	if (this._cursor == null) {
+		this._cursor = this.getAnchor();
 	}
-}
-
-DwtListView.prototype.createHeaderHtml = 
-function(defaultColumnSort) {
-
-	// does this list view have headers or have they already been created?
-	if (!this._headerList || this._headerColCreated)
-		return;
+	return this._cursor;
+};
+    
+    
+/**
+ * Returns true if the given item is selected.
+ */
+AjxSelectionManager.prototype.isSelected = function(item) {
+	return this.getItems().binarySearch(item) != -1;
+};
+    
+AjxSelectionManager.prototype.selectOneItem = function(item) {
+	this.select(item, AjxSelectionManager.SELECT_ONE_CLEAR_OTHERS);
+};
+    
+AjxSelectionManager.prototype.toggleItem = function(item) {
+	this.select(item, AjxSelectionManager.TOGGLE_ONE_LEAVE_OTHERS);
+};
 	
-	var idx = 0;
-	var htmlArr = new Array();
-	this._headerTableId = DwtListView.HEADER_ID + Dwt.getNextId();
-
-	htmlArr[idx++] = "<table id='" + this._headerTableId + "' cellpadding=0 cellspacing=0 border=0 height=100%";
-	htmlArr[idx++] = this._noMaximize ? ">" : " width=100%>";
-	htmlArr[idx++] = "<tr>";
-	for (i = 0; i < this._headerList.length; i++) {
-		var headerCol = this._headerList[i];
-		if (!headerCol._visible)
-			continue;
-			
-		htmlArr[idx++] = "<td id='" + headerCol._id + "' class='";
-		htmlArr[idx++] = headerCol._id == this._currentColId
-			? "DwtListView-Column DwtListView-ColumnActive'"
-			: "DwtListView-Column'";
-		htmlArr[idx++] = headerCol._width ? " width=" + headerCol._width + ">" : ">";
-		// must add a div to force clipping :(
-		htmlArr[idx++] = "<div";
-		htmlArr[idx++] = headerCol._width ? (" style='width: " + (headerCol._width+2) + "'>") : ">";
-
-		// add new table for icon/label/sorting arrow		
-		htmlArr[idx++] = "<table border=0 cellpadding=0 cellspacing=0 width=100%><tr>";
-		if (headerCol._iconInfo) {
-			htmlArr[idx++] = "<td><center>";
-			htmlArr[idx++] = AjxImg.getImageHtml(headerCol._iconInfo);
-			htmlArr[idx++] = "</center></td>";
-		}
-			
-		if (headerCol._label)
-			htmlArr[idx++] = "<td id='" + DwtListView.HEADERITEM_LABEL + headerCol._id + "'>&nbsp;" + headerCol._label + "</td>";
+AjxSelectionManager.prototype.selectFromAnchorToItem = function(item) {
+	this.select(item, AjxSelectionManager.SELECT_TO_ANCHOR);
+};
+    
+AjxSelectionManager.prototype.deselectAll = function() {
+	this.select(null, AjxSelectionManager.DESELECT_ALL);
+};
+	
+AjxSelectionManager.prototype.selectAll = function() {
+	this.select(null, AjxSelectionManager.SELECT_ALL);
+};
+    
+    
+/**
+ * This method will notify the owner of any changes by calling
+ * itemSelectionChanged() (if the owner defines it) for each item whose
+ * selection changes and also by calling selectionChanged() (if the
+ * owner defines it) once at the end, if anything changed selection.
+ *
+ */
+AjxSelectionManager.prototype.select = function(item, action) {
+	
+	// Update the anchor and cursor, if necessary
+	this._setAnchorAndCursor(item, action);
+    
+	// save off the old set of selected items
+	var oldItems = this._selectedItems;
+	var oldItemsCount = (oldItems == null) ? 0 : oldItems.length;
+	
+	// create a fresh set of selected items
+	this._selectedItems = null;
+	this._selectedItems = this._createItemsCollection();
+	
+	// Now update the selection
+	var itemCount = this._owner.getItemCount();
+	var needsSort = false;
+	var selectionChanged = false;
+	var selecting = false;
+	for (var i = 0; i < itemCount; ++i) {
+		var testItem = this._owner.getItem(i);
+		var oldSelectionExists = this._isItemOldSelection(testItem, oldItems);
+		var newSelectionExists = oldSelectionExists;
 		
-		if (headerCol._sortable) {
-			var arrowIcon = this._bSortAsc ? "ColumnUpArrow" : "ColumnDownArrow";
-			var id = DwtListView.HEADERITEM_ARROW + headerCol._id;
-			if (headerCol._sortable == defaultColumnSort) {
-				this._currentColId = headerCol._id;
-				htmlArr[idx++] = "<td width=10 id='" + id + "'>" + AjxImg.getImageHtml(arrowIcon) + "</td>";
-			} else {
-				htmlArr[idx++] = "<td width=10 id='" + id + "'>" + AjxImg.getImageHtml(arrowIcon, "visibility:hidden") + "</td>";
+		switch (action) {
+		case AjxSelectionManager.SELECT_TO_ANCHOR:
+			if (this._anchor == null) {
+				// If we have no anchor, let it be the first item
+				// in the list
+				this._anchor = testItem;
+			}
+			var atEdge = (testItem == this._anchor || testItem == item);
+			var changed = false;
+			// mark the beginning of the selection for the iteration
+			if (!selecting && atEdge) {
+				selecting = true;
+				changed = true;
+			}
+			newSelectionExists = selecting;
+			// mark the end of the selection if we're there
+			if ((!changed || this._anchor == item) 
+				&& selecting && atEdge) {
+				selecting = false;
 			}
-		}
-		
-		// ALWAYS add "sash" separators
-		htmlArr[idx++] = "<td width=4>";
-		htmlArr[idx++] = "<table align=right border=0 cellpadding=0 cellspacing=0 width=2 height=100%><tr>";
-		htmlArr[idx++] = "<td class='DwtListView-Sash'><div style='width: 1px; height: " + (DwtListView.HEADERITEM_HEIGHT-2) + "px; background-color: #8A8A8A'></div></td>";
-		htmlArr[idx++] = "<td class='DwtListView-Sash'><div style='width: 1px; height: " + (DwtListView.HEADERITEM_HEIGHT-2) + "px; background-color: #FFFFFF'></div></td>";
-		htmlArr[idx++] = "</tr></table>";
-		htmlArr[idx++] = "</td>";
-
-		htmlArr[idx++] = "</tr></table>";
-		htmlArr[idx++] = "</div></td>";
-	}
-	htmlArr[idx++] = "</tr>";
-	htmlArr[idx++] = "</table>";
 
-	this._listColDiv.innerHTML = htmlArr.join("");
+			break;
+		case AjxSelectionManager.SELECT_ONE_CLEAR_OTHERS:
+			newSelectionExists = (testItem == item);
+			break;
+		case AjxSelectionManager.TOGGLE_ONE_LEAVE_OTHERS:
+			if (testItem == item) {
+				newSelectionExists = !oldSelectionExists ;
+			}
+			break;
+		case AjxSelectionManager.DESELECT_ALL:
+			newSelectionExists = false;
+			break;
+		case AjxSelectionManager.SELECT_ALL:
+			newSelectionExists = true;
+			break;
+		}
 
-	// for each sortable column, sets its identifier
-	for (var j = 0; j < this._headerList.length; j++) {
-		var cell = document.getElementById(this._headerList[j]._id);
-		if (cell == null) continue;
-		
-		var sortable = this._headerList[j]._sortable;
-		if (sortable && sortable == defaultColumnSort)
-			cell.className = "DwtListView-Column DwtListView-ColumnActive";
+		if (newSelectionExists) {
+			this._selectedItems.add(testItem);
+			needsSort = (this._selectedItems.length > 1);
+		}
 
-		var isResizeable = this._headerList[j]._resizeable;
-		if (isResizeable) {
-			// always get the sibling cell to the right
-			var sashCell = cell.firstChild.firstChild.rows[0].lastChild;
-			if (sashCell) {
-				sashCell._type = DwtListView.TYPE_HEADER_SASH;
-				sashCell._itemIndex = j + "--sash";
+		if ( newSelectionExists != oldSelectionExists) {
+			// Something changed so notify the owner.
+			if (this._owner.itemSelectionChanged != null) {
+				this._owner.itemSelectionChanged(testItem, 
+												 i, newSelectionExists);
 			}
+			selectionChanged = true;
 		}
-
-		cell._isSortable = sortable != null;
-		cell._isResizeable = isResizeable;
-		cell._type = DwtListView.TYPE_HEADER_ITEM;
-		cell._itemIndex = j;
 	}
-	
-	this._headerColCreated = true;
-}
-
+	selectionChanged = selectionChanged || (oldItemsCount != 
+											this._selectedItems.length);
 
-// this returns the index into the header list array for the given Id
-DwtListView.prototype.getColIndexForId = 
-function(headerId) {
-	if (this._headerList) {
-		for (var i = 0; i < this._headerList.length; i++) {
-			if (this._headerList[i]._id.indexOf(headerId) != -1)
-				return i;
-		}
+	if (needsSort) this._selectedItems.sort();
+	
+	if (selectionChanged && this._owner.selectionChanged != null) {
+		this._owner.selectionChanged(item);
 	}
-	return -1;
 };
 
 /**
-* Creates a list view out of the given vector of items. The derived class should override _createItemHtml()
-* in order to display an item.
-*
-* @param list	a vector of items (AjxVector)
-* @param defaultColumnSort	default column field to sort (optional)
-*/
-DwtListView.prototype.set =
-function(list, defaultColumnSort) {
-	
-	this._selectedItems.removeAll();
-	this.enableSorting(true);
-	this._resetList();
-	this._list = list;
-	this._now = new Date();
-	this.setUI(defaultColumnSort);
-}
+ * Remove an item from the selection managers selected items
+ * collection if it exists.
+ */
+AjxSelectionManager.prototype.removeItem = function(item) {
+	if (this._selectedItems) {
+		var index = this._selectedItems.binarySearch(item);
+		if (index > -1) this._selectedItems.removeAt(index);
+	}
+};
 
+// -----------------------------------------------------------
+// Internal Methods
+// -----------------------------------------------------------
+	
 /**
-* Renders the list view using the current list of items.
-*
-* @param defaultColumnSort		[string]	ID of column that represents default sort order
-* @param noResultsOk			[boolean]*	if true, don't show "No Results" for empty list
-*/
-DwtListView.prototype.setUI =
-function(defaultColumnSort, noResultsOk) {
-	this.removeAll();
-	this.createHeaderHtml(defaultColumnSort);
-	this._renderList(this._list, noResultsOk);
-}
-
-DwtListView.prototype._renderList =
-function(list, noResultsOk) {
-	if (list instanceof AjxVector && list.size()) {
-		var size = list.size();
-		for (var i = 0; i < size; i++) {
-			var item = list.get(i);
-			var div = this._createItemHtml(item, this._now);
-			if (div) {
-				if (div instanceof Array) {
-					for (var j = 0; j < div.length; j++){
-						this._addRow(div[j]);
-					}
-				} else {
-					this._addRow(div);
-				}
-			}
-		}
-	} else if (!noResultsOk) {
-		this._setNoResultsHtml();
-	}
+ * Creates an array suitable for use as the sorted list of selected
+ * items and returns it.
+ */
+AjxSelectionManager.prototype._createItemsCollection = function() {
+	return new AjxVector();
 };
 
-DwtListView.prototype.addItems =
-function(itemArray, index) {
-	if (AjxUtil.isArray(itemArray)){
-		if (!this._list) {
-			this._list = new AjxVector();
-		}
-	
-		// clear the "no results" message before adding!
-		if (this._list.size() == 0) {
-			this._resetList();
+AjxSelectionManager.prototype._isItemOldSelection = function (testItem, oldItems) {
+	var ret = false;
+	if (oldItems) {
+		var oldSelectionIndex = oldItems.binarySearch(testItem);
+		if (oldSelectionIndex > -1) {
+			oldItems.removeAt(oldSelectionIndex);
 		}
-		var currentSize = this._list.size();
-		var vec = AjxVector.fromArray(itemArray);
-		this._renderList(vec);
-		this._list.addList(itemArray);
+		ret = (oldSelectionIndex != -1);
 	}
+	return ret;
 };
 
-DwtListView.prototype.addItem =
-function(item, index, skipNotify) {
-	if (!this._list)
-		this._list = new AjxVector();
-	
-	// clear the "no results" message before adding!
-	if (this._list.size() == 0)
-		this._resetList();
-	
-	this._list.add(item, index);
-	var div = this._createItemHtml(item, this._now);
-	if (div)
-		this._addRow(div, index);
-		
-	if (!skipNotify && this._evtMgr.isListenerRegistered(DwtEvent.STATE_CHANGE)) {
-		this._evtMgr.notifyListeners(DwtEvent.STATE_CHANGE, this._stateChangeEv);
+AjxSelectionManager.prototype._setAnchorAndCursor = function (item, action) {
+	switch (action) {
+	case AjxSelectionManager.SELECT_TO_ANCHOR:
+		this._cursor = item;
+		break;
+	case AjxSelectionManager.SELECT_ONE_CLEAR_OTHERS:		
+		this._anchor = item;
+		this._cursor = item;
+		break;
+	case AjxSelectionManager.TOGGLE_ONE_LEAVE_OTHERS:
+		this._anchor = item;
+		this._cursor = item;
+		break;
+	case AjxSelectionManager.DESELECT_ALL:
+		this._anchor = null;
+		this._cursor = null;
+		break;
+	case AjxSelectionManager.SELECT_ALL:
+		return;
 	}
-}
+};
+/** auto include file:./zimbra/js/soap/AjxSoapDoc.js **/
+/*
+* ***** BEGIN LICENSE BLOCK *****
+* Version: MPL 1.1
+*
+* The contents of this file are subject to the Mozilla Public
+* License Version 1.1 ("License"); you may not use this file except in
+* compliance with the License. You may obtain a copy of the License at
+* http://www.zimbra.com/license
+*
+* Software distributed under the License is distributed on an "AS IS"
+* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+* the License for the specific language governing rights and limitations
+* under the License.
+*
+* The Original Code is: Zimbra AJAX Toolkit.
+*
+* The Initial Developer of the Original Code is Zimbra, Inc.
+* Portions created by Zimbra are Copyright (C) 2005 Zimbra, Inc.
+* All Rights Reserved.
+*
+* Contributor(s):
+*
+* ***** END LICENSE BLOCK *****
+*/
 
-DwtListView.prototype.removeItem =
-function(item, skipNotify) {
-	var itemEl = this._getElFromItem(item);
-	this._selectedItems.remove(itemEl);
-	this._parentEl.removeChild(itemEl);
-	this._list.remove(item);
-		
-	if (!skipNotify && this._evtMgr.isListenerRegistered(DwtEvent.STATE_CHANGE)) {
-		this._evtMgr.notifyListeners(DwtEvent.STATE_CHANGE, this._stateChangeEv);
-	}
-}
 
-DwtListView.prototype.removeLastItem =
-function(skipNotify) {
-	var last = this._list.get(this._list.size() - 1);
-	this._list.remove(last);
-	this._parentEl.removeChild(this._getElFromItem(last));
-		
-	if (!skipNotify && this._evtMgr.isListenerRegistered(DwtEvent.STATE_CHANGE)) {
-		this._evtMgr.notifyListeners(DwtEvent.STATE_CHANGE, this._stateChangeEv);
-	}
+// Don't directly instantiate SoapDoc, use one of the create factory methods instead
+function AjxSoapDoc() {
 }
 
-DwtListView.prototype.reIndexColumn = 
-function(columnIdx, newIdx) {
-	// do some sanity checks before continuing
-	if (this._headerList == null) 
-		return;
-	var len = this._headerList.length;
-	if (columnIdx < 0 || newIdx < 0 || columnIdx >= len || newIdx >= len || columnIdx == newIdx)
-		return;
+AjxSoapDoc.prototype.toString =
+function() {
+	return "AjxSoapDoc";
+};
 
-	// reindex the header list
-	var temp = this._headerList.splice(columnIdx, 1);
-	this._headerList.splice(newIdx, 0, temp[0]);
-	
-	// finally, relayout the list view (incl. header columns)
-	this._relayout();
-}
+AjxSoapDoc._SOAP_URI = "http://www.w3.org/2003/05/soap-envelope";
+// AjxSoapDoc._SOAP_URI = "http://schemas.xmlsoap.org/soap/envelope/";
+AjxSoapDoc._XMLNS_URI = "http://www.w3.org/2000/xmlns";
 
-DwtListView.prototype.reSizeColumn = 
-function(headerIdx, newWidth) {
-	// TODO: do some (more?) sanity checks before changing the header width
-	if (newWidth == this._headerList._width || newWidth < DwtListView.MIN_COLUMN_WIDTH)
-		return;
+AjxSoapDoc.create =
+function(method, namespace, namespaceId, soapURI) {
+	var sd = new AjxSoapDoc();
+	sd._xmlDoc = AjxXmlDoc.create();
+	var d = sd._xmlDoc.getDoc();
+	var envEl = d.createElement("soap:Envelope");
 
-	this._headerList[headerIdx]._width = newWidth;
-	this._relayout();
-}
+	if (!soapURI)
+		soapURI = AjxSoapDoc._SOAP_URI;
+	envEl.setAttribute("xmlns:soap", soapURI);
 
-// determine if col header needs padding to accomodate for scrollbars
-DwtListView.prototype._resetColWidth =
-function() {
-	if (this._headerList == null)
-		return;
-	
-	// dynamically get col idx for last column (b/c col may or may not be turned on)
-	var count = this._headerList.length-1;
-	var lastColIdx = null;
-	while (lastColIdx == null && count >= 0) {
-		if (this._headerList[count]._visible)
-			lastColIdx = count;
-		count--;
-	}
+	d.appendChild(envEl);
 
-	var lastCell = document.getElementById(this._headerList[lastColIdx]._id);
-	var div = lastCell.firstChild;
-	var scrollbarPad = 16;
-	
-	var headerWidth = this._listColDiv.clientWidth;
-	var rowWidth = this._listDiv.clientWidth;
-	
-	if (headerWidth != rowWidth) {
-		lastCell.style.width = div.style.width = this._headerList[lastColIdx]._width
-			? (this._headerList[lastColIdx]._width + scrollbarPad)
-			: (lastCell.clientWidth + scrollbarPad);
-	} else {
-		lastCell.style.width = div.style.width = (this._headerList[lastColIdx]._width || "");
-	}
-}
+	var bodyEl = d.createElement("soap:Body");
+	envEl.appendChild(bodyEl);
 
-DwtListView.prototype.size =
-function() {
-	if(this._list) {
-		return this._list.size();
-	} else {
-		return 0;
-	}
-}
+	sd._methodEl = d.createElement(method);
+	if (namespaceId == null)
+		sd._methodEl.setAttribute("xmlns", namespace);
+	else
+		sd._methodEl.setAttribute("xmlns:" + namespaceId, namespace);
 
-DwtListView.prototype.setMultiSelect = 
-function (enabled) {
-	this._multiSelectEnabled = enabled;
+	bodyEl.appendChild(sd._methodEl);
+	return sd;
 };
 
-DwtListView.prototype.isMultiSelectEnabled =
-function () {
-	return this._multiSelectEnabled;
+AjxSoapDoc.createFromDom =
+function(doc) {
+	var sd = new AjxSoapDoc();
+	sd._xmlDoc = AjxXmlDoc.createFromDom(doc);
+	sd._methodEl = sd._check(sd._xmlDoc);
+	return sd;
 };
 
-// safari breaks w/ clicking on scrollbar in list views so we do this:
-DwtListView.prototype.getPropagationForEvent = 
-function() {
-	if (AjxEnv.isSafari) {
-		return false;
-	} else {
-		return DwtControl.prototype.getPropagationForEvent.call(this);
-	}
-}
+AjxSoapDoc.createFromXml =
+function(xml) {
+	var sd = new AjxSoapDoc();
+	sd._xmlDoc = AjxXmlDoc.createFromXml(xml);
+	sd._methodEl = sd._check(sd._xmlDoc);
+	return sd;
+};
 
-// safari breaks w/ clicking on scrollbar in list views so we do this:
-DwtListView.prototype.getReturnValueForEvent = 
-function() {
-	if (AjxEnv.isSafari) {
-		return true;
+AjxSoapDoc.element2FaultObj =
+function(el) {
+	// If the element is not a SOAP fault, then return null
+	var faultEl = el.firstChild;
+	// Safari is bad at handling namespaces
+	if (!AjxEnv.isSafari) {
+		if (faultEl != null && faultEl.namespaceURI != AjxSoapDoc._SOAP_URI || faultEl.nodeName != (el.prefix + ":Fault"))
+			return null;
 	} else {
-		return DwtControl.prototype.getReturnValueForEvent.call(this);
+		if (faultEl != null && faultEl.nodeName != (el.prefix + ":Fault"))
+			return null;
 	}
-}
+	return new AjxSoapFault(faultEl);
+};
 
-DwtListView.prototype._addRow =
-function(row, index) {
-	// bug fix #1894 - check for childNodes length otherwise IE barfs
-	if (index != null && this._parentEl.childNodes.length > 0)
-		this._parentEl.insertBefore(row, this._parentEl.childNodes[index]);
-	else
-		this._parentEl.appendChild(row);
-}
+AjxSoapDoc.prototype.setMethodAttribute =
+function(name, value) {
+	this._methodEl.setAttribute(name, value);
+};
 
 /**
-* Renders a single item as a DIV element.
-*
-* Default implementation creates a simple div with the innerHTML set to 
-* the string value of the item.
-*/
-DwtListView.prototype._createItemHtml = 
-function(item, now, isDnDIcon) {
-	var div = document.createElement("DIV");
-	div.id = Dwt.getNextId();
-	var rowClassName = AjxBuffer.concat(this._className, "Row");
-	div._styleClass = AjxBuffer.concat("Row ",rowClassName);
-	div._selectedStyleClass = AjxBuffer.concat("Row-", DwtCssStyle.SELECTED, " ", rowClassName);
-	div._selectedDisabledStyleClass = AjxBuffer.concat("Row-", DwtCssStyle.SELECTED, "-" , DwtCssStyle.DISABLED, " ", rowClassName);
-	div.className = div._styleClass;
-	if (typeof(item) == "object") {
-		div.innerHTML = AjxStringUtil.htmlEncode(item.toString());
-	} else {
-		div.innerHTML = AjxStringUtil.htmlEncode(String(item));
+ * Creates arguments to pass within the envelope.  "value" can be a JS object
+ * or a scalar (string, number, etc.).
+ *
+ * When "value" is a JS object, set() will call itself recursively in order to
+ * create a complex data structure.  Don't pass a "way-too-complicated" object
+ * ("value" should only contain references to simple JS objects, or better put,
+ * hashes--don't include a reference to the "window" object as it will kill
+ * your browser).
+ *
+ * Example:
+ *
+ *    soapDoc.set("user_auth", {
+ *       user_name : "foo",
+ *       password  : "bar"
+ *    });
+ *
+ * will create an XML like this under the method tag:
+ *
+ *    <user_auth>
+ *      <user_name>foo</user_name>
+ *      <password>bar</password>
+ *    </user_auth>
+ *
+ * Of course, nesting other hashes is allowed and will work as expected.
+ *
+ * NOTE: you can pass null for "name", in which case "value" is expected to be
+ * an object whose properties will be created directly under the method el.
+ */
+AjxSoapDoc.prototype.set = 
+function(name, value, parent) {
+	var	doc = this.getDoc();
+	var	p = name
+		? doc.createElement(name)
+		: doc.createDocumentFragment();
+
+	if (value != null) {
+		if (typeof value == "object") {
+			for (i in value)
+				this.set(i, value[i], p);
+		} else {
+			if (AjxEnv.isSafari) value = AjxStringUtil.xmlEncode(value);
+			p.appendChild(doc.createTextNode(value));
+		}
 	}
-	this.associateItemWithElement(item, div, DwtListView.TYPE_LIST_ITEM);
-	return div;
-}
+	if (!parent)
+		parent = this._methodEl;
+	return parent.appendChild(p);
+};
 
-DwtListView.prototype._setNoResultsHtml = 
+AjxSoapDoc.prototype.getMethod =
 function() {
-	var htmlArr = new Array(5);
-	var	div = document.createElement("div");
-	var idx = 0;
-
-	htmlArr[idx++] = "<table width='100%' cellspacing='0' cellpadding='1'>";
-	htmlArr[idx++] = "<tr><td class='NoResults'><br>";
-	htmlArr[idx++] = AjxMsg.noResults;
-	htmlArr[idx++] = "</td></tr></table>";
-
-	div.innerHTML = htmlArr.join("");
+	return this._methodEl;
+};
 
-	this._addRow(div);
-}
+AjxSoapDoc.prototype.createHeaderElement =
+function() {
+	var d = this._xmlDoc.getDoc();
+	var envEl = d.firstChild;
+	var header = this.getHeader();
+	if (header != null) {
+		throw new AjxSoapException("SOAP header already exists", AjxSoapException.ELEMENT_EXISTS, "AjxSoapDoc.prototype.createHeaderElement");
+	}
+	header = d.createElement("soap:Header")
+	envEl.insertBefore(header, envEl.firstChild);
+	return header;
+};
 
-DwtListView.prototype.addSelectionListener = 
-function(listener) {
-	this._evtMgr.addListener(DwtEvent.SELECTION, listener);
-}
+AjxSoapDoc.prototype.getHeader =
+function() {
+	// would love to use getElementsByTagNameNS, but IE does not support it
+	var d = this._xmlDoc.getDoc();
+	var nodeList = AjxEnv.isIE
+		? (d.getElementsByTagName(d.firstChild.prefix + ":Header"))
+		: (d.getElementsByTagNameNS(AjxSoapDoc._SOAP_URI, "Header"));
 
-DwtListView.prototype.removeSelectionListener = 
-function(listener) {
-	this._evtMgr.removeListener(DwtEvent.SELECTION, listener);    	
-}
+	return nodeList ? nodeList[0] : null;
+};
 
-DwtListView.prototype.addActionListener = 
-function(listener) {
-	this._evtMgr.addListener(DwtEvent.ACTION, listener);
-}
+AjxSoapDoc.prototype.getBody =
+function() {
+	// would love to use getElementsByTagNameNS, but IE does not support it
+	var d = this._xmlDoc.getDoc();
+	var nodeList = AjxEnv.isIE
+		? (d.getElementsByTagName(d.firstChild.prefix + ":Body"))
+		: (d.getElementsByTagNameNS(AjxSoapDoc._SOAP_URI, "Body"));
 

[... 7650 lines stripped ...]