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/16 20:18:12 UTC

svn commit: r432019 [6/7] - in /incubator/xap/trunk/dist: dojo.js xapcore.js zimbra.js

Added: incubator/xap/trunk/dist/zimbra.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/dist/zimbra.js?rev=432019&view=auto
==============================================================================
--- incubator/xap/trunk/dist/zimbra.js (added)
+++ incubator/xap/trunk/dist/zimbra.js Wed Aug 16 13:18:11 2006
@@ -0,0 +1,31843 @@
+function launch() {
+	// DBG = new AjxDebug( AjxDebug.NONE, null, false );
+}
+// AjxCore.addOnloadListener( launch );
+
+// Basename: /msgs/I18nMsg
+function I18nMsg(){}
+
+I18nMsg["currencyCode"] = "USD";
+I18nMsg["currencySymbol"] = "$";
+I18nMsg["eraAD"] = "AD";
+I18nMsg["eraBC"] = "BC";
+I18nMsg["firstDayOfWeek"] = "1";
+I18nMsg["formatDateFull"] = "EEEE, MMMM d, yyyy";
+I18nMsg["formatDateLong"] = "MMMM d, yyyy";
+I18nMsg["formatDateMedium"] = "MMM d, yyyy";
+I18nMsg["formatDateShort"] = "M/d/yy";
+I18nMsg["formatDateTime"] = "{0} {1}";
+I18nMsg["formatNumber"] = "#,##0.###";
+I18nMsg["formatNumberCurrency"] = "\u00a4#,##0.00;(\u00a4#,##0.00)";
+I18nMsg["formatNumberInteger"] = "#,##0";
+I18nMsg["formatNumberPercent"] = "#,##0%";
+I18nMsg["formatTimeFull"] = "h:mm:ss a z";
+I18nMsg["formatTimeLong"] = "h:mm:ss a z";
+I18nMsg["formatTimeMedium"] = "h:mm:ss a";
+I18nMsg["formatTimeShort"] = "h:mm a";
+I18nMsg["monthAprLong"] = "April";
+I18nMsg["monthAprMedium"] = "Apr";
+I18nMsg["monthAugLong"] = "August";
+I18nMsg["monthAugMedium"] = "Aug";
+I18nMsg["monthDecLong"] = "December";
+I18nMsg["monthDecMedium"] = "Dec";
+I18nMsg["monthFebLong"] = "February";
+I18nMsg["monthFebMedium"] = "Feb";
+I18nMsg["monthJanLong"] = "January";
+I18nMsg["monthJanMedium"] = "Jan";
+I18nMsg["monthJulLong"] = "July";
+I18nMsg["monthJulMedium"] = "Jul";
+I18nMsg["monthJunLong"] = "June";
+I18nMsg["monthJunMedium"] = "Jun";
+I18nMsg["monthMarLong"] = "March";
+I18nMsg["monthMarMedium"] = "Mar";
+I18nMsg["monthMayLong"] = "May";
+I18nMsg["monthMayMedium"] = "May";
+I18nMsg["monthNovLong"] = "November";
+I18nMsg["monthNovMedium"] = "Nov";
+I18nMsg["monthOctLong"] = "October";
+I18nMsg["monthOctMedium"] = "Oct";
+I18nMsg["monthSepLong"] = "September";
+I18nMsg["monthSepMedium"] = "Sep";
+I18nMsg["numberInfinity"] = "\u221e";
+I18nMsg["numberNaN"] = "\ufffd";
+I18nMsg["numberSeparatorDecimal"] = ".";
+I18nMsg["numberSeparatorGrouping"] = ",";
+I18nMsg["numberSeparatorMoneyDecimal"] = ".";
+I18nMsg["numberSignMinus"] = "-";
+I18nMsg["numberSignPerMill"] = "\u2030";
+I18nMsg["numberSignPercent"] = "%";
+I18nMsg["numberZero"] = "0";
+I18nMsg["periodAm"] = "AM";
+I18nMsg["periodPm"] = "PM";
+I18nMsg["timezoneMapAfrica/Algiers"] = "(GMT+01.00) West Central Africa";
+I18nMsg["timezoneMapAfrica/Cairo"] = "(GMT+02.00) Cairo";
+I18nMsg["timezoneMapAfrica/Casablanca"] = "(GMT) Casablanca / Monrovia";
+I18nMsg["timezoneMapAfrica/Harare"] = "(GMT+02.00) Harare / Pretoria";
+I18nMsg["timezoneMapAfrica/Nairobi"] = "(GMT+03.00) Nairobi";
+I18nMsg["timezoneMapAmerica/Bogota"] = "(GMT-05.00) Bogota / Lima / Quito";
+I18nMsg["timezoneMapAmerica/Buenos_Aires"] = "(GMT-03.00) Buenos Aires / Georgetown";
+I18nMsg["timezoneMapAmerica/Caracas"] = "(GMT-04.00) Caracas / La Paz";
+I18nMsg["timezoneMapAmerica/Godthab"] = "(GMT-03.00) Greenland";
+I18nMsg["timezoneMapAmerica/Santiago"] = "(GMT-04.00) Santiago";
+I18nMsg["timezoneMapAsia/Aqtobe"] = "(GMT+05.00) Ekaterinburg";
+I18nMsg["timezoneMapAsia/Baghdad"] = "(GMT+03.00) Baghdad";
+I18nMsg["timezoneMapAsia/Baku"] = "(GMT+04.00) Baku / Tbilisi / Yerevan";
+I18nMsg["timezoneMapAsia/Bangkok"] = "(GMT+07.00) Bangkok / Hanoi / Jakarta";
+I18nMsg["timezoneMapAsia/Calcutta"] = "(GMT+05.30) Chennai / Kolkata / Mumbai / New Delhi";
+I18nMsg["timezoneMapAsia/Colombo"] = "(GMT+06.00) Sri Jayawardenepura";
+I18nMsg["timezoneMapAsia/Dhaka"] = "(GMT+06.00) Astana / Dhaka";
+I18nMsg["timezoneMapAsia/Hong_Kong"] = "(GMT+08.00) Beijing / Chongqing / Hong Kong / Urumqi";
+I18nMsg["timezoneMapAsia/Irkutsk"] = "(GMT+08.00) Irkutsk / Ulaan Bataar";
+I18nMsg["timezoneMapAsia/Jerusalem"] = "(GMT+02.00) Jerusalem";
+I18nMsg["timezoneMapAsia/Kabul"] = "(GMT+04.30) Kabul";
+I18nMsg["timezoneMapAsia/Karachi"] = "(GMT+05.00) Islamabad / Karachi / Tashkent";
+I18nMsg["timezoneMapAsia/Katmandu"] = "(GMT+05.45) Kathmandu";
+I18nMsg["timezoneMapAsia/Krasnoyarsk"] = "(GMT+07.00) Krasnoyarsk";
+I18nMsg["timezoneMapAsia/Kuala_Lumpur"] = "(GMT+08.00) Kuala Lumpur / Singaporev";
+I18nMsg["timezoneMapAsia/Kuwait"] = "(GMT+03.00) Kuwait / Riyadh";
+I18nMsg["timezoneMapAsia/Magadan"] = "(GMT+11.00) Magadan / Solomon Is. / New Calenodia";
+I18nMsg["timezoneMapAsia/Muscat"] = "(GMT+04.00) Abu Dhabi / Muscat";
+I18nMsg["timezoneMapAsia/Novosibirsk"] = "(GMT+06.00) Almaty / Novosibirsk";
+I18nMsg["timezoneMapAsia/Rangoon"] = "(GMT+06.30) Rangoon";
+I18nMsg["timezoneMapAsia/Seoul"] = "(GMT+09.00) Seoul";
+I18nMsg["timezoneMapAsia/Taipei"] = "(GMT+08.00) Taipei";
+I18nMsg["timezoneMapAsia/Tehran"] = "(GMT+03.30) Tehran";
+I18nMsg["timezoneMapAsia/Tokyo"] = "(GMT+09.00) Osaka / Sapporo / Tokyo";
+I18nMsg["timezoneMapAsia/Vladivostok"] = "(GMT+10.00) Vladivostok";
+I18nMsg["timezoneMapAsia/Yakutsk"] = "(GMT+09.00) Yakutsk";
+I18nMsg["timezoneMapAtlantic/Azores"] = "(GMT-01.00) Azores";
+I18nMsg["timezoneMapAtlantic/Cape_Verde"] = "(GMT-01.00) Cape Verde Is.";
+I18nMsg["timezoneMapAustralia/Adelaide"] = "(GMT+09.30) Adelaide";
+I18nMsg["timezoneMapAustralia/Brisbane"] = "(GMT+10.00) Brisbane";
+I18nMsg["timezoneMapAustralia/Darwin"] = "(GMT+09.30) Darwin";
+I18nMsg["timezoneMapAustralia/Hobart"] = "(GMT+10.00) Hobart";
+I18nMsg["timezoneMapAustralia/Perth"] = "(GMT+08.00) Perth";
+I18nMsg["timezoneMapAustralia/Sydney"] = "(GMT+10.00) Canberra / Melbourne / Sydney";
+I18nMsg["timezoneMapBrazil/East"] = "(GMT-03.00) Brasilia";
+I18nMsg["timezoneMapCanada/Eastern"] = "(GMT-04.00) Atlantic Time (Canada)";
+I18nMsg["timezoneMapCanada/Newfoundland"] = "(GMT-03.30) Newfoundlan";
+I18nMsg["timezoneMapCanada/Saskatchewan"] = "(GMT-06.00) Saskatchewan";
+I18nMsg["timezoneMapEurope/Athens"] = "(GMT+02.00) Athens / Beirut / Istanbul / Minsk";
+I18nMsg["timezoneMapEurope/Berlin"] = "(GMT+01.00) Amsterdam / Berlin / Bern / Rome / Stockholm / Vienna";
+I18nMsg["timezoneMapEurope/London"] = "(GMT) Greenwich Mean Time - Dublin / Edinburgh / Lisbon / London";
+I18nMsg["timezoneMapEurope/Moscow"] = "(GMT+03.00) Moscow / St. Petersburg / Volgograd";
+I18nMsg["timezoneMapPacific/Auckland"] = "(GMT+12.00) Auckland / Wellington";
+I18nMsg["timezoneMapPacific/Fiji"] = "(GMT+12.00) Fiji / Kamchatka / Marshall Is.";
+I18nMsg["timezoneMapPacific/Guam"] = "(GMT+10.00) Guam / Port Moresby";
+I18nMsg["timezoneMapPacific/Midway"] = "(GMT-11.00) Midway Island / Samoa";
+I18nMsg["timezoneMapPacific/Tongatapu"] = "(GMT+13.00) Nuku'alofa";
+I18nMsg["timezoneMapUS/Alaska"] = "(GMT-09.00) Alaska";
+I18nMsg["timezoneMapUS/Arizona"] = "(GMT-07.00) Arizona";
+I18nMsg["timezoneMapUS/Central"] = "(GMT-06.00) Central Time (US & Canada)";
+I18nMsg["timezoneMapUS/East-Indiana"] = "(GMT-05.00) Indiana (East)";
+I18nMsg["timezoneMapUS/Eastern"] = "(GMT-05.00) Eastern Time (US & Canada)";
+I18nMsg["timezoneMapUS/Hawaii"] = "(GMT-10.00) Hawaii";
+I18nMsg["timezoneMapUS/Mountain"] = "(GMT-07.00) Mountain Time (US & Canada)";
+I18nMsg["timezoneMapUS/Pacific"] = "(GMT-08.00) Pacific Time (US & Canada) / Tijuana";
+I18nMsg["timezoneNameAfrica/Algiers"] = "Central European Time";
+I18nMsg["timezoneNameAfrica/Cairo"] = "Eastern European Time";
+I18nMsg["timezoneNameAfrica/Casablanca"] = "Western European Time";
+I18nMsg["timezoneNameAfrica/Harare"] = "Central African Time";
+I18nMsg["timezoneNameAfrica/Nairobi"] = "Eastern African Time";
+I18nMsg["timezoneNameAmerica/Bogota"] = "Colombia Time";
+I18nMsg["timezoneNameAmerica/Buenos_Aires"] = "Argentine Time";
+I18nMsg["timezoneNameAmerica/Caracas"] = "Venezuela Time";
+I18nMsg["timezoneNameAmerica/Godthab"] = "Western Greenland Time";
+I18nMsg["timezoneNameAmerica/Santiago"] = "Chile Time";
+I18nMsg["timezoneNameAsia/Aqtobe"] = "Aqtobe Time";
+I18nMsg["timezoneNameAsia/Baghdad"] = "Arabia Standard Time";
+I18nMsg["timezoneNameAsia/Baku"] = "Azerbaijan Time";
+I18nMsg["timezoneNameAsia/Bangkok"] = "Indochina Time";
+I18nMsg["timezoneNameAsia/Calcutta"] = "India Standard Time";
+I18nMsg["timezoneNameAsia/Colombo"] = "Sri Lanka Time";
+I18nMsg["timezoneNameAsia/Dhaka"] = "Bangladesh Time";
+I18nMsg["timezoneNameAsia/Hong_Kong"] = "Hong Kong Time";
+I18nMsg["timezoneNameAsia/Irkutsk"] = "Irkutsk Time";
+I18nMsg["timezoneNameAsia/Jerusalem"] = "Israel Standard Time";
+I18nMsg["timezoneNameAsia/Kabul"] = "Afghanistan Time";
+I18nMsg["timezoneNameAsia/Karachi"] = "Pakistan Time";
+I18nMsg["timezoneNameAsia/Katmandu"] = "Nepal Time";
+I18nMsg["timezoneNameAsia/Krasnoyarsk"] = "Krasnoyarsk Time";
+I18nMsg["timezoneNameAsia/Kuala_Lumpur"] = "Malaysia Time";
+I18nMsg["timezoneNameAsia/Kuwait"] = "Arabia Standard Time";
+I18nMsg["timezoneNameAsia/Magadan"] = "Magadan Time";
+I18nMsg["timezoneNameAsia/Muscat"] = "Gulf Standard Time";
+I18nMsg["timezoneNameAsia/Novosibirsk"] = "Novosibirsk Time";
+I18nMsg["timezoneNameAsia/Rangoon"] = "Myanmar Time";
+I18nMsg["timezoneNameAsia/Seoul"] = "Korea Standard Time";
+I18nMsg["timezoneNameAsia/Taipei"] = "China Standard Time";
+I18nMsg["timezoneNameAsia/Tehran"] = "Iran Standard Time";
+I18nMsg["timezoneNameAsia/Tokyo"] = "Japan Standard Time";
+I18nMsg["timezoneNameAsia/Vladivostok"] = "Vladivostok Time";
+I18nMsg["timezoneNameAsia/Yakutsk"] = "Yakutsk Time";
+I18nMsg["timezoneNameAtlantic/Azores"] = "Azores Time";
+I18nMsg["timezoneNameAtlantic/Cape_Verde"] = "Cape Verde Time";
+I18nMsg["timezoneNameAustralia/Adelaide"] = "Central Standard Time (South Australia)";
+I18nMsg["timezoneNameAustralia/Brisbane"] = "Eastern Standard Time (Queensland)";
+I18nMsg["timezoneNameAustralia/Darwin"] = "Central Standard Time (Northern Territory)";
+I18nMsg["timezoneNameAustralia/Hobart"] = "Eastern Standard Time (Tasmania)";
+I18nMsg["timezoneNameAustralia/Perth"] = "Western Standard Time (Australia)";
+I18nMsg["timezoneNameAustralia/Sydney"] = "Eastern Standard Time (New South Wales)";
+I18nMsg["timezoneNameBrazil/East"] = "Brazil Time";
+I18nMsg["timezoneNameCanada/Eastern"] = "Eastern Standard Time";
+I18nMsg["timezoneNameCanada/Newfoundland"] = "Newfoundland Standard Time";
+I18nMsg["timezoneNameCanada/Saskatchewan"] = "Central Standard Time";
+I18nMsg["timezoneNameEurope/Athens"] = "Eastern European Time";
+I18nMsg["timezoneNameEurope/Berlin"] = "Central European Time";
+I18nMsg["timezoneNameEurope/London"] = "Greenwich Mean Time";
+I18nMsg["timezoneNameEurope/Moscow"] = "Moscow Standard Time";
+I18nMsg["timezoneNamePacific/Auckland"] = "New Zealand Standard Time";
+I18nMsg["timezoneNamePacific/Fiji"] = "Fiji Time";
+I18nMsg["timezoneNamePacific/Guam"] = "Chamorro Standard Time";
+I18nMsg["timezoneNamePacific/Midway"] = "Samoa Standard Time";
+I18nMsg["timezoneNamePacific/Tongatapu"] = "Tonga Time";
+I18nMsg["timezoneNameUS/Alaska"] = "Alaska Standard Time";
+I18nMsg["timezoneNameUS/Arizona"] = "Mountain Standard Time";
+I18nMsg["timezoneNameUS/Central"] = "Central Standard Time";
+I18nMsg["timezoneNameUS/East-Indiana"] = "Eastern Standard Time";
+I18nMsg["timezoneNameUS/Eastern"] = "Eastern Standard Time";
+I18nMsg["timezoneNameUS/Hawaii"] = "Hawaii Standard Time";
+I18nMsg["timezoneNameUS/Mountain"] = "Mountain Standard Time";
+I18nMsg["timezoneNameUS/Pacific"] = "Pacific Standard Time";
+I18nMsg["weekdayFriLong"] = "Friday";
+I18nMsg["weekdayFriMedium"] = "Fri";
+I18nMsg["weekdayMonLong"] = "Monday";
+I18nMsg["weekdayMonMedium"] = "Mon";
+I18nMsg["weekdaySatLong"] = "Saturday";
+I18nMsg["weekdaySatMedium"] = "Sat";
+I18nMsg["weekdaySunLong"] = "Sunday";
+I18nMsg["weekdaySunMedium"] = "Sun";
+I18nMsg["weekdayThuLong"] = "Thursday";
+I18nMsg["weekdayThuMedium"] = "Thu";
+I18nMsg["weekdayTueLong"] = "Tuesday";
+I18nMsg["weekdayTueMedium"] = "Tue";
+I18nMsg["weekdayWedLong"] = "Wednesday";
+I18nMsg["weekdayWedMedium"] = "Wed";
+
+// Basename: /msgs/AjxMsg
+function AjxMsg(){}
+
+AjxMsg["XfnumberLessThanMin"] = "Value must be greater than or equal to {0}.";
+AjxMsg["_close"] = "Close";
+AjxMsg["_finish"] = "Finish";
+AjxMsg["_next"] = "Next";
+AjxMsg["_prev"] = "Previous";
+AjxMsg["add"] = "Add";
+AjxMsg["addAll"] = "Add All";
+AjxMsg["ago"] = "ago";
+AjxMsg["cancel"] = "Cancel";
+AjxMsg["cancelRequest"] = "Cancel Request";
+AjxMsg["confirmTitle"] = "Confirmation";
+AjxMsg["criticalMsg"] = "Critical";
+AjxMsg["dateParsing2DigitStartYear"] = "1936";
+AjxMsg["day"] = "day";
+AjxMsg["days"] = "days";
+AjxMsg["detail"] = "Detail";
+AjxMsg["didNotMatchChoice"] = "Value '$0' did not match any values for this type.";
+AjxMsg["dismiss"] = "Dismiss";
+AjxMsg["first"] = "first";
+AjxMsg["formatCalDate"] = "EEE, MMM d";
+AjxMsg["formatCalDateFull"] = "EEEE, MMMM d, yyyy";
+AjxMsg["formatCalDateLong"] = "EEEE, MMMM d";
+AjxMsg["formatCalDay"] = "M/d ";
+AjxMsg["formatCalMonth"] = "MMMM yyyy";
+AjxMsg["formatDateMediumNoYear"] = "MMM dd ";
+AjxMsg["fourth"] = "fourth";
+AjxMsg["hour"] = "hour";
+AjxMsg["hours"] = "hours";
+AjxMsg["infoMsg"] = "Informational";
+AjxMsg["invalidDateString"] = "Date value must be entered in the form: MM/DD/YYYY or \"today\", \"yesterday\" or \"tomorrow\".";
+AjxMsg["invalidDatetimeString"] = "Date format not understood.";
+AjxMsg["invalidTimeString"] = "Time value must be entered in the form: HH:MM[:SS] [AM|PM]";
+AjxMsg["last"] = "last";
+AjxMsg["minute"] = "minute";
+AjxMsg["minutes"] = "minutes";
+AjxMsg["month"] = "month";
+AjxMsg["monthAprShort"] = "A";
+AjxMsg["monthAugShort"] = "A";
+AjxMsg["monthDecShort"] = "D";
+AjxMsg["monthFebShort"] = "F";
+AjxMsg["monthJanShort"] = "J";
+AjxMsg["monthJulShort"] = "J";
+AjxMsg["monthJunShort"] = "J";
+AjxMsg["monthMarShort"] = "M";
+AjxMsg["monthMayShort"] = "M";
+AjxMsg["monthNovShort"] = "N";
+AjxMsg["monthOctShort"] = "O";
+AjxMsg["monthSepShort"] = "S";
+AjxMsg["months"] = "months";
+AjxMsg["no"] = "No";
+AjxMsg["noResults"] = "No results found.";
+AjxMsg["notANumber"] = "Value must be a number.";
+AjxMsg["notAString"] = "Value must be a text string.";
+AjxMsg["notAnInteger"] = "Value must be an integer.";
+AjxMsg["numberFractionExceeded"] = "Fractional digits exceeds total of {0}.";
+AjxMsg["numberLessThanEqualMin"] = "Value must be greater than {0}.";
+AjxMsg["numberLessThanMin"] = "Value must be greater than or equal to {0}.";
+AjxMsg["numberMoreThanEqualMax"] = "Value must be less than {0}.";
+AjxMsg["numberMoreThanMax"] = "Value must be less than or equal to {0}.";
+AjxMsg["numberMustBeNon0Percent"] = "Value must be a percentage between 1 and 100";
+AjxMsg["numberTotalExceeded"] = "Whole digits exceeds total of {0}.";
+AjxMsg["ok"] = "OK";
+AjxMsg["remove"] = "Remove";
+AjxMsg["removeAll"] = "Remove All";
+AjxMsg["second"] = "second";
+AjxMsg["seconds"] = "seconds";
+AjxMsg["stringLenWrong"] = "Value must be exactly {0} characters long.";
+AjxMsg["stringMismatch"] = "Value did not match valid values.";
+AjxMsg["stringTooLong"] = "Value must be no more than {0} characters long.";
+AjxMsg["stringTooShort"] = "Value must be at least {0} characters long.";
+AjxMsg["third"] = "third";
+AjxMsg["today"] = "today";
+AjxMsg["tomorrow"] = "tomorrow";
+AjxMsg["valueIsRequired"] = "Value is required";
+AjxMsg["warningMsg"] = "Warning";
+AjxMsg["week"] = "week";
+AjxMsg["weekdayFriShort"] = "F";
+AjxMsg["weekdayMonShort"] = "M";
+AjxMsg["weekdaySatShort"] = "S";
+AjxMsg["weekdaySunShort"] = "S";
+AjxMsg["weekdayThuShort"] = "T";
+AjxMsg["weekdayTueShort"] = "T";
+AjxMsg["weekdayWedShort"] = "W";
+AjxMsg["weeks"] = "weeks";
+AjxMsg["workInProgress"] = "Work In Progress";
+AjxMsg["xFnumberMoreThanMax"] = "Value must be less than or equal to {0}.";
+AjxMsg["xformDateTimeFormat"] = "{0,date} at {0,time}";
+AjxMsg["xformRepeatAdd"] = "+";
+AjxMsg["xformRepeatRemove"] = "-";
+AjxMsg["year"] = "year";
+AjxMsg["years"] = "years";
+AjxMsg["yes"] = "Yes";
+AjxMsg["yesterday"] = "yesterday";
+
+/*
+* Conventions
+*
+* - Classes that start with "Dwt" have a corollary Javascript object.
+* - Use one line if there is only one selector and one declaration. Otherwise, indent each declaration on its own line.
+* - Group selectors to avoid repetition of styles, as appropriate (ie group within a section). That means you may have
+*   to look at more than one definition to figure out all the applicable styles, but it lets you give the styles a 
+*   hierarchy. That way, you're more likely to need to change a style in just one place.
+* - Use shorthand styles when possible (font, margin, padding, etc).
+* - When grouping selectors that correspond to our Javascript objects, show inheritance by using a different line for
+*   each level of inheritance. CSS doesn't care about our object hierarchy, but doing that enhances readability.
+* - Use decimal RGB values for colors that don't have names.
+* - Modifiers are lower case, whether they're a class (eg .activated) or tacked on (eg -selected).
+*
+* Classes are laid out in the following general order:
+*	- HTML elements
+*	- General app stuff (shell, overlays, banner)
+*	- Widgets that tend toward abstract (minimal subclassing), such as tool tips and sashes
+*	- Heavier use widgets such as buttons and dialogs
+*		- General widget stuff, then specialized subclasses
+*	- List views, with common stuff first
+*	- Other views (lots of them)
+*	- Miscellaneous stuff that multiple apps might use (objects, autocomplete)
+*	- Modifiers
+*
+* Many of the Dwt widgets don't have corresponding classes here, since they are only subclassed. If you create and
+* display one of those widgets, you'll have to add a class for it.
+*/
+
+/* 
+* HTML elements - use for global declarations
+*/
+
+/* Global ELEMENT declarations */
+
+function ExMsg() {}
+/*
+* ***** 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 AjxEnv() {
+}
+
+AjxEnv._inited = false;
+
+
+AjxEnv.reset = function () {
+	AjxEnv.browserVersion = -1;
+	AjxEnv.geckoDate = 0;
+	AjxEnv.mozVersion = -1;
+	AjxEnv.isMac = false;
+	AjxEnv.isWindows = false;
+	AjxEnv.isLinux = false;
+	AjxEnv.isNav  = false;
+	AjxEnv.isIE = false;
+	AjxEnv.isNav4 = false;
+	AjxEnv.trueNs = true;
+	AjxEnv.isNav6 = false;
+	AjxEnv.isNav6up = false;
+	AjxEnv.isNav7 = false;
+	AjxEnv.isIE3 = false;
+	AjxEnv.isIE4 = false;
+	AjxEnv.isIE4up = false;
+	AjxEnv.isIE5 = false;
+	AjxEnv.isIE5_5 = false;
+	AjxEnv.isIE5up = false;
+	AjxEnv.isIE5_5up = false;
+	AjxEnv.isIE6  = false;
+	AjxEnv.isIE6up = false;
+	AjxEnv.isNormalResolution = false;
+	AjxEnv.ieScaleFactor = 1;
+	AjxEnv.isFirefox = false;
+	AjxEnv.isFirefox1up = false;
+	AjxEnv.isFirefox1_5up = false;
+	AjxEnv.isMozilla = false;
+	AjxEnv.isMozilla1_4up = false;
+	AjxEnv.isSafari = false;
+	AjxEnv.isGeckoBased = false;
+	AjxEnv.isOpera = false;
+	AjxEnv.useTransparentPNGs = false;
+
+	// screen resolution - ADD MORE RESOLUTION CHECKS AS NEEDED HERE:
+	AjxEnv.is800x600orLower = screen.width <= 800 && screen.height <= 600;
+};
+
+AjxEnv.parseUA = function (userAgent) {
+	var agt = userAgent.toLowerCase();
+	var agtArr = agt.split(" ");
+	var i = 0;
+	var index = -1;
+	var token = null;
+	var isSpoofer = false;
+	var isWebTv = false;
+	var isHotJava = false;
+	var beginsWithMozilla = false;
+	var isCompatible = false;
+	if (agtArr != null) {
+		if ( (index = agtArr[0].search(/^\s*mozilla\//) )!= -1){
+			beginsWithMozilla = true;
+			AjxEnv.browserVersion = parseFloat(agtArr[0].substring(index + 8));
+			AjxEnv.isNav = true;
+		}
+		for ( ; i < agtArr.length; ++i ){
+			token = agtArr[i];
+			if (token.indexOf('compatible') != -1 ) {
+				isCompatible = true;
+				AjxEnv.isNav = false;
+			} else if ((token.indexOf('opera')) != -1){
+				AjxEnv.isOpera = true;
+				AjxEnv.isNav = false;
+				AjxEnv.browserVersion = parseFloat(agtArr[i+1]);
+			} else if ((token.indexOf('spoofer')) != -1){
+				isSpoofer = true;
+				AjxEnv.isNav = false;
+			} else if ((token.indexOf('webtv')) != -1) {
+				isWebTv = true;
+				AjxEnv.isNav = false;
+			} else if ((token.indexOf('hotjava')) != -1) {
+				isHotJava = true;
+				AjxEnv.isNav = false;
+			} else if ((index = token.indexOf('msie')) != -1) {
+				AjxEnv.isIE = true;
+				AjxEnv.browserVersion = parseFloat(agtArr[i+1]);
+			} else if ((index = token.indexOf('gecko/')) != -1){
+				AjxEnv.isGeckoBased = true;
+				AjxEnv.geckoDate = parseFloat(token.substr(index + 6));
+			} else if ((index = token.indexOf('rv:')) != -1){
+				AjxEnv.mozVersion = parseFloat(token.substr(index + 3));
+				AjxEnv.browserVersion = AjxEnv.mozVersion;
+			} else if ((index = token.indexOf('firefox/')) != -1){
+				AjxEnv.isFirefox = true;
+				AjxEnv.browserVersion = parseFloat(token.substr(index + 8));
+			} else if ((index = token.indexOf('netscape6/')) != -1){
+				AjxEnv.trueNs = true;
+				AjxEnv.browserVersion = parseFloat(token.substr(index + 10));
+			} else if ((index = token.indexOf('netscape/')) != -1){
+				AjxEnv.trueNs = true;
+				AjxEnv.browserVersion = parseFloat(token.substr(index + 9));
+			} else if ((index = token.indexOf('safari/')) != -1){
+				AjxEnv.isSafari = true;
+				AjxEnv.browserVersion = parseFloat(token.substr(index + 7));
+			} else if (token.indexOf('windows') != -1){
+				AjxEnv.isWindows = true;
+			} else if ((token.indexOf('macintosh') != -1) ||
+					   (token.indexOf('mac_') != -1)){
+				AjxEnv.isMac = true;
+			} else if (token.indexOf('linux') != -1){
+				AjxEnv.isLinux = true;
+			}
+		}
+		// Note: Opera and WebTV spoof Navigator.  
+		// We do strict client detection.
+		AjxEnv.isNav  = (beginsWithMozilla && !isSpoofer && !isCompatible && 
+						!AjxEnv.isOpera && !isWebTv && !isHotJava &&
+						!AjxEnv.isSafari);
+
+		AjxEnv.isIE = (AjxEnv.isIE && !AjxEnv.isOpera);
+
+		AjxEnv.isNav4 = (AjxEnv.isNav && (AjxEnv.browserVersion  == 4) &&
+						(!AjxEnv.isIE));
+		AjxEnv.isNav6 = (AjxEnv.isNav && AjxEnv.trueNs && 
+						(AjxEnv.browserVersion >=6.0) && 
+						(AjxEnv.browserVersion < 7.0));
+		AjxEnv.isNav6up = (AjxEnv.isNav && AjxEnv.trueNs && 
+						  (AjxEnv.browserVersion >= 6.0));
+		AjxEnv.isNav7 = (AjxEnv.isNav && AjxEnv.trueNs && 
+						(AjxEnv.browserVersion == 7.0));
+
+		AjxEnv.isIE3 = (AjxEnv.isIE && (AjxEnv.browserVersion < 4));
+		AjxEnv.isIE4 = (AjxEnv.isIE && (AjxEnv.browserVersion == 4) && 
+					 (AjxEnv.browserVersion == 4.0));
+		AjxEnv.isIE4up = (AjxEnv.isIE && (AjxEnv.browserVersion >= 4));
+		AjxEnv.isIE5 = (AjxEnv.isIE && (AjxEnv.browserVersion == 4) && 
+					 (AjxEnv.browserVersion == 5.0));
+		AjxEnv.isIE5_5 = (AjxEnv.isIE && (AjxEnv.browserVersion == 4) && 
+						 (AjxEnv.browserVersion == 5.5));
+		AjxEnv.isIE5up = (AjxEnv.isIE && (AjxEnv.browserVersion >= 5.0));
+		AjxEnv.isIE5_5up =(AjxEnv.isIE && (AjxEnv.browserVersion >= 5.5));
+		AjxEnv.isIE6  = (AjxEnv.isIE && (AjxEnv.browserVersion == 6.0));
+		AjxEnv.isIE6up = (AjxEnv.isIE && (AjxEnv.browserVersion >= 6.0));
+
+		AjxEnv.isMozilla = ((AjxEnv.isNav && AjxEnv.mozVersion && 
+							AjxEnv.isGeckoBased && (AjxEnv.geckoDate != 0)));
+		AjxEnv.isMozilla1_4up = (AjxEnv.isMozilla && (AjxEnv.mozVersion >= 1.4));
+		AjxEnv.isFirefox = ((AjxEnv.isMozilla && AjxEnv.isFirefox));
+		AjxEnv.isFirefox1up = (AjxEnv.isFirefox && AjxEnv.browserVersion >= 1.0);
+		AjxEnv.isFirefox1_5up = (AjxEnv.isFirefox && AjxEnv.browserVersion >= 1.5);
+
+	}
+	// setup some global setting we can check for high resolution
+	if (AjxEnv.isIE){
+		AjxEnv.isNormalResolution = true;
+		AjxEnv.ieScaleFactor = screen.deviceXDPI / screen.logicalXDPI;
+		if (AjxEnv.ieScaleFactor > 1) {
+			AjxEnv.isNormalResolution = false;
+		}
+	}
+	// show transparent PNGs on platforms that support them well
+	//	(eg: all but IE and Linux)
+	//	MOW: having trouble getting safari to render transparency for shadows, skipping there, too
+	AjxEnv.useTransparentPNGs = !AjxEnv.isIE && !AjxEnv.isLinux && !AjxEnv.isSafari;
+	AjxEnv._inited = !AjxEnv.isIE;
+};
+
+AjxEnv.reset();
+AjxEnv.parseUA(navigator.userAgent);
+
+// COMPATIBILITY
+
+// Safari doesn't support string.replace(/regexp/, function);
+if (AjxEnv.isSafari) {
+	if (!String.prototype._AjxOldReplace) {
+		String.prototype._AjxOldReplace = String.prototype.replace;
+		String.prototype.replace = function(re, val) {
+			if (typeof val != "function")
+				return this._AjxOldReplace(re, val);
+			else {
+				// TODO: investigate if it's possible to use the array.join approach
+				var str = this.slice(0), v, l, a;
+				while (a = re.exec(str)) {
+					v = val.apply(null, a);
+					l = a[0].length;
+					re.lastIndex -= l - v.length;
+					str = str.substr(0, a.index) + v + str.substr(a.index + l);
+					if (!re.global)
+						break;
+				}
+				return str;
+			}
+		};
+	}
+}
+/*
+* ***** 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 *****
+*/
+
+
+/**
+ * AjxUtil - static class with some utility methods. This is where to
+ * put things when no other class wants them.
+ *
+ * 12/3/2004 At this point, it only needs AjxEnv to be loaded.
+ */
+function AjxUtil () {
+};
+
+AjxUtil.FLOAT_RE = /^[+\-]?((\d+(\.\d*)?)|((\d*\.)?\d+))([eE][+\-]?\d+)?$/;
+AjxUtil.NOTFLOAT_RE = /[^\d\.]/;
+AjxUtil.NOTINT_RE = /[^0-9]+/;
+AjxUtil.LIFETIME_FIELD = /^([0-9])+([dhms])?$/;
+
+AjxUtil.isSpecified 		= function(aThing) { return ((aThing !== void 0) && (aThing !== null)); };
+AjxUtil.isUndefined 		= function(aThing) { return (aThing === void 0); };
+AjxUtil.isNull 				= function(aThing) { return (aThing === null); };
+AjxUtil.isBoolean 			= function(aThing) { return (typeof(aThing) == 'boolean'); };
+AjxUtil.isString 			= function(aThing) { return (typeof(aThing) == 'string'); };
+AjxUtil.isNumber 			= function(aThing) { return (typeof(aThing) == 'number'); };
+AjxUtil.isObject 			= function(aThing) { return ((typeof(aThing) == 'object') && (aThing !== null)); };
+AjxUtil.isArray 			= function(aThing) { return AjxUtil.isInstance(aThing, Array); };
+AjxUtil.isFunction 			= function(aThing) { return (typeof(aThing) == 'function'); };
+AjxUtil.isDate 				= function(aThing) { return AjxUtil.isInstance(aThing, Date); };
+AjxUtil.isLifeTime 			= function(aThing) { return AjxUtil.LIFETIME_FIELD.test(aThing); };
+AjxUtil.isNumeric 			= function(aThing) { return (!isNaN(parseFloat(aThing)) && AjxUtil.FLOAT_RE.test(aThing) && !AjxUtil.NOTFLOAT_RE.test(aThing)); };
+AjxUtil.isLong			    = function(aThing) { return (AjxUtil.isNumeric(aThing) && !AjxUtil.NOTINT_RE.test(aThing)); };
+AjxUtil.isNonNegativeLong   = function(aThing) { return (AjxUtil.isNumeric(aThing) && AjxUtil.isLong(aThing) && (parseFloat(aThing) >= 0)); };
+
+
+// REVISIT: Should do more precise checking. However, there are names in
+//			common use that do not follow the RFC patterns (e.g. domain
+//			names that start with digits).
+AjxUtil.IP_ADDRESS_RE = /^\d{1,3}(\.\d{1,3}){3}(\.\d{1,3}\.\d{1,3})?$/;
+AjxUtil.DOMAIN_NAME_SHORT_RE = /^[A-Za-z0-9\-]{2,}$/;
+AjxUtil.DOMAIN_NAME_FULL_RE = /^[A-Za-z0-9\-]{2,}(\.[A-Za-z0-9\-]{2,}){1,}$/;
+AjxUtil.HOST_NAME_RE = /^[A-Za-z0-9\-]{2,}(\.[A-Za-z0-9\-]{2,})*$/;
+AjxUtil.HOST_NAME_WITH_PORT_RE = /^[A-Za-z0-9\-]{2,}(\.[A-Za-z0-9\-]{2,})*:([0-9])+$/;
+AjxUtil.EMAIL_SHORT_RE = /^[^@\s]+$/;
+AjxUtil.EMAIL_FULL_RE = /^[^@\s]+@[A-Za-z0-9\-]{2,}(\.[A-Za-z0-9\-]{2,})*$/;
+AjxUtil.EMAIL_RE = /^([a-zA-Z0-9_\-])+((\.)?([a-zA-Z0-9_\-])+)*@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
+AjxUtil.SHORT_URL_RE = /^[A-Za-z0-9]{2,}:\/\/[A-Za-z0-9\-]{2,}(\.[A-Za-z0-9\-]{2,})*(:([0-9])+)*$/;
+AjxUtil.IP_SHORT_URL_RE = /^[A-Za-z0-9]{2,}:\/\/\d{1,3}(\.\d{1,3}){3}(\.\d{1,3}\.\d{1,3})?(:([0-9])+)*$/;
+
+AjxUtil.isIpAddress 		= function(s) { return AjxUtil.IP_ADDR_RE.test(s); };
+AjxUtil.isDomain 			= function(s) {	return AjxUtil.DOMAIN_RE.test(s); };
+AjxUtil.isHostName 			= function(s) { return AjxUtil.HOST_NAME_RE.test(s); };
+AjxUtil.isDomainName = 
+function(s, shortMatch) {
+	return shortMatch 
+		? AjxUtil.DOMAIN_NAME_SHORT_RE.test(s) 
+		: AjxUtil.DOMAIN_NAME_FULL_RE.test(s);
+};
+
+AjxUtil.isEmailAddress = 
+function(s, nameOnly) {
+	return nameOnly 
+		? AjxUtil.EMAIL_SHORT_RE.test(s) 
+		: AjxUtil.EMAIL_FULL_RE.test(s);
+};
+
+AjxUtil.SIZE_GIGABYTES = "GB";
+AjxUtil.SIZE_MEGABYTES = "MB";
+AjxUtil.SIZE_KILOBYTES = "KB";
+AjxUtil.SIZE_BYTES = "B";
+
+/**
+ * Formats a size (in bytes) to the largest whole unit. For example,
+ * AjxUtil.formatSize(302132199) returns "288 MB".
+ *
+ * @param size      The size (in bytes) to be formatted.
+ * @param round     True to round to nearest integer. Default is true.
+ * @param fractions Number of fractional digits to display, if not rounding.
+ *                  Trailing zeros after the decimal point are trimmed.
+ */
+AjxUtil.formatSize = 
+function(size, round, fractions) {
+	if (round == null) round = true;
+	if (fractions == null) fractions = 20; // max allowed for toFixed is 20
+
+	var units = AjxUtil.SIZE_BYTES;
+	if (size >= 1073741824) {
+		size /= 1073741824;
+		units = AjxUtil.SIZE_GIGABYTES;
+	}
+	else if (size >= 1048576) {
+		size /= 1048576;
+		units = AjxUtil.SIZE_MEGABYTES;
+	}
+	else if (size > 1023) {
+		size /= 1024;
+		units = AjxUtil.SIZE_KILOBYTES;
+	}
+
+	var formattedSize = round ? Math.round(size) : size.toFixed(fractions).replace(/\.?0+$/,"");
+	var formattedUnits = ' '+units;
+	
+	return formattedSize + formattedUnits;
+};
+
+/**
+ * Formats a size (in bytes) to a specific unit. Since the unit size is
+ * known, the unit is not shown in the returned string. For example,
+ * AjxUtil.formatSizeForUnit(302132199, AjxUtil.SIZE_MEGABYTES, false, 2) 
+ * returns "288.13".
+ *
+ * @param size      The size (in bytes) to be formatted.
+ * @param units     The unit of measure.
+ * @param round     True to round to nearest integer. Default is true.
+ * @param fractions Number of fractional digits to display, if not rounding.
+ *                  Trailing zeros after the decimal point are trimmed.
+ */
+AjxUtil.formatSizeForUnits = 
+function(size, units, round, fractions) {
+	if (units == null) units = AjxUtil.SIZE_BYTES;
+	if (round == null) round = true;
+	if (fractions == null) fractions = 20; // max allowed for toFixed is 20
+
+	switch (units) {
+		case AjxUtil.SIZE_GIGABYTES: { size /= 1073741824; break; }
+		case AjxUtil.SIZE_MEGABYTES: { size /= 1048576; break; }
+		case AjxUtil.SIZE_KILOBYTES: { size /= 1024; break; }
+	}
+	
+	var formattedSize = round ? Math.round(size) : size.toFixed(fractions).replace(/\.?0+$/,"");
+	return formattedSize;
+};
+
+/**
+ * Performs the opposite of AjxUtil.formatSize in that this function takes a 
+ * formatted size.
+ *
+ * @param units Unit constant: "GB", "MB", "KB", "B". Must be specified 
+ *              unless the formatted size ends with the size marker, in
+ *				which case the size marker in the formattedSize param
+ *				overrides this parameter.
+ */
+AjxUtil.parseSize = 
+function(formattedSize, units) {
+	// NOTE: Take advantage of fact that parseFloat ignores bad chars
+	//       after numbers
+	var size = parseFloat(formattedSize.replace(/^\s*/,""));
+
+	var marker = /[GMK]?B$/i;
+	var result = marker.exec(formattedSize);
+	if (result) {
+		//alert("units: "+units+", result[0]: '"+result[0]+"'");
+		units = result[0].toUpperCase();
+	}
+	
+	switch (units) {
+		case AjxUtil.SIZE_GIGABYTES: size *= 1073741824; break;
+		case AjxUtil.SIZE_MEGABYTES: size *= 1048576; break; 
+		case AjxUtil.SIZE_KILOBYTES: size *= 1024; break;
+	}
+	
+	//alert("AjxUtil#parseSize: formattedSize="+formattedSize+", size="+size);
+	return size;
+};
+
+AjxUtil.isInstance = 
+function(aThing, aClass) { 
+	return !!(aThing && aThing.constructor && (aThing.constructor === aClass)); 
+};
+
+AjxUtil.assert = 
+function(aCondition, aMessage) {
+	if (!aCondition && AjxUtil.onassert) AjxUtil.onassert(aMessage);
+};
+
+AjxUtil.onassert = 
+function(aMessage) {
+	// Create an exception object and set the message
+	var myException = new Object();
+	myException.message = aMessage;
+	
+	// Compile a stack trace
+	var myStack = new Array();
+	if (AjxEnv.isIE5_5up) {
+		// On IE, the caller chain is on the arguments stack
+		var myTrace = arguments.caller;
+		while (myTrace) {
+		    myStack[myStack.length] = myTrace.callee;
+	    	myTrace = myTrace.caller;
+		}
+	} else {
+		try {
+			var myTrace = arguments.callee.caller;
+			while (myTrace) {
+				myStack[myStack.length] = myTrace;
+				if (myStack.length > 2) break;
+				myTrace = myTrace.caller;
+		    }
+		} catch (e) {
+		}
+	}
+	myException.stack = myStack;
+	
+	// Alert with the message and a description of the stack
+	var stackString = '';
+	var MAX_LEN = 170;
+	for (var i = 1; i < myStack.length; i++) {
+		if (i > 1) stackString += '\n';
+		if (i < 11) {
+			var fs = myStack[i].toString();
+			if (fs.length > MAX_LEN) {
+				fs = fs.substr(0,MAX_LEN) + '...';
+				fs = fs.replace(/\n/g, '');
+			}
+			stackString += i + ': ' + fs;
+		} else {
+			stackString += '(' + (myStack.length - 11) + ' frames follow)';
+			break;
+		}
+	}
+	alert('assertion:\n\n' + aMessage + '\n\n---- Call Stack ---\n' + stackString);
+	
+	// Now throw the exception
+	throw myException;
+};
+
+AjxUtil.NODE_REPEATS = new Object();
+AjxUtil.NODE_REPEATS["folder"]		= true;
+AjxUtil.NODE_REPEATS["search"]		= true;
+AjxUtil.NODE_REPEATS["tag"]			= true;
+AjxUtil.NODE_REPEATS["pref"]		= true;
+AjxUtil.NODE_REPEATS["attr"]		= true;
+AjxUtil.NODE_REPEATS["c"]			= true;
+AjxUtil.NODE_REPEATS["m"]			= true;
+AjxUtil.NODE_REPEATS["cn"]			= true;
+AjxUtil.NODE_REPEATS["e"]			= true;
+AjxUtil.NODE_REPEATS["a"]			= true;
+AjxUtil.NODE_REPEATS["mbx"]			= true;
+//AjxUtil.NODE_REPEATS["mp"]		= true; // only when parent is "mp"
+// these really shouldn't repeat
+AjxUtil.NODE_REPEATS["prefs"]		= true;
+AjxUtil.NODE_REPEATS["attrs"]		= true;
+AjxUtil.NODE_REPEATS["tags"]		= true;
+
+AjxUtil.NODE_IS_ATTR = new Object();
+AjxUtil.NODE_IS_ATTR["authToken"]	= true;
+AjxUtil.NODE_IS_ATTR["lifetime"]	= true;
+AjxUtil.NODE_IS_ATTR["sessionId"]	= true;
+AjxUtil.NODE_IS_ATTR["name"]		= true;
+AjxUtil.NODE_IS_ATTR["quotaUsed"]	= true;
+AjxUtil.NODE_IS_ATTR["su"]			= true;
+AjxUtil.NODE_IS_ATTR["fr"]			= true;
+AjxUtil.NODE_IS_ATTR["mid"]			= true;
+//AjxUtil.NODE_IS_ATTR["content"]	= true; // only when parent is "note"
+
+AjxUtil.NODE_CONTENT = new Object();
+AjxUtil.NODE_CONTENT["pref"]		= true;
+AjxUtil.NODE_CONTENT["attr"]		= true;
+AjxUtil.NODE_CONTENT["a"]			= true;
+
+// IE doesn't define Node type constants
+AjxUtil.ELEMENT_NODE	= 1;
+AjxUtil.TEXT_NODE		= 3;
+
+/**
+* Convert an XML node to the equivalent JS. Traverses the node's
+* children recursively.
+* <p>
+* NOTE: This method has not been extensively tested and likely needs
+* work.
+*
+* @param node		[Element]	XML node
+* @param omitName	[boolean]	if true, don't include node name in output
+*/
+AjxUtil.xmlToJs =
+function(node, omitName) {
+
+	if (node.nodeType == AjxUtil.TEXT_NODE)
+		return ['"', node.data, '"'].join("");
+
+	var name = node.name ? node.name : node.localName;
+	if (node.nodeType == AjxUtil.ELEMENT_NODE) {
+		// if only child is text, no need for enclosing {}
+		var hasTextNode = (node.childNodes && node.childNodes.length == 1 && 
+				   (node.childNodes[0].nodeType == AjxUtil.TEXT_NODE));
+		var text;
+		if (omitName) {
+			text = "{";
+		} else if (hasTextNode) {
+			text = [name, ":"].join("");
+		} else {
+			text = [name, ":{"].join("");
+		}
+		var needComma = false;	
+		if (node.attributes) {
+			for (var i = 0; i < node.attributes.length; i++) {
+				var attr = node.attributes[i];
+				if (attr.name == "xmlns") continue;
+				if (needComma) text += ",";
+				var value = AjxUtil.isNumeric(attr.value) ? attr.value : AjxUtil.jsEncode(attr.value);
+				text = [text, attr.name, ':', value].join("");
+				needComma = true;
+			}
+		}
+		if (node.hasChildNodes()) {
+			var cnodes = new Object();
+			var hasChild = false;
+			for (var i = 0; i < node.childNodes.length; i++) {
+				var child = node.childNodes[i];
+				var cname = child.name ? child.name : child.localName;
+				var isAttr = AjxUtil.NODE_IS_ATTR[cname] || 
+							 (name == "content" && parent.name == "note");
+				if (isAttr) {
+					if (needComma) text += ",";
+					text = [text, cname, ':', AjxUtil.jsEncode(child.textContent)].join("");
+					needComma = true;
+				} else {
+					if (!cnodes[cname])
+						cnodes[cname] = new Array();
+					cnodes[cname].push(child);
+					hasChild = true;
+				}
+			}
+			if (hasChild && needComma) {text += ","; needComma = false;}
+			for (var cname in cnodes) {
+				if (needComma) {
+					text += ",";
+					needComma = false;
+				}
+				var repeats = AjxUtil.NODE_REPEATS[cname] ||
+							  (cname == "mp" && name == "mp");
+				if (repeats) text += cname + ":[";
+				var clist = cnodes[cname];
+				for (var i = 0; i < clist.length; i++) {
+					if (needComma) text += ",";
+					text += AjxUtil.xmlToJs(clist[i], repeats);
+					needComma = true;
+				}
+				if (repeats) text += "]";
+			}
+		}
+		if (!hasTextNode) text += "}";
+	}
+
+	return text;
+}
+
+AjxUtil.JS_CHAR_ENCODINGS = [
+	"\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005", "\\u0006", "\\u0007",
+	"\\b",     "\\t",     "\\n",     "\\u000B", "\\f",     "\\r",     "\\u000E", "\\u000F",
+	"\\u0010", "\\u0011", "\\u0012", "\\u0013", "\\u0014", "\\u0015", "\\u0016", "\\u0017",
+	"\\u0018", "\\u0019", "\\u001A", "\\u001B", "\\u001C", "\\u001D", "\\u001E", "\\u001F"
+];
+
+AjxUtil.jsEncode =
+function(string) {
+
+	if (!string) return "\"\"";
+
+	var text = '"';
+	for (var i = 0; i < string.length; i++) {
+		var c = string.charAt(i);
+		switch (c) {
+			case '\\': case '"': case '/':
+				text += '\\' + c;
+				break;
+			default:
+				var code = string.charCodeAt(i);
+				text += (code < 32) ? AjxUtil.JS_CHAR_ENCODINGS[code] : c;
+		}
+	}
+	text += '"';
+	return text;
+};
+
+AjxUtil.getInnerText = 
+function(node) {
+ 	if (AjxEnv.isIE)
+ 		return node.innerText;
+
+	function f(n) {
+		if (n) {
+			if (n.nodeType == 3 /* TEXT_NODE */)
+				return n.data;
+			if (n.nodeType == 1 /* ELEMENT_NODE */) {
+				if (/^br$/i.test(n.tagName))
+					return "\r\n";
+				var str = "";
+				for (var i = n.firstChild; i; i = i.nextSibling)
+					str += f(i);
+				return str;
+			}
+		}
+		return "";
+	};
+	return f(node);
+};
+
+/**
+ * This method returns a proxy for the specified object. This is useful when
+ * you want to modify properties of an object and want to keep those values
+ * separate from the values in the original object. You can then iterate
+ * over the proxy's properties and use the <code>hasOwnProperty</code>
+ * method to determine if the property is a new value in the proxy.
+ * <p>
+ * <strong>Note:</strong>
+ * A reference to the original object is stored in the proxy as the "_object_" 
+ * property.
+ *
+ * @param object [object] The object to proxy.
+ * @param level  [number] The number of property levels deep to proxy.
+ *						  Defaults to zero.
+ */
+AjxUtil.createProxy = 
+function(object, level) {
+	var proxy;
+	var proxyCtor = function(){}; // bug #6517 (Safari doesnt like 'new Function')
+	proxyCtor.prototype = object;
+	if (object instanceof Array) {
+		proxy  = new Array();
+		var cnt  = object.length;
+		for(var ix = 0; ix < cnt; ix++) {
+			proxy[ix] = object[ix];
+		}
+	} else {
+		proxy = new proxyCtor;
+	}
+	
+	if (level) {
+		for (var prop in object) {
+			if (typeof object[prop] == "object")
+				proxy[prop] = AjxUtil.createProxy(object[prop], level - 1);
+		}
+	}	
+	
+	proxy._object_ = object;
+	return proxy;
+};
+
+/**
+* Returns a copy of a list with empty members removed.
+*
+* @param list	[array]		original list
+*/
+AjxUtil.collapseList =
+function(list) {
+	var newList = [];
+	for (var i = 0; i < list.length; i++)
+		if (list[i])
+			newList.push(list[i]);
+	return newList;
+};
+/*
+* ***** 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 AjxCore() {}
+
+AjxCore._objectIds = [null];
+
+
+AjxCore.assignId = 
+function(anObject) {
+	var myId = AjxCore._objectIds.length;
+	AjxCore._objectIds[myId]= anObject;
+	return myId;
+};
+
+AjxCore.unassignId = 
+function(anId) {
+	AjxCore._objectIds[anId]= null;
+};
+
+AjxCore.objectWithId = 
+function(anId) {
+	return AjxCore._objectIds[anId];
+};
+
+/**
+ * Adds a listener to an element, for the given event name.
+ */
+AjxCore.addListener = 
+function(eventSource, eventName, action) {
+	eventSource = AjxCore._getEventSource(eventSource);
+	var listenerStruct = AjxCore._getListenerStruct(eventSource, eventName, true);
+	listenerStruct.list[listenerStruct.list.length] = action;
+};
+
+/**
+ * sets a one time event handler for the given eventName.
+ */
+AjxCore.setEventHandler = 
+function(eventSource, eventName, action) {
+	eventSource = AjxCore._getEventSource(eventSource);
+	var listenerStruct = AjxCore._getListenerStruct(eventSource, eventName, true);
+	listenerStruct.single = action;
+};
+
+/**
+ * removes a listener for a given event
+ */
+AjxCore.removeListener = 
+function(eventSource, eventName, action) {
+	eventSource = AjxCore._getEventSource(eventSource);
+	var listenerStruct = AjxCore._getListenerStruct(eventSource, eventName);
+
+	if (listenerStruct) {
+		var listenerList = listenerStruct.list;
+		for (var i = 0; i < listenerList.length; i++) {
+			if (listenerList[i] == action)
+				listenerList[i] = null;
+		}
+	}
+};
+
+/**
+ * removes all listeners for a given eventName, and source
+ */
+AjxCore.removeAllListeners = 
+function(eventSource, eventName) {
+	eventSource = AjxCore._getEventSource(eventSource);
+	var listenerStruct = AjxCore._getListenerStruct(eventSource, eventName);
+
+	if (listenerStruct) {
+		var listenerList = listenerStruct.list;
+		for (var i = 0; i < listenerList.length; i++)
+			listenerList[i] = null;
+	}
+	AjxCore.unassignId(listenerStruct.id);
+};
+
+/**
+ * notifies listeners of the event. This only needs to be called if
+ * the event is not a standard DOM event. Those types of event callbacks
+ * will be triggered by their event handlers
+ */
+AjxCore.notifyListeners = 
+function(eventSource, eventName, arg1) {
+	eventSource = AjxCore._getEventSource(eventSource);
+	var listenerStruct = AjxCore._getListenerStruct(eventSource, eventName)
+	if (listenerStruct)
+		eventSource[eventName](arg1);
+};
+
+AjxCore._getEventSource = 
+function(eventSource) {
+	if (typeof(eventSource) == 'string')
+		eventSource = document.getElementById(eventSource);
+	return eventSource;
+};
+
+AjxCore.getListenerStruct = 
+function (eventSource, eventName) {
+	return AjxCore._getListenerStruct(eventSource, eventName);
+};
+
+/**
+ * gets the existing struct for the eventSource, or creates a new one.
+ */
+AjxCore._getListenerStruct = 
+function(eventSource, eventName, create) {
+	var listenerStruct = null;
+	if (eventSource[eventName]) {
+		var id = eventSource[eventName]._lsListenerStructId;
+		listenerStruct = AjxCore.objectWithId(id);
+	} else if (create) {
+		listenerStruct = AjxCore._setupListener(eventSource, eventName);
+	}
+
+	return listenerStruct;
+};
+    
+/**
+ * Creates a listener struct
+ */
+AjxCore._setupListener = 
+function(eventSource, eventName, id) {
+	var listenerStruct = new Object();
+	listenerStruct.list = new Array();
+	listenerStruct.single = null;
+	var id = listenerStruct.id = AjxCore.assignId(listenerStruct);
+	var handler = AjxCore._createListenerClosure(id);
+	eventSource[eventName] = handler;
+	eventSource[eventName]._lsListenerStructId = id;
+
+	return listenerStruct;
+};
+
+AjxCore._createListenerClosure = 
+function(id) {
+	var closure = function(arg1) {
+		var listenerStruct = AjxCore.objectWithId(id);
+		var listenerList = listenerStruct.list;
+		for (var i = 0; i < listenerList.length; i++) {
+			var callback = listenerList[i];
+			if (callback) {
+				if (typeof(callback) == 'string') {
+					eval(callback);
+				} else {
+					// handle AjxListener callbacks as well as simple functions
+					if (callback.handleEvent) {
+						callback.handleEvent(arg1, this);
+					} else {
+						callback(arg1, this);
+					}
+				}
+			}
+		}
+        if (listenerStruct.single) {
+			var callback = listenerStruct.single;
+			if (typeof(callback) == 'string') {
+				eval(callback);
+			} else {
+				return callback.handleEvent
+					? callback.handleEvent(arg1, this)
+					: callback(arg1, this);
+			}
+		}
+	}
+	return closure;
+};
+
+/**
+ * Convenience method for adding onload listeners
+ */
+AjxCore.addOnloadListener = 
+function(action) {
+	if (window.onload && (!window.onload._lsListenerStructId)) {
+		var priorListener = window.onload;
+		window.onload = null;
+		AjxCore.addListener(window, "onload", priorListener);
+	}
+
+	AjxCore.addListener(window, "onload", action);
+};
+
+/**
+ * Convenience method for adding onunload listeners
+ */    
+AjxCore.addOnunloadListener = 
+function(action) {
+	if (window.onunload && (!window.onunload._lsListenerStructId)) {
+		var priorListener = window.onunload;
+		window.onunload = null;
+		AjxCore.addListener(window, "onunload", priorListener);
+	}
+
+	AjxCore.addListener(window, "onunload", action);
+};
+/*
+* ***** 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 *****
+*/
+
+
+/* Represents a SOAP Fault
+*
+* Public attributes:
+*
+* - faultCode: The SOAP fault code
+* - reason: Reason string
+* - errorCode: server error code
+*/
+function AjxSoapFault(faultEl) {
+	if (arguments.length == 0) return;
+	var prefix = faultEl.prefix;
+	var codeStr = prefix + ":Code";
+	var reasonStr = prefix + ":Reason";
+	var detailStr = prefix + ":Detail"
+	// We will assume a correctly formatted Fault element
+	for (var i = 0; i < faultEl.childNodes.length; i++) {
+		var childNode = faultEl.childNodes[i];
+		if (childNode.nodeName == codeStr) {
+			var faultCode = childNode.firstChild.firstChild.nodeValue;
+			if (faultCode == (prefix + ":VersionMismatch"))
+				this.faultCode = AjxSoapFault.VERSION_MISMATCH;
+			else if (faultCode == (prefix + ":MustUnderstand"))
+				this.faultCode = AjxSoapFault.MUST_UNDERSTAND;
+			else if (faultCode == (prefix + ":DataEncodingUnknown"))
+				this.faultCode = AjxSoapFault.DATA_ENCODING_UNKNOWN;
+			else if (faultCode == (prefix + ":Sender"))
+				this.faultCode = AjxSoapFault.SENDER;
+			else if (faultCode == (prefix + ":Receiver"))
+				this.faultCode = AjxSoapFault.RECEIVER;
+			else
+				this.faultCode = AjxSoapFault.UNKNOWN;		
+		} else if (childNode.nodeName == reasonStr) {
+			this.reason = childNode.firstChild.firstChild.nodeValue;
+		} else if (childNode.nodeName == detailStr) {
+			this.errorCode = childNode.firstChild.firstChild.firstChild.nodeValue;
+		}
+	}
+}
+
+AjxSoapFault.prototype.toString = 
+function() {
+	return "AjxSoapFault";
+}
+
+AjxSoapFault.SENDER = -1;
+AjxSoapFault.RECEIVER = -2;
+AjxSoapFault.VERSION_MISMATCH = -3;
+AjxSoapFault.MUST_UNDERSTAND = -4;
+AjxSoapFault.DATA_ENCODING_UNKNOWN = -5;
+AjxSoapFault.UNKNOWN = -6;
+/*
+* ***** 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 AjxCookie() {
+}
+
+AjxCookie.prototype.toString = 
+function() {
+	return "AjxCookie";
+}
+
+AjxCookie.getCookie = 
+function(doc, name) {
+	var arg = name + "=";
+	var alen = arg.length;
+	var clen = doc.cookie.length;
+	var cookie = doc.cookie;
+	var i = 0;
+	while (i < clen) {
+		var j = i + alen;
+		if (cookie.substring(i, j) == arg) {
+			var endstr = cookie.indexOf (";", j);
+			if (endstr == -1)
+				endstr = cookie.length;
+			return unescape(cookie.substring(j, endstr));
+		}
+		i = cookie.indexOf(" ", i) + 1;
+		if (i == 0) 
+			break; 
+	}
+  return null;
+}
+
+AjxCookie.setCookie = 
+function(doc, name, value, expires, path, domain, secure) {
+	doc.cookie = name + "=" + escape (value) +
+		((expires) ? "; expires=" + expires.toGMTString() : "") +
+		((path) ? "; path=" + path : "") +
+		((domain) ? "; domain=" + domain : "") +
+		((secure) ? "; secure" : "");
+}
+
+AjxCookie.deleteCookie = 
+function (doc, name, path, domain) {
+	doc.cookie = name + "=" +
+	((path) ? "; path=" + path : "") +
+	((domain) ? "; domain=" + domain : "") + "; expires=Fri, 31 Dec 1999 23:59:59 GMT";
+}
+/*
+* ***** 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";
+/*
+* ***** 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 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;
+}
+
+AjxCallback.prototype.toString =
+function() {
+	return "AjxCallback";
+}
+
+/**
+* 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);
+	}
+
+	for (var i = 0; i < arguments.length; ++i)
+		args.push(arguments[i]);
+
+	// invoke function
+	return this.func.apply(this.obj || window, args);
+};
+
+/**
+ * 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));
+	};
+};
+/*
+* ***** 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 *****
+*/
+
+
+/**
+ * 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;
+};
+
+// -----------------------------------------------------------
+// Constants
+// -----------------------------------------------------------
+
+// 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();
+	}
+	return this._selectedItems;
+};
+
+/**
+ * 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];
+		}
+	}
+	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();
+	}
+	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);
+};
+	
+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;
+		
+		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);
+		}
+
+		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);
+
+	if (needsSort) this._selectedItems.sort();
+	
+	if (selectionChanged && this._owner.selectionChanged != null) {
+		this._owner.selectionChanged(item);
+	}
+};
+
+/**
+ * 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
+// -----------------------------------------------------------
+	
+/**
+ * Creates an array suitable for use as the sorted list of selected
+ * items and returns it.
+ */
+AjxSelectionManager.prototype._createItemsCollection = function() {
+	return new AjxVector();
+};
+
+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;
+};
+
+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;
+	}
+};
+/*
+* ***** 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 *****
+*/
+
+
+// Don't directly instantiate SoapDoc, use one of the create factory methods instead
+function AjxSoapDoc() {
+}
+
+AjxSoapDoc.prototype.toString =
+function() {
+	return "AjxSoapDoc";
+};
+
+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);
+
+	d.appendChild(envEl);
+
+	var bodyEl = d.createElement("soap:Body");
+	envEl.appendChild(bodyEl);
+
+	sd._methodEl = d.createElement(method);
+	if (namespaceId == null)
+		sd._methodEl.setAttribute("xmlns", namespace);
+	else
+		sd._methodEl.setAttribute("xmlns:" + namespaceId, namespace);
+
+	bodyEl.appendChild(sd._methodEl);
+	return sd;
+};
+
+AjxSoapDoc.createFromDom =
+function(doc) {
+	var sd = new AjxSoapDoc();
+	sd._xmlDoc = AjxXmlDoc.createFromDom(doc);
+	sd._methodEl = sd._check(sd._xmlDoc);
+	return sd;
+};
+
+AjxSoapDoc.createFromXml =
+function(xml) {
+	var sd = new AjxSoapDoc();
+	sd._xmlDoc = AjxXmlDoc.createFromXml(xml);
+	sd._methodEl = sd._check(sd._xmlDoc);
+	return sd;
+};
+
+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;
+	}
+	return new AjxSoapFault(faultEl);
+};
+
+AjxSoapDoc.prototype.setMethodAttribute =
+function(name, value) {
+	this._methodEl.setAttribute(name, value);
+};
+
+/**
+ * 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));
+		}
+	}
+	if (!parent)
+		parent = this._methodEl;
+	return parent.appendChild(p);
+};
+
+AjxSoapDoc.prototype.getMethod =
+function() {
+	return this._methodEl;
+};
+
+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;
+};
+
+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"));
+
+	return nodeList ? nodeList[0] : null;
+};
+
+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"));
+
+	return nodeList ? nodeList[0] : null;
+};
+
+AjxSoapDoc.prototype.getByTagName =
+function(type) {
+	if (type.indexOf(":") == -1)
+		type = "soap:" + type;
+
+	var a = this.getDoc().getElementsByTagName(type);
+
+	if (a.length == 1)		return a[0];
+	else if (a.length > 0)	return a;
+	else					return null;
+};
+
+// gimme a header, no exceptions.
+AjxSoapDoc.prototype.ensureHeader =
+function() {
+	return (this.getByTagName("Header") || this.createHeaderElement());
+};
+
+AjxSoapDoc.prototype.getDoc =
+function() {
+	return this._xmlDoc.getDoc();
+};
+
+AjxSoapDoc.prototype.getXml =
+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");
+		}
+	} else {
+		if (el.nodeName != (el.prefix + ":Envelope"))
+			throw new AjxSoapException("Invalid SOAP PDU", AjxSoapException.INVALID_PDU, "AjxSoapDoc.createFromXml:2");
+	}
+};
+/*
+* ***** 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();
+	}
+};
+
+AjxRpcRequest._inited = false;
+AjxRpcRequest._msxmlVers = null;
+
+AjxRpcRequest.prototype.toString = 
+function() {
+	return "AjxRpcRequest";
+};
+
+/**
+* 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) {
+
+	var asyncMode = (callback != null);
+	
+	// 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]);
+		}
+	}
+	
+	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};
+		}
+	}
+};
+
+/*
+* 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;
+	}
+};
+
+AjxRpcRequest.prototype.cancel =
+function() {
+	DBG.println(AjxDebug.DBG1, "Aborting HTTP request");
+	this._httpReq.abort();
+};
+
+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
+			}
+		}
+		if (AjxRpcRequest._msxmlVers == null)
+			throw new AjxException("MSXML not installed", AjxException.INTERNAL_ERROR, "AjxRpc._init");
+	}
+	AjxRpcRequest._inited = true;
+};
+/*
+* ***** 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 DwtHtmlEditorStateEvent(init) {
+	if (arguments.length == 0) return;
+	DwtEvent.call(this, true);
+	this.reset();
+}
+
+DwtHtmlEditorStateEvent.prototype = new DwtEvent;
+DwtHtmlEditorStateEvent.prototype.constructor = DwtHtmlEditorStateEvent;
+
+DwtHtmlEditorStateEvent.prototype.toString = 
+function() {
+	return "DwtHtmlEditorStateEvent";
+}
+
+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;
+}
+/*
+* ***** 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 DwtKeyEvent() {
+	DwtUiEvent.call(this, true);
+	this.reset(true);
+}
+
+
+DwtKeyEvent.KEY_END_OF_TEXT =  0x03;
+DwtKeyEvent.KEY_TAB = 0x09;
+DwtKeyEvent.KEY_RETURN = 0x0D;
+DwtKeyEvent.KEY_ENTER = 0x0D;
+DwtKeyEvent.KEY_ESCAPE = 0x1B;
+
+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;
+}
+
+
+DwtKeyEvent.prototype.setFromDhtmlEvent =
+function(ev) {
+	ev = DwtUiEvent.prototype.setFromDhtmlEvent.call(this, ev);
+	this.charCode = (ev.charCode) ? ev.charCode : ev.keyCode;
+	this.keyCode = ev.keyCode;
+}
+
+DwtKeyEvent.getCharCode =
+function(ev) {
+	ev = DwtUiEvent.getEvent(ev);
+	return AjxEnv.isSafari ? ev.keyCode : (ev.charCode || ev.keyCode);
+}
+
+DwtKeyEvent.copy = 
+function(dest, src) {
+	DwtUiEvent.copy(dest, src);
+	dest.charCode = src.charCode;
+	dest.keyCode = src.keyCode;
+}
+/*
+* ***** 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 DwtListView(parent, className, posStyle, headerList, noMaximize) {
+
+	if (arguments.length == 0) return;
+	className = className || "DwtListView";
+	DwtComposite.call(this, parent, className, posStyle);
+
+	if (headerList) {
+		var htmlElement = this.getHtmlElement();
+
+		this._listColDiv = document.createElement("div");
+		this._listColDiv.id = Dwt.getNextId();
+		this._listColDiv.className = "DwtListView-ColHeader";
+		htmlElement.appendChild(this._listColDiv);
+
+		this._listDiv = document.createElement("div");
+		this._listDiv.id = Dwt.getNextId();
+		this._listDiv.className = "DwtListView-Rows";
+		htmlElement.appendChild(this._listDiv);
+
+		// setup vars needed for sorting
+		this._bSortAsc = false;
+		this._currentColId = null;
+		this._sortingEnabled = true;
+	} else {
+		this.setScrollStyle(DwtControl.SCROLL); // auto scroll
+	}
+		
+	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);
+
+	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();
+	
+	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);
+	}
+	// 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");
+		}
+	}
+}
+
+DwtListView.prototype.createHeaderHtml = 
+function(defaultColumnSort) {
+
+	// does this list view have headers or have they already been created?
+	if (!this._headerList || this._headerColCreated)
+		return;
+	
+	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>";
+		
+		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>";
+			}
+		}
+		
+		// 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("");
+
+	// 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";
+
+		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;

[... 29237 lines stripped ...]