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/23 18:00:43 UTC
svn commit: r434107 [2/2] - /incubator/xap/trunk/dist/zimbra_uncompressed.js
Added: incubator/xap/trunk/dist/zimbra_uncompressed.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/dist/zimbra_uncompressed.js?rev=434107&view=auto
==============================================================================
--- incubator/xap/trunk/dist/zimbra_uncompressed.js (added)
+++ incubator/xap/trunk/dist/zimbra_uncompressed.js Wed Aug 23 11:00:42 2006
@@ -0,0 +1,36159 @@
+/** auto include file:./xap/peter/src/zimbra/js/msgs/AjxMsg.js **/
+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() {}
+/** auto include file:./xap/peter/src/zimbra/js/core/AjxCore.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 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);
+};
+/** auto include file:./xap/peter/src/zimbra/js/core/AjxEnv.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 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;
+ }
+ };
+ }
+}
+/** auto include file:./xap/peter/src/zimbra/js/util/AjxUtil.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 *****
+*/
+
+
+/**
+ * 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;
+};
+/** auto include file:./xap/peter/src/zimbra/js/util/AjxText.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 *****
+*/
+
+
+// NOTE: The API for the classes in this file are inspired by the Java text
+// formatting classes but the implementation was NOT copied or ported
+// from the Java sources.
+
+//
+// Format class
+//
+
+/**
+ * Base class for all formats. To format an object, instantiate the
+ * format of your choice and call the <code>format</code> method which
+ * returns the formatted string.
+ */
+function AjxFormat(pattern) {
+ this._pattern = pattern;
+ this._segments = [];
+}
+
+/** Returns string representation of this object. */
+AjxFormat.prototype.toString = function() {
+ var s = [];
+ s.push("pattern=\"",this._pattern,'"');
+ if (this._segments.length > 0) {
+ s.push(", segments={ ");
+ for (var i = 0; i < this._segments.length; i++) {
+ if (i > 0) { s.push(", "); }
+ s.push(String(this._segments[i]));
+ }
+ s.push(" }");
+ }
+ return s.join("");
+};
+
+// Data
+
+AjxFormat.prototype._pattern;
+AjxFormat.prototype._segments;
+
+// Public methods
+
+/**
+ * This method does <em>not</em> need to be overridden unless
+ * the subclass doesn't use format segments and takes complete
+ * responsibility for formatting.
+ */
+AjxFormat.prototype.format = function(object) {
+ var s = [];
+ for (var i = 0; i < this._segments.length; i++) {
+ s.push(this._segments[i].format(object));
+ }
+ return s.join("");
+};
+
+/**
+ * Parses the given string according to this format's pattern and returns
+ * an object.
+ * <p>
+
+ * <strong>Note:</strong>
+ * The default implementation of this method assumes that the sub-class
+ * has implemented the <code>_createParseObject</code> method.
+ */
+AjxFormat.prototype.parse = function(s) {
+ var object = this._createParseObject();
+ var index = 0;
+ for (var i = 0; i < this._segments.length; i++) {
+ var segment = this._segments[i];
+ index = segment.parse(object, s, index);
+ }
+ // REVISIT: Should this return null instead?
+ if (index < s.length) {
+ throw new AjxFormat.ParsingException(this, null, "input too long"); // I18n
+ }
+ return object;
+};
+
+/**
+ * Returns an array of segments that comprise this format.
+ * <p>
+ * <strong>Note:</strong>
+ * This method is specific to this implementation and does not follow
+ * the format classes found in the <code>java.text</code> package.
+ */
+AjxFormat.prototype.getSegments = function() {
+ return this._segments;
+};
+
+/** Returns a string pattern for this format. */
+AjxFormat.prototype.toPattern = function() {
+ return this._pattern;
+};
+
+/** Returns a copy of this format. */
+AjxFormat.prototype.clone = function() {
+ return new this.constructor(this._pattern);
+};
+
+// Protected methods
+
+/**
+ * Creates the object that is initialized by parsing
+ * <p>
+
+ * <strong>Note:</strong>
+ * This must be implemented by sub-classes.
+ */
+AjxFormat.prototype._createParseObject = function(s) {
+ throw new AjxFormat.ParsingException(this, null, "not implemented"); // I18n
+};
+
+// Protected static methods
+
+AjxFormat._zeroPad = function(s, length, zeroChar, rightSide) {
+ s = typeof s == "string" ? s : String(s);
+
+ if (s.length >= length) return s;
+
+ zeroChar = zeroChar || '0';
+
+ var a = [];
+ for (var i = s.length; i < length; i++) {
+ a.push(zeroChar);
+ }
+ a[rightSide ? "unshift" : "push"](s);
+
+ return a.join("");
+};
+
+//
+// Format exception base class
+//
+
+AjxFormat.FormatException = function(format, message) {
+ this._format = format;
+ this._message = message;
+};
+AjxFormat.FormatException.prototype.toString = function() {
+ return this._message;
+};
+
+// Data
+
+AjxFormat.FormatException.prototype._format;
+AjxFormat.FormatException.prototype._message;
+
+//
+// Formatting exception class
+//
+
+AjxFormat.FormattingException = function(format, segment, message) {
+ AjxFormat.FormatException.call(this, format, message);
+ this._segment = segment;
+};
+AjxFormat.FormattingException.prototype = new AjxFormat.FormatException;
+AjxFormat.FormattingException.prototype.constructor = AjxFormat.FormattingException;
+
+// Data
+
+AjxFormat.FormattingException.prototype._segment;
+
+//
+// Parsing exception class
+//
+
+AjxFormat.ParsingException = function(format, segment, message) {
+ AjxFormat.FormatException.call(this, format, message);
+ this._segment = segment;
+};
+AjxFormat.ParsingException.prototype = new AjxFormat.FormatException;
+AjxFormat.ParsingException.prototype.constructor = AjxFormat.ParsingException;
+
+// Data
+
+AjxFormat.ParsingException.prototype._segment;
+
+//
+// Segment class
+//
+
+AjxFormat.Segment = function(format, s) {
+ this._parent = format;
+ this._s = s;
+};
+
+AjxFormat.Segment.prototype.toString = function() {
+ return "segment: \""+this._s+'"';
+};
+
+// Data
+
+AjxFormat.Segment.prototype._parent;
+AjxFormat.Segment.prototype._s;
+
+// Public methods
+
+AjxFormat.Segment.prototype.format = function(o) {
+ return this._s;
+};
+
+/**
+ * Parses the string at the given index, initializes the parse object
+ * (as appropriate), and returns the new index within the string for
+ * the next parsing step.
+ * <p>
+ * <strong>Note:</strong>
+ * This method must be implemented by sub-classes.
+ *
+ * @param o [object] The parse object to be initialized.
+ * @param s [string] The input string to be parsed.
+ * @param index [number] The index within the string to start parsing.
+ */
+AjxFormat.Segment.prototype.parse = function(o, s, i) {
+ throw new AjxFormat.ParsingException(this._parent, this, "not implemented"); // I18n
+};
+
+// Protected static methods
+
+AjxFormat.Segment._parseLiteral = function(literal, s, index) {
+ if (s.length - index < literal.length) {
+ throw new AjxFormat.ParsingException(this._parent, this, "input too short"); // I18n
+ }
+ for (var i = 0; i < literal.length; i++) {
+ if (literal.charAt(i) != s.charAt(index + i)) {
+ throw new AjxFormat.ParsingException(this._parent, this, "input doesn't match"); // I18n
+ }
+ }
+ return index + literal.length;
+};
+AjxFormat.Segment._parseLiterals = function(literals, s, index) {
+ for (var i = 0; i < literals.length; i++) {
+ try {
+ var literal = literals[i];
+ return AjxFormat.Segment._parseLiteral(literal, s, index);
+ }
+ catch (e) {
+ // ignore. keep trying to find a match
+ }
+ }
+ return -1;
+};
+
+/**
+ * Parses an integer at the offset of the given string and calls a
+ * method on the specified object.
+ *
+ * @param o [object] The target object.
+ * @param f [function] The method to call on the target object.
+ * @param adjust [number] The numeric adjustment to make on the
+ * value before calling the object method.
+ * @param s [string] The string to parse.
+ * @param index [number] The index within the string to start parsing.
+ * @param fixedlen [number] If specified, specifies the required number
+ * of digits to be parsed.
+ */
+AjxFormat.Segment._parseInt = function(o, f, adjust, s, index, fixedlen) {
+ var len = fixedlen || s.length - index;
+ var head = index;
+ for (var i = 0; i < len; i++) {
+ if (!s.charAt(index++).match(/\d/)) {
+ index--;
+ break;
+ }
+ }
+ var tail = index;
+ if (head == tail) {
+ throw new AjxFormat.ParsingException(this._parent, this, "number not present"); // I18n
+ }
+ if (fixedlen && tail - head != fixedlen) {
+ throw new AjxFormat.ParsingException(this._parent, this, "number too short"); // I18n
+ }
+ var value = parseInt(s.substring(head, tail), 10);
+ if (f) {
+ var target = o || window;
+ f.call(target, value + adjust);
+ }
+ return tail;
+};
+
+//
+// Date format class
+//
+
+/**
+ * The AjxDateFormat class formats Date objects according to a specified
+ * pattern. The patterns are defined the same as the SimpleDateFormat
+ * class in the Java libraries. <strong>Note:</strong> <em>Only the
+ * Gregorian Calendar is supported at this time.</em> Supporting other
+ * calendars would require a lot more information downloaded to the
+ * client. Limiting dates to the Gregorian calendar is a trade-off.
+ * <p>
+
+ * <strong>Note:</strong>
+ * The date format differs from the Java patterns a few ways: the pattern
+ * "EEEEE" (5 'E's) denotes a <em>short</em> weekday and the pattern "MMMMM"
+ * (5 'M's) denotes a <em>short</em> month name. This matches the extended
+ * pattern found in the Common Locale Data Repository (CLDR) found at:
+ * http://www.unicode.org/cldr/.
+ */
+function AjxDateFormat(pattern) {
+ AjxFormat.call(this, pattern);
+ if (typeof pattern == "number") {
+ switch (pattern) {
+ case AjxDateFormat.SHORT: pattern = I18nMsg.formatDateShort; break;
+ case AjxDateFormat.MEDIUM: pattern = I18nMsg.formatDateMedium; break;
+ case AjxDateFormat.LONG: pattern = I18nMsg.formatDateLong; break;
+ case AjxDateFormat.FULL: pattern = I18nMsg.formatDateFull; break;
+ }
+ }
+ for (var i = 0; i < pattern.length; i++) {
+ // literal
+ var c = pattern.charAt(i);
+ if (c == "'") {
+ var head = i + 1;
+ for (i++ ; i < pattern.length; i++) {
+ var c = pattern.charAt(i);
+ if (c == "'") {
+ if (i + 1 < pattern.length && pattern.charAt(i + 1) == "'") {
+ pattern = pattern.substr(0, i) + pattern.substr(i + 1);
+ }
+ else {
+ break;
+ }
+ }
+ }
+ if (i == pattern.length) {
+ // TODO: i18n
+ throw new FormatException(this, "unterminated string literal");
+ }
+ var tail = i;
+ var segment = new AjxFormat.TextSegment(this, pattern.substring(head, tail));
+ this._segments.push(segment);
+ continue;
+ }
+
+ // non-meta chars
+ var head = i;
+ while(i < pattern.length) {
+ c = pattern.charAt(i);
+ if (AjxDateFormat._META_CHARS.indexOf(c) != -1 || c == "'") {
+ break;
+ }
+ i++;
+ }
+ var tail = i;
+ if (head != tail) {
+ var segment = new AjxFormat.TextSegment(this, pattern.substring(head, tail));
+ this._segments.push(segment);
+ i--;
+ continue;
+ }
+
+ // meta char
+ var head = i;
+ while(++i < pattern.length) {
+ if (pattern.charAt(i) != c) {
+ break;
+ }
+ }
+ var tail = i--;
+ var count = tail - head;
+ var field = pattern.substr(head, count);
+ var segment = null;
+ switch (c) {
+ case 'G': segment = new AjxDateFormat.EraSegment(this, field); break;
+ case 'y': segment = new AjxDateFormat.YearSegment(this, field); break;
+ case 'M': segment = new AjxDateFormat.MonthSegment(this, field); break;
+ case 'w': segment = new AjxDateFormat.WeekSegment(this, field); break;
+ case 'W': segment = new AjxDateFormat.WeekSegment(this, field); break;
+ case 'D': segment = new AjxDateFormat.DaySegment(this, field); break;
+ case 'd': segment = new AjxDateFormat.DaySegment(this, field); break;
+ case 'F': segment = new AjxDateFormat.WeekdaySegment(this, field); break;
+ case 'E': segment = new AjxDateFormat.WeekdaySegment(this, field); break;
+ case 'a': segment = new AjxDateFormat.AmPmSegment(this, field); break;
+ case 'H': segment = new AjxDateFormat.HourSegment(this, field); break;
+ case 'k': segment = new AjxDateFormat.HourSegment(this, field); break;
+ case 'K': segment = new AjxDateFormat.HourSegment(this, field); break;
+ case 'h': segment = new AjxDateFormat.HourSegment(this, field); break;
+ case 'm': segment = new AjxDateFormat.MinuteSegment(this, field); break;
+ case 's': segment = new AjxDateFormat.SecondSegment(this, field); break;
+ case 'S': segment = new AjxDateFormat.SecondSegment(this, field); break;
+ case 'z': segment = new AjxDateFormat.TimezoneSegment(this, field); break;
+ case 'Z': segment = new AjxDateFormat.TimezoneSegment(this, field); break;
+ }
+ if (segment != null) {
+ segment._index = this._segments.length;
+ this._segments.push(segment);
+ }
+ }
+}
+AjxDateFormat.prototype = new AjxFormat;
+AjxDateFormat.prototype.constructor = AjxDateFormat;
+
+AjxDateFormat.prototype.toString = function() {
+ return "[AjxDateFormat: "+AjxFormat.prototype.toString.call(this)+"]";
+};
+
+// Constants
+
+AjxDateFormat.SHORT = 0;
+AjxDateFormat.MEDIUM = 1;
+AjxDateFormat.LONG = 2;
+AjxDateFormat.FULL = 3;
+AjxDateFormat.DEFAULT = AjxDateFormat.MEDIUM;
+
+AjxDateFormat._META_CHARS = "GyMwWDdFEaHkKhmsSzZ";
+
+AjxDateFormat._dateFormats = [
+ I18nMsg.formatDateShort, I18nMsg.formatDateMedium,
+ I18nMsg.formatDateLong, I18nMsg.formatDateFull
+];
+AjxDateFormat._timeFormats = [
+ I18nMsg.formatTimeShort, I18nMsg.formatTimeMedium,
+ I18nMsg.formatTimeLong, I18nMsg.formatTimeFull
+];
+
+AjxDateFormat._DATE_FORMATTERS = {};
+AjxDateFormat._TIME_FORMATTERS = {};
+AjxDateFormat._DATETIME_FORMATTERS = {};
+
+// Static methods
+
+AjxDateFormat.getDateInstance = function(style) {
+ // lazily create formatters
+ style = style != null ? style : AjxDateFormat.DEFAULT;
+ if (!AjxDateFormat._DATE_FORMATTERS[style]) {
+ AjxDateFormat._DATE_FORMATTERS[style] = new AjxDateFormat(AjxDateFormat._dateFormats[style]);
+ }
+ return AjxDateFormat._DATE_FORMATTERS[style];
+};
+
+AjxDateFormat.getTimeInstance = function(style) {
+ // lazily create formatters
+ style = style != null ? style : AjxDateFormat.DEFAULT;
+ if (!AjxDateFormat._TIME_FORMATTERS[style]) {
+ AjxDateFormat._TIME_FORMATTERS[style] = new AjxDateFormat(AjxDateFormat._timeFormats[style]);
+ }
+ return AjxDateFormat._TIME_FORMATTERS[style];
+};
+
+AjxDateFormat.getDateTimeInstance = function(dateStyle, timeStyle) {
+ // lazily create formatters
+ dateStyle = dateStyle != null ? dateStyle : AjxDateFormat.DEFAULT;
+ timeStyle = timeStyle != null ? timeStyle : AjxDateFormat.DEFAULT;
+ var style = dateStyle * 10 + timeStyle;
+ if (!AjxDateFormat._DATETIME_FORMATTERS[style]) {
+ var pattern = I18nMsg.formatDateTime;
+ var params = [ AjxDateFormat._dateFormats[dateStyle], AjxDateFormat._timeFormats[timeStyle] ];
+
+ var dateTimePattern = AjxMessageFormat.format(pattern, params);
+ AjxDateFormat._DATETIME_FORMATTERS[style] = new AjxDateFormat(dateTimePattern);
+ }
+ return AjxDateFormat._DATETIME_FORMATTERS[style];
+};
+
+AjxDateFormat.format = function(pattern, date) {
+ return new AjxDateFormat(pattern).format(date);
+};
+AjxDateFormat.parse = function(pattern, dateStr) {
+ return new AjxDateFormat(pattern).parse(dateStr);
+};
+
+// Public methods
+
+/**
+ * Parses the given string and returns a date. If the string cannot be
+ * parsed as a date, <code>null</code> is returned.
+ */
+AjxDateFormat.prototype.parse = function(s) {
+ var object = null;
+ try {
+ object = AjxFormat.prototype.parse.call(this, s);
+ }
+ catch (e) {
+ // do nothing
+ }
+ return object;
+};
+
+// Protected methods
+
+AjxDateFormat.prototype._createParseObject = function() {
+ return new Date(0, 0, 1, 0, 0, 0, 0);
+};
+
+//
+// Text segment class
+//
+
+AjxFormat.TextSegment = function(format, s) {
+ AjxFormat.Segment.call(this, format, s);
+};
+AjxFormat.TextSegment.prototype = new AjxFormat.Segment;
+AjxFormat.TextSegment.prototype.constructor = AjxFormat.TextSegment;
+
+AjxFormat.TextSegment.prototype.toString = function() {
+ return "text: \""+this._s+'"';
+};
+
+// Public methods
+
+AjxFormat.TextSegment.prototype.parse = function(o, s, index) {
+ return AjxFormat.Segment._parseLiteral(this._s, s, index);
+};
+
+//
+// Date segment class
+//
+
+AjxDateFormat.DateSegment = function(format, s) {
+ AjxFormat.Segment.call(this, format, s);
+}
+AjxDateFormat.DateSegment.prototype = new AjxFormat.Segment;
+AjxDateFormat.DateSegment.prototype.constructor = AjxDateFormat.DateSegment;
+
+// Protected methods
+
+AjxDateFormat.DateSegment.prototype._getFixedLength = function() {
+ var fixedlen;
+ if (this._index + 1 < this._parent._segments.length) {
+ var nextSegment = this._parent._segments[this._index + 1];
+ if (!(nextSegment instanceof AjxFormat.TextSegment)) {
+ fixedlen = this._s.length;
+ }
+ }
+ return fixedlen;
+};
+
+//
+// Date era segment class
+//
+
+AjxDateFormat.EraSegment = function(format, s) {
+ AjxDateFormat.DateSegment.call(this, format, s);
+};
+AjxDateFormat.EraSegment.prototype = new AjxDateFormat.DateSegment;
+AjxDateFormat.EraSegment.prototype.constructor = AjxDateFormat.EraSegment;
+
+AjxDateFormat.EraSegment.prototype.toString = function() {
+ return "dateEra: \""+this._s+'"';
+};
+
+// Public methods
+
+AjxDateFormat.EraSegment.prototype.format = function(date) {
+ // TODO: Only support current era at the moment...
+ return I18nMsg.eraAD;
+};
+
+//
+// Date year segment class
+//
+
+AjxDateFormat.YearSegment = function(format, s) {
+ AjxDateFormat.DateSegment.call(this, format, s);
+};
+AjxDateFormat.YearSegment.prototype = new AjxDateFormat.DateSegment;
+AjxDateFormat.YearSegment.prototype.constructor = AjxDateFormat.YearSegment;
+
+AjxDateFormat.YearSegment.prototype.toString = function() {
+ return "dateYear: \""+this._s+'"';
+};
+
+// Public methods
+
+AjxDateFormat.YearSegment.prototype.format = function(date) {
+ var year = String(date.getFullYear());
+ return this._s.length < 4 ? year.substr(year.length - 2) : AjxFormat._zeroPad(year, this._s.length);
+};
+
+AjxDateFormat.YearSegment.prototype.parse = function(date, s, index) {
+ var fixedlen = this._getFixedLength();
+ var nindex = AjxFormat.Segment._parseInt(date, date.setFullYear, 0, s, index, fixedlen);
+ // adjust 2-digit years
+ if (nindex - index == 2) {
+ if (!AjxDateFormat._2digitStartYear) {
+ AjxDateFormat._2digitStartYear = parseInt(AjxMsg.dateParsing2DigitStartYear);
+ }
+ var syear = AjxDateFormat._2digitStartYear;
+ var pyear = parseInt(s.substr(index,2));
+ var century = (Math.floor(syear / 100) + (pyear < (syear % 100) ? 1 : 0)) * 100;
+ var year = century + pyear;
+ date.setFullYear(year);
+ }
+ return nindex;
+};
+
+//
+// Date month segment class
+//
+
+AjxDateFormat.MonthSegment = function(format, s) {
+ AjxDateFormat.DateSegment.call(this, format, s);
+};
+AjxDateFormat.MonthSegment.prototype = new AjxDateFormat.DateSegment;
+AjxDateFormat.MonthSegment.prototype.constructor = AjxDateFormat.MonthSegment;
+
+AjxDateFormat.MonthSegment.prototype.toString = function() {
+ return "dateMonth: \""+this._s+'"';
+};
+
+// Constants
+
+AjxDateFormat.MonthSegment.MONTHS = {};
+AjxDateFormat.MonthSegment.MONTHS[AjxDateFormat.SHORT] = [
+ AjxMsg.monthJanShort, AjxMsg.monthFebShort, AjxMsg.monthMarShort,
+ AjxMsg.monthAprShort, AjxMsg.monthMayShort, AjxMsg.monthJunShort,
+ AjxMsg.monthJulShort, AjxMsg.monthAugShort, AjxMsg.monthSepShort,
+ AjxMsg.monthOctShort, AjxMsg.monthNovShort, AjxMsg.monthDecShort
+];
+AjxDateFormat.MonthSegment.MONTHS[AjxDateFormat.MEDIUM] = [
+ I18nMsg.monthJanMedium, I18nMsg.monthFebMedium, I18nMsg.monthMarMedium,
+ I18nMsg.monthAprMedium, I18nMsg.monthMayMedium, I18nMsg.monthJunMedium,
+ I18nMsg.monthJulMedium, I18nMsg.monthAugMedium, I18nMsg.monthSepMedium,
+ I18nMsg.monthOctMedium, I18nMsg.monthNovMedium, I18nMsg.monthDecMedium
+];
+AjxDateFormat.MonthSegment.MONTHS[AjxDateFormat.LONG] = [
+ I18nMsg.monthJanLong, I18nMsg.monthFebLong, I18nMsg.monthMarLong,
+ I18nMsg.monthAprLong, I18nMsg.monthMayLong, I18nMsg.monthJunLong,
+ I18nMsg.monthJulLong, I18nMsg.monthAugLong, I18nMsg.monthSepLong,
+ I18nMsg.monthOctLong, I18nMsg.monthNovLong, I18nMsg.monthDecLong
+];
+
+// Public methods
+
+AjxDateFormat.MonthSegment.prototype.format = function(date) {
+ var month = date.getMonth();
+ switch (this._s.length) {
+ case 1: return String(month + 1);
+ case 2: return AjxFormat._zeroPad(month + 1, 2);
+ case 3: return AjxDateFormat.MonthSegment.MONTHS[AjxDateFormat.MEDIUM][month];
+ case 5: return AjxDateFormat.MonthSegment.MONTHS[AjxDateFormat.SHORT][month];
+ }
+ return AjxDateFormat.MonthSegment.MONTHS[AjxDateFormat.LONG][month];
+};
+
+AjxDateFormat.MonthSegment.prototype.parse = function(date, s, index) {
+ var months;
+ switch (this._s.length) {
+ case 3:
+ months = AjxDateFormat.MonthSegment.MONTHS[AjxDateFormat.SHORT];
+ case 4:
+ months = months || AjxDateFormat.MonthSegment.MONTHS[AjxDateFormat.MEDIUM];
+ case 5: {
+ months = months || AjxDateFormat.MonthSegment.MONTHS[AjxDateFormat.LONG];
+ var nindex = AjxFormat.Segment._parseLiterals(months, s, index);
+ if (nindex != -1) {
+ return nindex;
+ }
+ throw new AjxFormat.ParsingException(this._parent, this, "no match"); // I18n
+ }
+ }
+ var fixedlen = this._getFixedLength();
+ return AjxFormat.Segment._parseInt(date, date.setMonth, -1, s, index, fixedlen);
+};
+
+//
+// Date week segment class
+//
+
+AjxDateFormat.WeekSegment = function(format, s) {
+ AjxDateFormat.DateSegment.call(this, format, s);
+};
+AjxDateFormat.WeekSegment.prototype = new AjxDateFormat.DateSegment;
+AjxDateFormat.WeekSegment.prototype.constructor = AjxDateFormat.WeekSegment;
+
+AjxDateFormat.WeekSegment.prototype.toString = function() {
+ return "weekMonth: \""+this._s+'"';
+};
+
+// Public methods
+
+AjxDateFormat.WeekSegment.prototype.format = function(date) {
+ var year = date.getYear();
+ var month = date.getMonth();
+ var day = date.getDate();
+
+ var ofYear = /w/.test(this._s);
+ var date2 = new Date(year, ofYear ? 0 : month, 1);
+
+ var week = 0;
+ while (true) {
+ week++;
+ if (date2.getMonth() > month || (date2.getMonth() == month && date2.getDate() >= day)) {
+ break;
+ }
+ date2.setDate(date2.getDate() + 7);
+ }
+
+ return AjxFormat._zeroPad(week, this._s.length);
+};
+
+//
+// Date day segment class
+//
+
+AjxDateFormat.DaySegment = function(format, s) {
+ AjxDateFormat.DateSegment.call(this, format, s);
+};
+AjxDateFormat.DaySegment.prototype = new AjxDateFormat.DateSegment;
+AjxDateFormat.DaySegment.prototype.constructor = AjxDateFormat.DaySegment;
+
+AjxDateFormat.DaySegment.prototype.toString = function() {
+ return "dateDay: \""+this._s+'"';
+};
+
+// Public methods
+
+AjxDateFormat.DaySegment.prototype.format = function(date) {
+ var month = date.getMonth();
+ var day = date.getDate();
+ if (/D/.test(this._s) && month > 0) {
+ var year = date.getYear();
+ do {
+ // set date to first day of month and then go back one day
+ var date2 = new Date(year, month, 1);
+ date2.setDate(0);
+
+ day += date2.getDate();
+ month--;
+ } while (month > 0);
+ }
+ return AjxFormat._zeroPad(day, this._s.length);
+};
+
+AjxDateFormat.DaySegment.prototype.parse = function(date, s, index) {
+ if (/D/.test(this._s)) {
+ date.setMonth(0);
+ }
+ var fixedlen = this._getFixedLength();
+ return AjxFormat.Segment._parseInt(date, date.setDate, 0, s, index, fixedlen);
+};
+
+//
+// Date weekday segment class
+//
+
+AjxDateFormat.WeekdaySegment = function(format, s) {
+ AjxDateFormat.DateSegment.call(this, format, s);
+};
+AjxDateFormat.WeekdaySegment.prototype = new AjxDateFormat.DateSegment;
+AjxDateFormat.WeekdaySegment.prototype.constructor = AjxDateFormat.WeekdaySegment;
+
+AjxDateFormat.DaySegment.prototype.toString = function() {
+ return "dateDay: \""+this._s+'"';
+};
+
+// Constants
+
+AjxDateFormat.WeekdaySegment.WEEKDAYS = {};
+// NOTE: The short names aren't available in Java so we have to define them.
+AjxDateFormat.WeekdaySegment.WEEKDAYS[AjxDateFormat.SHORT] = [
+ AjxMsg.weekdaySunShort, AjxMsg.weekdayMonShort, AjxMsg.weekdayTueShort,
+ AjxMsg.weekdayWedShort, AjxMsg.weekdayThuShort, AjxMsg.weekdayFriShort,
+ AjxMsg.weekdaySatShort
+];
+AjxDateFormat.WeekdaySegment.WEEKDAYS[AjxDateFormat.MEDIUM] = [
+ I18nMsg.weekdaySunMedium, I18nMsg.weekdayMonMedium, I18nMsg.weekdayTueMedium,
+ I18nMsg.weekdayWedMedium, I18nMsg.weekdayThuMedium, I18nMsg.weekdayFriMedium,
+ I18nMsg.weekdaySatMedium
+];
+AjxDateFormat.WeekdaySegment.WEEKDAYS[AjxDateFormat.LONG] = [
+ I18nMsg.weekdaySunLong, I18nMsg.weekdayMonLong, I18nMsg.weekdayTueLong,
+ I18nMsg.weekdayWedLong, I18nMsg.weekdayThuLong, I18nMsg.weekdayFriLong,
+ I18nMsg.weekdaySatLong
+];
+
+// Public methods
+
+AjxDateFormat.WeekdaySegment.prototype.format = function(date) {
+ var weekday = date.getDay();
+ if (/E/.test(this._s)) {
+ var style;
+ switch (this._s.length) {
+ case 4: style = AjxDateFormat.LONG; break;
+ case 5: style = AjxDateFormat.SHORT; break;
+ default: style = AjxDateFormat.MEDIUM;
+ }
+ return AjxDateFormat.WeekdaySegment.WEEKDAYS[style][weekday];
+ }
+ return AjxFormat._zeroPad(weekday, this._s.length);
+};
+
+//
+// Time segment class
+//
+
+AjxDateFormat.TimeSegment = function(format, s) {
+ AjxFormat.Segment.call(this, format, s);
+};
+AjxDateFormat.TimeSegment.prototype = new AjxFormat.Segment;
+AjxDateFormat.TimeSegment.prototype.constructor = AjxDateFormat.TimeSegment;
+
+//
+// Time hour segment class
+//
+
+AjxDateFormat.HourSegment = function(format, s) {
+ AjxFormat.Segment.call(this, format, s);
+};
+AjxDateFormat.HourSegment.prototype = new AjxDateFormat.TimeSegment;
+AjxDateFormat.HourSegment.prototype.constructor = AjxDateFormat.HourSegment;
+
+AjxDateFormat.HourSegment.prototype.toString = function() {
+ return "timeHour: \""+this._s+'"';
+};
+
+// Public methods
+
+AjxDateFormat.HourSegment.prototype.format = function(date) {
+ var hours = date.getHours();
+ if (hours > 12 && /[hK]/.test(this._s)) {
+ hours -= 12;
+ }
+ /***
+ // NOTE: This is commented out to match the Java formatter output
+ // but from the comments for these meta-chars, it doesn't
+ // seem right.
+ if (/[Hk]/.test(this._s)) {
+ hours--;
+ }
+ /***/
+ return AjxFormat._zeroPad(hours, this._s.length);
+};
+
+//
+// Time minute segment class
+//
+
+AjxDateFormat.MinuteSegment = function(format, s) {
+ AjxFormat.Segment.call(this, format, s);
+};
+AjxDateFormat.MinuteSegment.prototype = new AjxDateFormat.TimeSegment;
+AjxDateFormat.MinuteSegment.prototype.constructor = AjxDateFormat.MinuteSegment;
+
+AjxDateFormat.MinuteSegment.prototype.toString = function() {
+ return "timeMinute: \""+this._s+'"';
+};
+
+// Public methods
+
+AjxDateFormat.MinuteSegment.prototype.format = function(date) {
+ var minutes = date.getMinutes();
+ return AjxFormat._zeroPad(minutes, this._s.length);
+};
+
+//
+// Time second segment class
+//
+
+AjxDateFormat.SecondSegment = function(format, s) {
+ AjxFormat.Segment.call(this, format, s);
+};
+AjxDateFormat.SecondSegment.prototype = new AjxDateFormat.TimeSegment;
+AjxDateFormat.SecondSegment.prototype.constructor = AjxDateFormat.SecondSegment;
+
+AjxDateFormat.SecondSegment.prototype.toString = function() {
+ return "timeSecond: \""+this._s+'"';
+};
+
+// Public methods
+
+AjxDateFormat.SecondSegment.prototype.format = function(date) {
+ var minutes = /s/.test(this._s) ? date.getSeconds() : date.getMilliseconds();
+ return AjxFormat._zeroPad(minutes, this._s.length);
+};
+
+//
+// Time am/pm segment class
+//
+
+AjxDateFormat.AmPmSegment = function(format, s) {
+ AjxFormat.Segment.call(this, format, s);
+};
+AjxDateFormat.AmPmSegment.prototype = new AjxDateFormat.TimeSegment;
+AjxDateFormat.AmPmSegment.prototype.constructor = AjxDateFormat.AmPmSegment;
+
+AjxDateFormat.AmPmSegment.prototype.toString = function() {
+ return "timeAmPm: \""+this._s+'"';
+};
+
+// Public methods
+
+AjxDateFormat.AmPmSegment.prototype.format = function(date) {
+ var hours = date.getHours();
+ return hours < 12 ? I18nMsg.periodAm : I18nMsg.periodPm;
+};
+
+//
+// Time timezone segment class
+//
+
+AjxDateFormat.TimezoneSegment = function(format, s) {
+ AjxFormat.Segment.call(this, format, s);
+};
+AjxDateFormat.TimezoneSegment.prototype = new AjxDateFormat.TimeSegment;
+AjxDateFormat.TimezoneSegment.prototype.constructor = AjxDateFormat.TimezoneSegment;
+
+AjxDateFormat.TimezoneSegment.prototype.toString = function() {
+ return "timeTimezone: \""+this._s+'"';
+};
+
+// Public methods
+
+AjxDateFormat.TimezoneSegment.prototype.format = function(date) {
+ var clientId = date.timezone || AjxTimezone.DEFAULT;
+ if (/Z/.test(this._s)) {
+ return AjxTimezone.getShortName(clientId);
+ }
+ return this._s.length < 4 ? AjxTimezone.getMediumName(clientId) : AjxTimezone.getLongName(clientId);
+};
+
+//
+// Message format class
+//
+
+function AjxMessageFormat(pattern) {
+ AjxFormat.call(this, pattern);
+ for (var i = 0; i < pattern.length; i++) {
+ // literal
+ var c = pattern.charAt(i);
+ if (c == "'") {
+ if (i + 1 < pattern.length && pattern.charAt(i + 1) == "'") {
+ var segment = new AjxFormat.TextSegment(this, "'");
+ this._segments.push(segment);
+ i++;
+ continue;
+ }
+ var head = i + 1;
+ for (i++ ; i < pattern.length; i++) {
+ var c = pattern.charAt(i);
+ if (c == "'") {
+ if (i + 1 < pattern.length && pattern.charAt(i + 1) == "'") {
+ pattern = pattern.substr(0, i) + pattern.substr(i + 1);
+ }
+ else {
+ break;
+ }
+ }
+ }
+ if (i == pattern.length) {
+ // TODO: i18n
+ throw new AjxFormat.FormatException(this, "unterminated string literal");
+ }
+ var tail = i;
+ var segment = new AjxFormat.TextSegment(this, pattern.substring(head, tail));
+ this._segments.push(segment);
+ continue;
+ }
+
+ // non-meta chars
+ var head = i;
+ while(i < pattern.length) {
+ c = pattern.charAt(i);
+ if (c == '{' || c == "'") {
+ break;
+ }
+ i++;
+ }
+ var tail = i;
+ if (head != tail) {
+ var segment = new AjxFormat.TextSegment(this, pattern.substring(head, tail));
+ this._segments.push(segment);
+ i--;
+ continue;
+ }
+
+ // meta char
+ var head = i + 1;
+ while(++i < pattern.length) {
+ if (pattern.charAt(i) == '}') {
+ break;
+ }
+ }
+ var tail = i;
+ var count = tail - head;
+ var field = pattern.substr(head, count);
+ var segment = new AjxMessageFormat.MessageSegment(this, field);
+ if (segment != null) {
+ this._segments.push(segment);
+ }
+ }
+}
+AjxMessageFormat.prototype = new AjxFormat;
+AjxMessageFormat.prototype.constructor = AjxMessageFormat;
+
+AjxMessageFormat.prototype.toString = function() {
+ return "[AjxMessageFormat: "+AjxFormat.prototype.toString.call(this)+"]";
+};
+
+// Static methods
+
+AjxMessageFormat.format = function(pattern, params) {
+ return new AjxMessageFormat(pattern).format(params);
+};
+
+// Public methods
+
+AjxMessageFormat.prototype.format = function(params) {
+ if (!(params instanceof Array)) {
+ params = [ params ];
+ }
+ return AjxFormat.prototype.format.call(this, params);
+};
+
+//
+// AjxMessageFormat.MessageSegment class
+//
+
+AjxMessageFormat.MessageSegment = function(format, s) {
+ AjxFormat.Segment.call(this, format, s);
+ var parts = s.split(',');
+ this._index = Number(parts[0]);
+ this._type = parts[1] || "string";
+ this._style = parts[2];
+ switch (this._type) {
+ case "number": {
+ switch (this._style) {
+ case "integer": this._formatter = AjxNumberFormat.getIntegerInstance(); break;
+ case "currency": this._formatter = AjxNumberFormat.getCurrencyInstance(); break;
+ case "percent": this._formatter = AjxNumberFormat.getPercentInstance(); break;
+ default: this._formatter = this._style == null ? AjxNumberFormat.getInstance() : new AjxNumberFormat(this._style);
+ }
+ break;
+ }
+ case "date": case "time": {
+ var func = this._type == "date" ? AjxDateFormat.getDateInstance : AjxDateFormat.getTimeInstance;
+ switch (this._style) {
+ case "short": this._formatter = func(AjxDateFormat.SHORT); break;
+ case "medium": this._formatter = func(AjxDateFormat.MEDIUM); break;
+ case "long": this._formatter = func(AjxDateFormat.LONG); break;
+ case "full": this._formatter = func(AjxDateFormat.FULL); break;
+ default: this._formatter = this._style == null ? func(AjxDateFormat.DEFAULT) : new AjxDateFormat(this._style);
+ }
+ break;
+ }
+ case "choice": /*TODO*/ break;
+ }
+
+};
+AjxMessageFormat.MessageSegment.prototype = new AjxFormat.Segment;
+AjxMessageFormat.MessageSegment.prototype.constructor = AjxMessageFormat.MessageSegment;
+
+AjxMessageFormat.MessageSegment.prototype.toString = function() {
+ var a = [ "message: \"", this._s, "\", index: ", this.index ];
+ if (this._type) a.push(", type: ", this._type);
+ if (this._style) a.push(", style: ", this._style);
+ if (this._formatter) a.push(", formatter: ", this._formatter.toString());
+ return a.join("");
+};
+
+// Data
+
+AjxMessageFormat.MessageSegment.prototype._index;
+AjxMessageFormat.MessageSegment.prototype._type;
+AjxMessageFormat.MessageSegment.prototype._style;
+
+AjxMessageFormat.MessageSegment.prototype._formatter;
+
+// Public methods
+
+AjxMessageFormat.MessageSegment.prototype.format = function(args) {
+ var object = args[this._index];
+ return this._formatter ? this._formatter.format(object) : String(object);
+};
+
+//
+// AjxNumberFormat class
+//
+
+/**
+ * @param pattern The number pattern.
+ * @param skipNegFormat Specifies whether to skip the generation of this
+ * format's negative value formatter.
+ * <p>
+
+ * <strong>Note:</strong>
+ * This parameter is only used by the implementation
+ * and should not be passed by application code
+ * instantiating a custom number format.
+ */
+function AjxNumberFormat(pattern, skipNegFormat) {
+ AjxFormat.call(this, pattern);
+ if (pattern == "") return;
+
+ var patterns = pattern.split(/;/);
+ var pattern = patterns[0];
+
+ // parse prefix
+ var i = 0;
+ var results = this.__parseStatic(pattern, i);
+ i = results.offset;
+ var hasPrefix = results.text != "";
+ if (hasPrefix) {
+ this._segments.push(new AjxFormat.TextSegment(this, results.text));
+ }
+
+ // parse number descriptor
+ var start = i;
+ while (i < pattern.length &&
+ AjxNumberFormat._META_CHARS.indexOf(pattern.charAt(i)) != -1) {
+ i++;
+ }
+ var end = i;
+
+ var numPattern = pattern.substring(start, end);
+ var e = numPattern.indexOf('E');
+ var expon = e != -1 ? numPattern.substring(e + 1) : null;
+ if (expon) {
+ numPattern = numPattern.substring(0, e);
+ this._showExponent = true;
+ }
+
+ var dot = numPattern.indexOf('.');
+ var whole = dot != -1 ? numPattern.substring(0, dot) : numPattern;
+ if (whole) {
+ var comma = whole.lastIndexOf(',');
+ if (comma != -1) {
+ this._groupingOffset = whole.length - comma - 1;
+ }
+ whole = whole.replace(/[^#0]/g,"");
+ var zero = whole.indexOf('0');
+ if (zero != -1) {
+ this._minIntDigits = whole.length - zero;
+ }
+ this._maxIntDigits = whole.length;
+ }
+
+ var fract = dot != -1 ? numPattern.substring(dot + 1) : null;
+ if (fract) {
+ var zero = fract.lastIndexOf('0');
+ if (zero != -1) {
+ this._minFracDigits = zero + 1;
+ }
+ this._maxFracDigits = fract.replace(/[^#0]/g,"").length;
+ }
+
+ this._segments.push(new AjxNumberFormat.NumberSegment(this, numPattern));
+
+ // parse suffix
+ var results = this.__parseStatic(pattern, i);
+ i = results.offset;
+ if (results.text != "") {
+ this._segments.push(new AjxFormat.TextSegment(this, results.text));
+ }
+
+ // add negative formatter
+ if (skipNegFormat) return;
+
+ if (patterns.length > 1) {
+ var pattern = patterns[1];
+ this._negativeFormatter = new AjxNumberFormat(pattern, true);
+ }
+ else {
+ // no negative pattern; insert minus sign before number segment
+ var formatter = new AjxNumberFormat("");
+ formatter._segments = formatter._segments.concat(this._segments);
+
+ var index = hasPrefix ? 1 : 0;
+ var minus = new AjxFormat.TextSegment(formatter, I18nMsg.numberSignMinus);
+ formatter._segments.splice(index, 0, minus);
+
+ this._negativeFormatter = formatter;
+ }
+}
+AjxNumberFormat.prototype = new AjxFormat;
+AjxNumberFormat.prototype.constructor = AjxNumberFormat;
+
+AjxNumberFormat.prototype.toString = function() {
+ var array = [
+ "[AjxNumberFormat: ",
+ "formatter=", AjxFormat.prototype.toString.call(this)
+ ];
+ if (this._negativeFormatter) {
+ array.push(", negativeFormatter=", this._negativeFormatter.toString());
+ }
+ array.push(']');
+ return array.join("");
+};
+
+// Constants
+
+AjxNumberFormat._NUMBER = "number";
+AjxNumberFormat._INTEGER = "integer";
+AjxNumberFormat._CURRENCY = "currency";
+AjxNumberFormat._PERCENT = "percent";
+
+AjxNumberFormat._META_CHARS = "0#.,E";
+
+AjxNumberFormat._FORMATTERS = {};
+
+// Data
+
+AjxNumberFormat.prototype._groupingOffset = Number.MAX_VALUE;
+AjxNumberFormat.prototype._maxIntDigits;
+AjxNumberFormat.prototype._minIntDigits = 1;
+AjxNumberFormat.prototype._maxFracDigits;
+AjxNumberFormat.prototype._minFracDigits;
+AjxNumberFormat.prototype._isCurrency = false;
+AjxNumberFormat.prototype._isPercent = false;
+AjxNumberFormat.prototype._isPerMille = false;
+AjxNumberFormat.prototype._showExponent = false;
+
+AjxNumberFormat.prototype._negativeFormatter;
+
+// Static functions
+
+AjxNumberFormat.getInstance = function() {
+ if (!AjxNumberFormat._FORMATTERS[AjxNumberFormat._NUMBER]) {
+ AjxNumberFormat._FORMATTERS[AjxNumberFormat._NUMBER] = new AjxNumberFormat(I18nMsg.formatNumber);
+ }
+ return AjxNumberFormat._FORMATTERS[AjxNumberFormat._NUMBER];
+};
+AjxNumberFormat.getNumberInstance = AjxNumberFormat.getInstance;
+AjxNumberFormat.getCurrencyInstance = function() {
+ if (!AjxNumberFormat._FORMATTERS[AjxNumberFormat._CURRENCY]) {
+ AjxNumberFormat._FORMATTERS[AjxNumberFormat._CURRENCY] = new AjxNumberFormat(I18nMsg.formatNumberCurrency);
+ }
+ return AjxNumberFormat._FORMATTERS[AjxNumberFormat._CURRENCY];
+};
+AjxNumberFormat.getIntegerInstance = function() {
+ if (!AjxNumberFormat._FORMATTERS[AjxNumberFormat._INTEGER]) {
+ AjxNumberFormat._FORMATTERS[AjxNumberFormat._INTEGER] = new AjxNumberFormat(I18nMsg.formatNumberInteger);
+ }
+ return AjxNumberFormat._FORMATTERS[AjxNumberFormat._INTEGER];
+};
+AjxNumberFormat.getPercentInstance = function() {
+ if (!AjxNumberFormat._FORMATTERS[AjxNumberFormat._PERCENT]) {
+ AjxNumberFormat._FORMATTERS[AjxNumberFormat._PERCENT] = new AjxNumberFormat(I18nMsg.formatNumberPercent);
+ }
+ return AjxNumberFormat._FORMATTERS[AjxNumberFormat._PERCENT];
+};
+
+AjxNumberFormat.format = function(pattern, number) {
+ return new AjxNumberFormat(pattern).format(number);
+};
+
+// Public methods
+
+AjxNumberFormat.prototype.format = function(number) {
+ if (number < 0 && this._negativeFormatter) {
+ return this._negativeFormatter.format(number);
+ }
+ return AjxFormat.prototype.format.call(this, number);
+};
+
+// Private methods
+
+AjxNumberFormat.prototype.__parseStatic = function(s, i) {
+ var data = [];
+ while (i < s.length) {
+ var c = s.charAt(i++);
+ if (AjxNumberFormat._META_CHARS.indexOf(c) != -1) {
+ i--;
+ break;
+ }
+ switch (c) {
+ case "'": {
+ var start = i;
+ while (i < s.length && s.charAt(i++) != "'") {
+ // do nothing
+ }
+ var end = i;
+ c = end - start == 0 ? "'" : s.substring(start, end);
+ break;
+ }
+ case '%': {
+ c = I18nMsg.numberSignPercent;
+ this._isPercent = true;
+ break;
+ }
+ case '\u2030': {
+ c = I18nMsg.numberSignPerMill;
+ this._isPerMille = true;
+ break;
+ }
+ case '\u00a4': {
+ c = s.charAt(i) == '\u00a4'
+ ? I18nMsg.currencyCode : I18nMsg.currencySymbol;
+ this._isCurrency = true;
+ break;
+ }
+ }
+ data.push(c);
+ }
+ return { text: data.join(""), offset: i };
+};
+
+//
+// AjxNumberFormat.NumberSegment class
+//
+
[... 33587 lines stripped ...]