diff --git a/UNGProject/css/gadget.css b/UNGProject/css/gadget.css
index c3482879e668ff30ec9e7a288ce56d21106d6f6c..8f26cb7ecd2002fbc34264dbaabdc48b9884482f 100644
--- a/UNGProject/css/gadget.css
+++ b/UNGProject/css/gadget.css
@@ -13,9 +13,9 @@ div#pad-navigation-wrapper {
 }
 #pad-navigation-wrapper {
     border-bottom: 1px solid #3D6474;
-    height: 25px;
+    height: 38px;
     margin-top: 10px;
-    width: 100%;
+    width: 96%;
 }
             /* tabs */
 #tabs_switcher {
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_ROOT.js b/UNGProject/dojo/dojo/nls/refimpldojo_ROOT.js
new file mode 100644
index 0000000000000000000000000000000000000000..8c51402b1fe47b4f503830c9c8bef58beacfd3e8
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_ROOT.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_ROOT");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.ROOT");dojo.cldr.nls.gregorian.ROOT={"months-format-narrow":["1","2","3","4","5","6","7","8","9","10","11","12"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"Day of the Week","dateFormatItem-yQQQ":"yyyy QQQ","dateFormatItem-yMEd":"EEE, yyyy-M-d","dateFormatItem-MMMEd":"E MMM d","eraNarrow":["BCE","CE"],"dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateFormat-long":"yyyy MMMM d","months-format-wide":["1","2","3","4","5","6","7","8","9","10","11","12"],"dateFormat-full":"EEEE, yyyy MMMM dd","dateFormatItem-Md":"M-d","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","field-era":"Era","dateFormatItem-yM":"yyyy-M","months-standAlone-wide":["1","2","3","4","5","6","7","8","9","10","11","12"],"timeFormat-short":"HH:mm","quarters-format-wide":["Q1","Q2","Q3","Q4"],"dateTimeFormat":"{1} {0}","timeFormat-long":"HH:mm:ss z","field-year":"Year","dateFormatItem-yMMM":"yyyy MMM","dateFormatItem-yQ":"yyyy Q","dateTimeFormats-appendItem-Era":"{0} {1}","field-hour":"Hour","months-format-abbr":["1","2","3","4","5","6","7","8","9","10","11","12"],"patternChars":"GyMdkHmsSEDFwWahKzYeugAZvcL","timeFormat-full":"HH:mm:ss v","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","am":"AM","months-standAlone-abbr":["1","2","3","4","5","6","7","8","9","10","11","12"],"quarters-format-abbr":["Q1","Q2","Q3","Q4"],"quarters-standAlone-wide":["Q1","Q2","Q3","Q4"],"dateFormatItem-M":"L","days-standAlone-wide":["1","2","3","4","5","6","7"],"dateFormatItem-MMMMd":"MMMM d","timeFormat-medium":"HH:mm:ss","dateFormatItem-Hm":"H:mm","quarters-standAlone-abbr":["Q1","Q2","Q3","Q4"],"eraAbbr":["BCE","CE"],"field-minute":"Minute","field-dayperiod":"Dayperiod","days-standAlone-abbr":["1","2","3","4","5","6","7"],"dateFormatItem-d":"d","dateFormatItem-ms":"mm:ss","quarters-format-narrow":["1","2","3","4"],"dateFormatItem-MMMd":"MMM d","dateFormatItem-MEd":"E, M-d","dateFormatItem-yMMMM":"yyyy MMMM","field-day":"Day","days-format-wide":["1","2","3","4","5","6","7"],"field-zone":"Zone","dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateFormatItem-y":"yyyy","months-standAlone-narrow":["1","2","3","4","5","6","7","8","9","10","11","12"],"dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","days-format-abbr":["1","2","3","4","5","6","7"],"eraNames":["BCE","CE"],"days-format-narrow":["1","2","3","4","5","6","7"],"field-month":"Month","days-standAlone-narrow":["1","2","3","4","5","6","7"],"dateFormatItem-MMM":"LLL","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","pm":"PM","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateFormatItem-MMMMEd":"E MMMM d","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateFormat-short":"yyyy-MM-dd","field-second":"Second","dateFormatItem-yMMMEd":"EEE, yyyy MMM d","dateTimeFormats-appendItem-Timezone":"{0} {1}","field-week":"Week","dateFormat-medium":"yyyy MMM d"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.ROOT");dijit.nls.loading.ROOT={"loadingState":"Loading...","errorState":"Sorry, an error occurred"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.ROOT");dijit.nls.common.ROOT={"buttonOk":"OK","buttonCancel":"Cancel","buttonSave":"Save","itemClose":"Close"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.ROOT");dijit.form.nls.validate.ROOT={"rangeMessage":"This value is out of range.","invalidMessage":"The value entered is not valid.","missingMessage":"This value is required."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.ROOT");dojo.cldr.nls.number.ROOT={"scientificFormat":"#E0","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","infinity":"∞","list":";","percentSign":"%","minusSign":"-","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","nan":"NaN","nativeZeroDigit":"0","plusSign":"+","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencyFormat":"¤ #,##0.00","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","perMille":"‰","group":",","percentFormat":"#,##0%","decimalFormat":"#,##0.###","decimal":".","patternDigit":"#","currencySpacing-beforeCurrency-insertBetween":" ","exponential":"E"};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.ROOT");dijit.form.nls.ComboBox.ROOT={"previousMessage":"Previous choices","nextMessage":"More choices"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_ar.js b/UNGProject/dojo/dojo/nls/refimpldojo_ar.js
new file mode 100644
index 0000000000000000000000000000000000000000..5df8abfcf4a55af6584533504f3a23dee055cd12
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_ar.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_ar");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.ar");dojo.cldr.nls.gregorian.ar={"dateFormatItem-yM":"M/yyyy","field-dayperiod":"ص/م","dateFormatItem-yQ":"yyyy Q","field-minute":"الدقائق","eraNames":["قبل الميلاد","ميلادي"],"dateFormatItem-MMMEd":"E d MMM","field-weekday":"اليوم","dateFormatItem-yQQQ":"yyyy QQQ","dateFormatItem-MMdd":"dd‏/MM","days-standAlone-wide":["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت"],"dateFormatItem-MMM":"LLL","patternChars":"GanjkHmsSEDFwWxhKzAeugXZvcL","months-standAlone-narrow":["ي","ف","م","أ","و","ن","ل","غ","س","ك","ب","د"],"field-era":"العصر","field-hour":"الساعات","quarters-standAlone-abbr":["الربع الأول","الربع الثاني","الربع الثالث","الربع الرابع"],"dateFormatItem-y":"yyyy","timeFormat-full":"v h:mm:ss a","months-standAlone-abbr":["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],"dateFormatItem-yMMM":"MMM yyyy","days-standAlone-narrow":["ح","ن","ث","ر","خ","ج","س"],"eraAbbr":["ق.م","م"],"dateFormatItem-yyyyMM":"MM‏/yyyy","dateFormatItem-yyyyMMMM":"MMMM, yyyy","dateFormat-long":"d MMMM، yyyy","timeFormat-medium":"h:mm:ss a","field-zone":"التوقيت","dateFormatItem-Hm":"H:mm","dateFormat-medium":"dd‏/MM‏/yyyy","quarters-standAlone-wide":["الربع الأول","الربع الثاني","الربع الثالث","الربع الرابع"],"dateTimeFormat":"{1} {0}","dateFormatItem-yMMMM":"MMMM yyyy","dateFormatItem-ms":"mm:ss","field-year":"السنة","quarters-standAlone-narrow":["١","٢","٣","٤"],"field-week":"الأسبوع","months-standAlone-wide":["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],"dateFormatItem-MMMMEd":"E d MMMM","dateFormatItem-MMMd":"d MMM","quarters-format-narrow":["١","٢","٣","٤"],"dateFormatItem-yyQ":"Q yy","timeFormat-long":"z h:mm:ss a","months-format-abbr":["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],"timeFormat-short":"h:mm a","field-month":"الشهر","dateFormatItem-MMMMd":"d MMMM","quarters-format-abbr":["الربع الأول","الربع الثاني","الربع الثالث","الربع الرابع"],"days-format-abbr":["ح","ن","ث","ر","خ","ج","س"],"pm":"م","dateFormatItem-M":"L","days-format-narrow":["ح","ن","ث","ر","خ","ج","س"],"field-second":"الثواني","field-day":"يوم","months-format-narrow":["ي","ف","م","أ","و","ن","ل","غ","س","ك","ب","د"],"am":"ص","days-standAlone-abbr":["أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت"],"dateFormat-short":"d‏/M‏/yyyy","dateFormat-full":"EEEE، d MMMM، yyyy","months-format-wide":["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],"dateFormatItem-d":"d","quarters-format-wide":["الربع الأول","الربع الثاني","الربع الثالث","الربع الرابع"],"days-format-wide":["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت"],"eraNarrow":["ق.م","م"],"dateFormatItem-yMEd":"EEE, yyyy-M-d","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateFormatItem-Md":"M-d","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","dateFormatItem-MEd":"E, M-d","dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateFormatItem-yMMMEd":"EEE, yyyy MMM d","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.ar");dijit.nls.loading.ar={"loadingState":"جاري التحميل...","errorState":"عفوا، حدث خطأ"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.ar");dijit.nls.common.ar={"buttonOk":"حسنا","buttonCancel":"الغاء","buttonSave":"حفظ","itemClose":"اغلاق"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.ar");dijit.form.nls.validate.ar={"rangeMessage":"هذه القيمة ليس بالمدى الصحيح.","invalidMessage":"القيمة التي تم ادخالها غير صحيحة.","missingMessage":"يجب ادخال هذه القيمة."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.ar");dojo.cldr.nls.number.ar={"group":"٬","percentSign":"٪","exponential":"اس","list":"؛","decimal":"٫","nan":"ليس رقم","nativeZeroDigit":"٠","decimalFormat":"#,##0.###;#,##0.###-","currencyFormat":"¤ #,##0.00;¤ #,##0.00-","scientificFormat":"#E0","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","infinity":"∞","minusSign":"-","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","plusSign":"+","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","perMille":"‰","percentFormat":"#,##0%","patternDigit":"#","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.ar");dijit.form.nls.ComboBox.ar={"previousMessage":"الاختيارات السابقة","nextMessage":"مزيد من الاختيارات"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_ca.js b/UNGProject/dojo/dojo/nls/refimpldojo_ca.js
new file mode 100644
index 0000000000000000000000000000000000000000..c0690cbdda651eb2ff506cf3e29e3722071f6f33
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_ca.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_ca");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.ca");dojo.cldr.nls.gregorian.ca={"dateFormatItem-yM":"M/yyyy","field-dayperiod":"AM/PM","dateFormatItem-yQ":"Q yyyy","field-minute":"minut","eraNames":["aC","dC"],"dateFormatItem-MMMEd":"E MMM d","field-weekday":"dia de la setmana","dateFormatItem-yQQQ":"QQQ yyyy","days-standAlone-wide":["diumenge","dilluns","dimarts","dimecres","dijous","divendres","dissabte"],"dateFormatItem-MMM":"LLL","patternChars":"GuMtkHmsSEDFwWahKzUeygAZvcL","months-standAlone-narrow":["g","f","m","a","m","j","j","a","s","o","n","d"],"field-era":"era","field-hour":"hora","dateFormatItem-hhmm":"hh:mm a","quarters-standAlone-abbr":["1T","2T","3T","4T"],"dateFormatItem-y":"yyyy","timeFormat-full":"H:mm:ss v","months-standAlone-abbr":["gen.","febr.","març","abr.","maig","juny","jul.","ag.","set.","oct.","nov.","des."],"dateFormatItem-yMMM":"MMM yyyy","days-standAlone-narrow":["g","l","t","c","j","v","s"],"eraAbbr":["aC","dC"],"dateFormatItem-yyyyMM":"MM/yyyy","dateFormat-long":"d 'de' MMMM 'de' yyyy","timeFormat-medium":"H:mm:ss","field-zone":"zona","dateFormatItem-Hm":"H:mm","dateFormat-medium":"dd/MM/yyyy","quarters-standAlone-wide":["1r trimestre","2n trimestre","3r trimestre","4t trimestre"],"dateTimeFormat":"{1} {0}","dateFormatItem-yMMMM":"LLLL 'del' yyyy","dateFormatItem-ms":"mm:ss","field-year":"any","quarters-standAlone-narrow":["1","2","3","4"],"field-week":"setmana","months-standAlone-wide":["gener","febrer","març","abril","maig","juny","juliol","agost","setembre","octubre","novembre","desembre"],"dateFormatItem-MMMMEd":"E d MMMM","dateFormatItem-MMMd":"MMM d","dateFormatItem-yyQ":"Q yy","timeFormat-long":"H:mm:ss z","months-format-abbr":["gen.","febr.","març","abr.","maig","juny","jul.","ag.","set.","oct.","nov.","des."],"timeFormat-short":"H:mm","field-month":"mes","dateFormatItem-MMMMd":"d MMMM","quarters-format-abbr":["1T","2T","3T","4T"],"days-format-abbr":["dg.","dl.","dt.","dc.","dj.","dv.","ds."],"pm":"PM","dateFormatItem-M":"L","dateFormatItem-mmss":"mm:ss","days-format-narrow":["g","l","t","c","j","v","s"],"field-second":"segon","field-day":"dia","dateFormatItem-MEd":"E d/M","months-format-narrow":["g","f","m","a","m","j","j","a","s","o","n","d"],"dateFormatItem-hhmmss":"hh:mm:ss a","am":"AM","days-standAlone-abbr":["dg","dl","dt","dc","dj","dv","ds"],"dateFormat-short":"dd/MM/yy","dateFormatItem-yMMMEd":"EEE d MMM yyyy","dateFormat-full":"EEEE d 'de' MMMM 'de' yyyy","dateFormatItem-Md":"d/M","dateFormatItem-yMEd":"E d/M/yyyy","months-format-wide":["gener","febrer","març","abril","maig","juny","juliol","agost","setembre","octubre","novembre","desembre"],"dateFormatItem-d":"d","quarters-format-wide":["1r trimestre","2n trimestre","3r trimestre","4t trimestre"],"days-format-wide":["diumenge","dilluns","dimarts","dimecres","dijous","divendres","dissabte"],"eraNarrow":["aC","dC"],"dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.ca");dijit.nls.loading.ca={"loadingState":"S'està carregant...","errorState":"Ens sap greu. S'ha produït un error."};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.ca");dijit.nls.common.ca={"buttonOk":"D'acord","buttonCancel":"Cancel·la","buttonSave":"Desa","itemClose":"Tanca"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.ca");dijit.form.nls.validate.ca={"rangeMessage":"Aquest valor és fora de l'interval","invalidMessage":"El valor introduït no és vàlid","missingMessage":"Aquest valor és necessari"};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.ca");dojo.cldr.nls.number.ca={"group":".","percentSign":"%","exponential":"E","percentFormat":"#,##0%","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":",","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","currencyFormat":"#,##0.00 ¤","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.ca");dijit.form.nls.ComboBox.ca={"previousMessage":"Opcions anteriors","nextMessage":"Més opcions"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_cs.js b/UNGProject/dojo/dojo/nls/refimpldojo_cs.js
new file mode 100644
index 0000000000000000000000000000000000000000..5178881611a3c125b00fbbd468fbb3f53e85a293
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_cs.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_cs");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.cs");dojo.cldr.nls.gregorian.cs={"quarters-standAlone-wide":["1. čtvrtletí","2. čtvrtletí","3. čtvrtletí","4. čtvrtletí"],"quarters-format-abbr":["1. čtvrtletí","2. čtvrtletí","3. čtvrtletí","4. čtvrtletí"],"dateFormat-medium":"d.M.yyyy","quarters-standAlone-abbr":["1. čtvrtletí","2. čtvrtletí","3. čtvrtletí","4. čtvrtletí"],"eraNarrow":["př.Kr.","po Kr."],"months-format-narrow":["l","ú","b","d","k","č","č","s","z","ř","l","p"],"pm":"odp.","months-standAlone-narrow":["l","ú","b","d","k","č","č","s","z","ř","l","p"],"months-standAlone-wide":["leden","únor","březen","duben","květen","červen","červenec","srpen","září","říjen","listopad","prosinec"],"eraNames":["př.Kr.","po Kr."],"am":"dop.","days-standAlone-narrow":["N","P","Ú","S","Č","P","S"],"months-standAlone-abbr":["1.","2.","3.","4.","5.","6.","7.","8.","9.","10.","11.","12."],"timeFormat-medium":"H:mm:ss","dateFormat-long":"d. MMMM yyyy","dateFormat-short":"d.M.yy","months-format-wide":["ledna","února","března","dubna","května","června","července","srpna","září","října","listopadu","prosince"],"days-standAlone-wide":["neděle","pondělí","úterý","středa","čtvrtek","pátek","sobota"],"days-format-narrow":["N","P","Ú","S","Č","P","S"],"timeFormat-short":"H:mm","months-format-abbr":["ledna","února","března","dubna","května","června","července","srpna","září","října","listopadu","prosince"],"days-standAlone-abbr":["ne","po","út","st","čt","pá","so"],"days-format-wide":["neděle","pondělí","úterý","středa","čtvrtek","pátek","sobota"],"eraAbbr":["př.Kr.","po Kr."],"patternChars":"GuMtkHmsSEDFwWahKzUeygAZvcL","quarters-format-wide":["1. čtvrtletí","2. čtvrtletí","3. čtvrtletí","4. čtvrtletí"],"dateFormat-full":"EEEE, d. MMMM yyyy","days-format-abbr":["ne","po","út","st","čt","pá","so"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"Day of the Week","dateFormatItem-yQQQ":"yyyy QQQ","dateFormatItem-yMEd":"EEE, yyyy-M-d","dateFormatItem-MMMEd":"E MMM d","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateFormatItem-Md":"M-d","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","field-era":"Era","dateFormatItem-yM":"yyyy-M","dateTimeFormat":"{1} {0}","timeFormat-long":"HH:mm:ss z","field-year":"Year","dateFormatItem-yMMM":"yyyy MMM","dateFormatItem-yQ":"yyyy Q","dateTimeFormats-appendItem-Era":"{0} {1}","field-hour":"Hour","timeFormat-full":"HH:mm:ss v","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","dateFormatItem-M":"L","dateFormatItem-MMMMd":"MMMM d","dateFormatItem-Hm":"H:mm","field-minute":"Minute","field-dayperiod":"Dayperiod","dateFormatItem-d":"d","dateFormatItem-ms":"mm:ss","quarters-format-narrow":["1","2","3","4"],"dateFormatItem-MMMd":"MMM d","dateFormatItem-MEd":"E, M-d","dateFormatItem-yMMMM":"yyyy MMMM","field-day":"Day","field-zone":"Zone","dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateFormatItem-y":"yyyy","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","field-month":"Month","dateFormatItem-MMM":"LLL","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateFormatItem-MMMMEd":"E MMMM d","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","field-second":"Second","dateFormatItem-yMMMEd":"EEE, yyyy MMM d","dateTimeFormats-appendItem-Timezone":"{0} {1}","field-week":"Week"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.cs");dijit.nls.loading.cs={"loadingState":"Probíhá načítání...","errorState":"Omlouváme se, došlo k chybě"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.cs");dijit.nls.common.cs={"buttonOk":"OK","buttonCancel":"Storno","buttonSave":"Uložit","itemClose":"Zavřít"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.cs");dijit.form.nls.validate.cs={"rangeMessage":"Tato hodnota je mimo rozsah.","invalidMessage":"Zadaná hodnota není platná.","missingMessage":"Tato hodnota je vyžadována."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.cs");dojo.cldr.nls.number.cs={"group":" ","percentSign":"%","exponential":"E","percentFormat":"#,##0%","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":",","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","currencyFormat":"#,##0.00 ¤","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.cs");dijit.form.nls.ComboBox.cs={"previousMessage":"Předchozí volby","nextMessage":"Další volby"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_da.js b/UNGProject/dojo/dojo/nls/refimpldojo_da.js
new file mode 100644
index 0000000000000000000000000000000000000000..da36103b6da3e2682da5ef35a44b22c57fb7e5f8
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_da.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_da");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.da");dojo.cldr.nls.gregorian.da={"months-format-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"ugedag","dateFormatItem-yQQQ":"QQQ yyyy","dateFormatItem-yMEd":"EEE. d-M-yyyy","dateFormatItem-MMMEd":"E d MMM","eraNarrow":["f.Kr.","e.Kr."],"dateFormat-long":"d. MMM yyyy","months-format-wide":["januar","februar","marts","april","maj","juni","juli","august","september","oktober","november","december"],"dateFormat-full":"EEEE 'den' d. MMMM yyyy","dateFormatItem-Md":"d/M","field-era":"æra","dateFormatItem-yM":"M-yyyy","months-standAlone-wide":["januar","februar","marts","april","maj","juni","juli","august","september","oktober","november","december"],"timeFormat-short":"HH.mm","quarters-format-wide":["1. kvartal","2. kvartal","3. kvartal","4. kvartal"],"dateTimeFormat":"{1} {0}","timeFormat-long":"HH:mm:ss z","field-year":"år","dateFormatItem-yMMM":"MMM yyyy","dateFormatItem-yQ":"Q yyyy","field-hour":"time","dateFormatItem-MMdd":"dd/MM","months-format-abbr":["jan","feb","mar","apr","maj","jun","jul","aug","sep","okt","nov","dec"],"dateFormatItem-yyQ":"Q. 'kvartal' yy","patternChars":"GuMtkHmsSEDFwWahKzUeygAZvcL","timeFormat-full":"HH.mm.ss v","am":"f.m.","dateFormatItem-H":"H","months-standAlone-abbr":["jan","feb","mar","apr","maj","jun","jul","aug","sep","okt","nov","dec"],"quarters-format-abbr":["K1","K2","K3","K4"],"quarters-standAlone-wide":["1. kvartal","2. kvartal","3. kvartal","4. kvartal"],"dateFormatItem-HHmmss":"HH.mm.ss","dateFormatItem-M":"M","days-standAlone-wide":["søndag","mandag","tirsdag","onsdag","torsdag","fredag","lørdag"],"dateFormatItem-yyyyMMM":"MMM yyyy","dateFormatItem-MMMMd":"d. MMMM","dateFormatItem-yyMMM":"MMM yy","timeFormat-medium":"HH.mm.ss","dateFormatItem-Hm":"HH.mm","quarters-standAlone-abbr":["K1","K2","K3","K4"],"eraAbbr":["f.Kr.","e.Kr."],"field-minute":"minut","field-dayperiod":"dagtid","days-standAlone-abbr":["søn","man","tir","ons","tor","fre","lør"],"dateFormatItem-d":"d.","dateFormatItem-ms":"mm.ss","dateFormatItem-MMMd":"d. MMM","dateFormatItem-MEd":"E. d-M","dateFormatItem-yMMMM":"MMMM yyyy","field-day":"dag","days-format-wide":["søndag","mandag","tirsdag","onsdag","torsdag","fredag","lørdag"],"field-zone":"zone","dateFormatItem-yyyyMM":"MM/yyyy","dateFormatItem-y":"yyyy","months-standAlone-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"dateFormatItem-yyMM":"MM/yy","days-format-abbr":["søn","man","tir","ons","tor","fre","lør"],"eraNames":["f.Kr.","e.Kr."],"days-format-narrow":["S","M","T","O","T","F","L"],"field-month":"måned","days-standAlone-narrow":["S","M","T","O","T","F","L"],"dateFormatItem-MMM":"MMM","dateFormatItem-HHmm":"HH.mm","pm":"e.m.","dateFormatItem-MMMMEd":"E, d. MMMM","dateFormat-short":"dd/MM/yy","field-second":"sekund","dateFormatItem-yMMMEd":"EEE. d. MMM yyyy","field-week":"uge","dateFormat-medium":"dd/MM/yyyy","dateFormatItem-mmss":"mm.ss","dateFormatItem-yyyy":"yyyy","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.da");dijit.nls.loading.da={"loadingState":"Indlæser...","errorState":"Der er opstået en fejl"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.da");dijit.nls.common.da={"buttonOk":"OK","buttonCancel":"Annullér","buttonSave":"Gem","itemClose":"Luk"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.da");dijit.form.nls.validate.da={"rangeMessage":"Værdien er uden for intervallet.","invalidMessage":"Den angivne værdi er ugyldig.","missingMessage":"Værdien er påkrævet."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.da");dojo.cldr.nls.number.da={"group":".","percentSign":"%","exponential":"E","percentFormat":"#,##0 %","scientificFormat":"#E0","list":",","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":",","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","currencyFormat":"#,##0.00 ¤","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.da");dijit.form.nls.ComboBox.da={"previousMessage":"Forrige valg","nextMessage":"Flere valg"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_de-de.js b/UNGProject/dojo/dojo/nls/refimpldojo_de-de.js
new file mode 100644
index 0000000000000000000000000000000000000000..38ebe808e0507225c7b4c2b203928d21092a86ae
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_de-de.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_de-de");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.de_de");dojo.cldr.nls.gregorian.de_de={"months-format-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"Wochentag","dateFormatItem-yyQQQQ":"QQQQ yy","dateFormatItem-yQQQ":"QQQ yyyy","dateFormatItem-yMEd":"EEE, yyyy-M-d","dateFormatItem-MMMEd":"E d. MMM","eraNarrow":["v. Chr.","n. Chr."],"dateFormat-long":"d. MMMM yyyy","months-format-wide":["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],"dateFormat-full":"EEEE, d. MMMM yyyy","dateFormatItem-Md":"d.M.","dateFormatItem-yyMMdd":"dd.MM.yy","field-era":"Epoche","dateFormatItem-yM":"yyyy-M","months-standAlone-wide":["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],"timeFormat-short":"HH:mm","quarters-format-wide":["1. Quartal","2. Quartal","3. Quartal","4. Quartal"],"dateTimeFormat":"{1} {0}","timeFormat-long":"HH:mm:ss z","field-year":"Jahr","dateFormatItem-yMMM":"MMM yyyy","dateFormatItem-yQ":"Q yyyy","dateFormatItem-yyyyMMMM":"MMMM yyyy","field-hour":"Stunde","dateFormatItem-MMdd":"dd.MM.","months-format-abbr":["Jan","Feb","Mrz","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],"dateFormatItem-yyQ":"Q yy","patternChars":"GjMtkHmsSEDFwWahKzJeugAZvcL","timeFormat-full":"HH:mm:ss v","am":"vorm.","dateFormatItem-H":"H","months-standAlone-abbr":["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],"quarters-format-abbr":["Q1","Q2","Q3","Q4"],"quarters-standAlone-wide":["1. Quartal","2. Quartal","3. Quartal","4. Quartal"],"dateFormatItem-HHmmss":"HH:mm:ss","dateFormatItem-hhmmss":"HH:mm:ss","dateFormatItem-M":"L","days-standAlone-wide":["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],"dateFormatItem-MMMMd":"d. MMMM","dateFormatItem-yyMMM":"MMM yy","timeFormat-medium":"HH:mm:ss","dateFormatItem-Hm":"H:mm","eraAbbr":["v. Chr.","n. Chr."],"field-minute":"Minute","field-dayperiod":"Tageshälfte","days-standAlone-abbr":["So.","Mo.","Di.","Mi.","Do.","Fr.","Sa."],"dateFormatItem-d":"d","dateFormatItem-ms":"mm:ss","dateFormatItem-MMMd":"d. MMM","dateFormatItem-MEd":"E, d.M.","dateFormatItem-yMMMM":"MMMM yyyy","field-day":"Tag","days-format-wide":["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],"field-zone":"Zone","dateFormatItem-y":"yyyy","months-standAlone-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"dateFormatItem-yyMM":"MM.yy","days-format-abbr":["So.","Mo.","Di.","Mi.","Do.","Fr.","Sa."],"eraNames":["v. Chr.","n. Chr."],"days-format-narrow":["S","M","D","M","D","F","S"],"field-month":"Monat","days-standAlone-narrow":["S","M","D","M","D","F","S"],"dateFormatItem-MMM":"LLL","dateFormatItem-HHmm":"HH:mm","pm":"nachm.","dateFormatItem-MMMMEd":"E d. MMMM","dateFormatItem-MMMMdd":"dd. MMMM","dateFormat-short":"dd.MM.yy","dateFormatItem-MMd":"d.MM.","field-second":"Sekunde","dateFormatItem-yMMMEd":"EEE, d. MMM yyyy","dateFormatItem-hhmm":"HH:mm","dateFormatItem-Ed":"E d.","field-week":"Woche","dateFormat-medium":"dd.MM.yyyy","dateFormatItem-mmss":"mm:ss","dateFormatItem-yyyy":"yyyy","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-standAlone-abbr":["Q1","Q2","Q3","Q4"],"quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.de_de");dijit.nls.loading.de_de={"loadingState":"Wird geladen...","errorState":"Es ist ein Fehler aufgetreten."};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.de_de");dijit.nls.common.de_de={"buttonOk":"OK","buttonCancel":"Abbrechen","buttonSave":"Speichern","itemClose":"Schließen"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.de_de");dijit.form.nls.validate.de_de={"rangeMessage":"Dieser Wert liegt außerhalb des gültigen Bereichs. ","invalidMessage":"Der eingegebene Wert ist ungültig. ","missingMessage":"Dieser Wert ist erforderlich."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.de_de");dojo.cldr.nls.number.de_de={"currencyFormat":"#,##0.00 ¤","group":".","percentSign":"%","exponential":"E","percentFormat":"#,##0 %","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":",","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.de_de");dijit.form.nls.ComboBox.de_de={"previousMessage":"Vorherige Auswahl","nextMessage":"Weitere Auswahlmöglichkeiten"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_de.js b/UNGProject/dojo/dojo/nls/refimpldojo_de.js
new file mode 100644
index 0000000000000000000000000000000000000000..6a15d5289b75cc57a57f96109da7f55de27b128c
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_de.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_de");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.de");dojo.cldr.nls.gregorian.de={"months-format-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"Wochentag","dateFormatItem-yyQQQQ":"QQQQ yy","dateFormatItem-yQQQ":"QQQ yyyy","dateFormatItem-yMEd":"EEE, yyyy-M-d","dateFormatItem-MMMEd":"E d. MMM","eraNarrow":["v. Chr.","n. Chr."],"dateFormat-long":"d. MMMM yyyy","months-format-wide":["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],"dateFormat-full":"EEEE, d. MMMM yyyy","dateFormatItem-Md":"d.M.","dateFormatItem-yyMMdd":"dd.MM.yy","field-era":"Epoche","dateFormatItem-yM":"yyyy-M","months-standAlone-wide":["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],"timeFormat-short":"HH:mm","quarters-format-wide":["1. Quartal","2. Quartal","3. Quartal","4. Quartal"],"dateTimeFormat":"{1} {0}","timeFormat-long":"HH:mm:ss z","field-year":"Jahr","dateFormatItem-yMMM":"MMM yyyy","dateFormatItem-yQ":"Q yyyy","dateFormatItem-yyyyMMMM":"MMMM yyyy","field-hour":"Stunde","dateFormatItem-MMdd":"dd.MM.","months-format-abbr":["Jan","Feb","Mrz","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],"dateFormatItem-yyQ":"Q yy","patternChars":"GjMtkHmsSEDFwWahKzJeugAZvcL","timeFormat-full":"HH:mm:ss v","am":"vorm.","dateFormatItem-H":"H","months-standAlone-abbr":["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],"quarters-format-abbr":["Q1","Q2","Q3","Q4"],"quarters-standAlone-wide":["1. Quartal","2. Quartal","3. Quartal","4. Quartal"],"dateFormatItem-HHmmss":"HH:mm:ss","dateFormatItem-hhmmss":"HH:mm:ss","dateFormatItem-M":"L","days-standAlone-wide":["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],"dateFormatItem-MMMMd":"d. MMMM","dateFormatItem-yyMMM":"MMM yy","timeFormat-medium":"HH:mm:ss","dateFormatItem-Hm":"H:mm","eraAbbr":["v. Chr.","n. Chr."],"field-minute":"Minute","field-dayperiod":"Tageshälfte","days-standAlone-abbr":["So.","Mo.","Di.","Mi.","Do.","Fr.","Sa."],"dateFormatItem-d":"d","dateFormatItem-ms":"mm:ss","dateFormatItem-MMMd":"d. MMM","dateFormatItem-MEd":"E, d.M.","dateFormatItem-yMMMM":"MMMM yyyy","field-day":"Tag","days-format-wide":["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],"field-zone":"Zone","dateFormatItem-y":"yyyy","months-standAlone-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"dateFormatItem-yyMM":"MM.yy","days-format-abbr":["So.","Mo.","Di.","Mi.","Do.","Fr.","Sa."],"eraNames":["v. Chr.","n. Chr."],"days-format-narrow":["S","M","D","M","D","F","S"],"field-month":"Monat","days-standAlone-narrow":["S","M","D","M","D","F","S"],"dateFormatItem-MMM":"LLL","dateFormatItem-HHmm":"HH:mm","pm":"nachm.","dateFormatItem-MMMMEd":"E d. MMMM","dateFormatItem-MMMMdd":"dd. MMMM","dateFormat-short":"dd.MM.yy","dateFormatItem-MMd":"d.MM.","field-second":"Sekunde","dateFormatItem-yMMMEd":"EEE, d. MMM yyyy","dateFormatItem-hhmm":"HH:mm","dateFormatItem-Ed":"E d.","field-week":"Woche","dateFormat-medium":"dd.MM.yyyy","dateFormatItem-mmss":"mm:ss","dateFormatItem-yyyy":"yyyy","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-standAlone-abbr":["Q1","Q2","Q3","Q4"],"quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.de");dijit.nls.loading.de={"loadingState":"Wird geladen...","errorState":"Es ist ein Fehler aufgetreten."};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.de");dijit.nls.common.de={"buttonOk":"OK","buttonCancel":"Abbrechen","buttonSave":"Speichern","itemClose":"Schließen"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.de");dijit.form.nls.validate.de={"rangeMessage":"Dieser Wert liegt außerhalb des gültigen Bereichs. ","invalidMessage":"Der eingegebene Wert ist ungültig. ","missingMessage":"Dieser Wert ist erforderlich."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.de");dojo.cldr.nls.number.de={"group":".","percentSign":"%","exponential":"E","percentFormat":"#,##0 %","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":",","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","currencyFormat":"#,##0.00 ¤","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.de");dijit.form.nls.ComboBox.de={"previousMessage":"Vorherige Auswahl","nextMessage":"Weitere Auswahlmöglichkeiten"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_el.js b/UNGProject/dojo/dojo/nls/refimpldojo_el.js
new file mode 100644
index 0000000000000000000000000000000000000000..a1f788373cff28825cc2b4c43a685afb68d95bee
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_el.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_el");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.el");dojo.cldr.nls.gregorian.el={"field-dayperiod":"ΠΜ/ΜΜ","field-minute":"Λεπτό","eraNames":["π.Χ.","μ.Χ."],"dateFormatItem-MMMEd":"E d MMM","field-weekday":"Ημέρα Εβδομάδας","dateFormatItem-MMdd":"dd/MM","days-standAlone-wide":["Κυριακή","Δευτέρα","Τρίτη","Τετάρτη","Πέμπτη","Παρασκευή","Σάββατο"],"patternChars":"GanjkHmsSEDFwWxhKzAeugXZvcL","months-standAlone-narrow":["Ι","Φ","Μ","Α","Μ","Ι","Ι","Α","Σ","Ο","Ν","Δ"],"field-era":"Περίοδος","field-hour":"Ώρα","quarters-standAlone-abbr":["Τ1","Τ2","Τ3","Τ4"],"timeFormat-full":"h:mm:ss a v","dateFormatItem-yyyy":"yyyy","months-standAlone-abbr":["Ιαν","Φεβ","Μαρ","Απρ","Μαϊ","Ιουν","Ιουλ","Αυγ","Σεπ","Οκτ","Νοε","Δεκ"],"dateFormatItem-Ed":"E d","dateFormatItem-yMMM":"MMM yyyy","days-standAlone-narrow":["Κ","Δ","Τ","Τ","Π","Π","Σ"],"eraAbbr":["π.Χ.","μ.Χ."],"dateFormatItem-yyyyMM":"MM/yyyy","dateFormatItem-yyyyMMMM":"MMMM yyyy","dateFormat-long":"dd MMMM yyyy","timeFormat-medium":"h:mm:ss a","field-zone":"Ζώνη","dateFormatItem-yyMM":"MM/yy","dateFormat-medium":"dd MMM yyyy","dateFormatItem-yyMMM":"MMM yy","dateFormatItem-yyQQQQ":"QQQQ yy","quarters-standAlone-wide":["1ο τρίμηνο","2ο τρίμηνο","3ο τρίμηνο","4ο τρίμηνο"],"dateTimeFormat":"{1} {0}","dateFormatItem-yMMMM":"LLLL yyyy","field-year":"Έτος","dateFormatItem-HHmmss":"HH:mm:ss","months-standAlone-wide":["Ιανουάριος","Φεβρουάριος","Μάρτιος","Απρίλιος","Μάιος","Ιούνιος","Ιούλιος","Αύγουστος","Σεπτέμβριος","Οκτώβριος","Νοέμβριος","Δεκέμβριος"],"field-week":"Εβδομάδα","dateFormatItem-MMMMEd":"E d MMMM","dateFormatItem-MMMd":"d MMM","dateFormatItem-HHmm":"HH:mm","dateFormatItem-yyQ":"Q yy","timeFormat-long":"h:mm:ss a z","months-format-abbr":["Ιαν","Φεβ","Μαρ","Απρ","Μαϊ","Ιουν","Ιουλ","Αυγ","Σεπ","Οκτ","Νοε","Δεκ"],"timeFormat-short":"h:mm a","dateFormatItem-H":"H","field-month":"Μήνας","dateFormatItem-MMMMd":"d MMMM","quarters-format-abbr":["Τ1","Τ2","Τ3","Τ4"],"days-format-abbr":["Κυρ","Δευ","Τρι","Τετ","Πεμ","Παρ","Σαβ"],"dateFormatItem-MMMMdd":"dd MMMM","pm":"μ.μ.","dateFormatItem-mmss":"mm:ss","days-format-narrow":["Κ","Δ","Τ","Τ","Π","Π","Σ"],"field-second":"Δευτερόλεπτο","field-day":"Ημέρα","dateFormatItem-MEd":"E, d-M","months-format-narrow":["Ι","Φ","Μ","Α","Μ","Ι","Ι","Α","Σ","Ο","Ν","Δ"],"am":"π.μ.","days-standAlone-abbr":["Κυρ","Δευ","Τρι","Τετ","Πεμ","Παρ","Σαβ"],"dateFormat-short":"dd/MM/yyyy","dateFormatItem-yMMMEd":"EEE, d MMM yyyy","dateFormat-full":"EEEE, dd MMMM yyyy","dateFormatItem-Md":"d/M","dateFormatItem-yMEd":"EEE, d-M-yyyy","months-format-wide":["Ιανουαρίου","Φεβρουαρίου","Μαρτίου","Απριλίου","Μαΐου","Ιουνίου","Ιουλίου","Αυγούστου","Σεπτεμβρίου","Οκτωβρίου","Νοεμβρίου","Δεκεμβρίου"],"quarters-format-wide":["1ο τρίμηνο","2ο τρίμηνο","3ο τρίμηνο","4ο τρίμηνο"],"days-format-wide":["Κυριακή","Δευτέρα","Τρίτη","Τετάρτη","Πέμπτη","Παρασκευή","Σάββατο"],"eraNarrow":["π.Χ.","μ.Χ."],"quarters-standAlone-narrow":["1","2","3","4"],"dateFormatItem-yQQQ":"yyyy QQQ","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateFormatItem-yM":"yyyy-M","dateFormatItem-yQ":"yyyy Q","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","dateFormatItem-M":"L","dateFormatItem-Hm":"H:mm","dateFormatItem-d":"d","dateFormatItem-ms":"mm:ss","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateFormatItem-y":"yyyy","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateFormatItem-MMM":"LLL","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.el");dijit.nls.loading.el={"loadingState":"Φόρτωση...","errorState":"Σας ζητούμε συγνώμη, παρουσιάστηκε σφάλμα"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.el");dijit.nls.common.el={"buttonOk":"ΟΚ","buttonCancel":"Ακύρωση","buttonSave":"Αποθήκευση","itemClose":"Κλείσιμο"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.el");dijit.form.nls.validate.el={"rangeMessage":"Η τιμή αυτή δεν ανήκει στο εύρος έγκυρων τιμών.","invalidMessage":"Η τιμή που καταχωρήσατε δεν είναι έγκυρη.","missingMessage":"Η τιμή αυτή πρέπει απαραίτητα να καθοριστεί."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.el");dojo.cldr.nls.number.el={"currencyFormat":"#,##0.00 ¤;-#,##0.00 ¤","group":".","decimal":",","scientificFormat":"#E0","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","infinity":"∞","list":";","percentSign":"%","minusSign":"-","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","nan":"NaN","nativeZeroDigit":"0","plusSign":"+","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","perMille":"‰","percentFormat":"#,##0%","decimalFormat":"#,##0.###","patternDigit":"#","currencySpacing-beforeCurrency-insertBetween":" ","exponential":"E"};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.el");dijit.form.nls.ComboBox.el={"previousMessage":"Προηγούμενες επιλογές","nextMessage":"Περισσότερες επιλογές"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_en-gb.js b/UNGProject/dojo/dojo/nls/refimpldojo_en-gb.js
new file mode 100644
index 0000000000000000000000000000000000000000..676402a29835a3ca9bc5f488ccc16c6f38cea76b
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_en-gb.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_en-gb");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.en_gb");dojo.cldr.nls.gregorian.en_gb={"dateFormatItem-yyMMM":"MMM yy","dateFormatItem-Md":"d/M","dateFormatItem-yMEd":"EEE, d/M/yyyy","dateFormatItem-yyyyMMMM":"MMMM yyyy","timeFormat-full":"HH:mm:ss v","timeFormat-medium":"HH:mm:ss","dateFormatItem-MEd":"E, d/M","dateFormat-medium":"d MMM yyyy","dateFormatItem-MMdd":"dd/MM","dateFormatItem-yyyyMM":"MM/yyyy","dateFormat-full":"EEEE, d MMMM yyyy","timeFormat-long":"HH:mm:ss z","timeFormat-short":"HH:mm","dateFormat-short":"dd/MM/yyyy","dateFormatItem-MMMMd":"d MMMM","dateFormat-long":"d MMMM yyyy","dateFormatItem-MMMEd":"E d MMM","dateFormatItem-yM":"M/yyyy","field-dayperiod":"AM/PM","dateFormatItem-yQ":"Q yyyy","field-minute":"Minute","eraNames":["Before Christ","Anno Domini"],"field-weekday":"Day of the Week","dateFormatItem-yQQQ":"QQQ yyyy","days-standAlone-wide":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"dateFormatItem-MMM":"LLL","months-standAlone-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"field-era":"Era","field-hour":"Hour","dateFormatItem-y":"yyyy","months-standAlone-abbr":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"dateFormatItem-yMMM":"MMM yyyy","days-standAlone-narrow":["S","M","T","W","T","F","S"],"eraAbbr":["BC","AD"],"field-zone":"Zone","dateFormatItem-Hm":"HH:mm","dateFormatItem-Hms":"HH:mm:ss","quarters-standAlone-wide":["1st quarter","2nd quarter","3rd quarter","4th quarter"],"dateTimeFormat":"{1} {0}","dateFormatItem-yMMMM":"MMMM yyyy","dateFormatItem-ms":"mm:ss","field-year":"Year","quarters-standAlone-narrow":["1","2","3","4"],"months-standAlone-wide":["January","February","March","April","May","June","July","August","September","October","November","December"],"field-week":"Week","dateFormatItem-MMMMEd":"E, MMMM d","dateFormatItem-MMMd":"MMM d","months-format-abbr":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"field-month":"Month","quarters-format-abbr":["Q1","Q2","Q3","Q4"],"days-format-abbr":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"pm":"PM","dateFormatItem-M":"L","days-format-narrow":["S","M","T","W","T","F","S"],"field-second":"Second","field-day":"Day","months-format-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"dateFormatItem-hm":"h:mm a","am":"AM","days-standAlone-abbr":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"dateFormatItem-yMMMEd":"EEE, MMM d, yyyy","months-format-wide":["January","February","March","April","May","June","July","August","September","October","November","December"],"dateFormatItem-d":"d","quarters-format-wide":["1st quarter","2nd quarter","3rd quarter","4th quarter"],"days-format-wide":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"eraNarrow":["B","A"],"dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","patternChars":"GyMdkHmsSEDFwWahKzYeugAZvcL","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-standAlone-abbr":["Q1","Q2","Q3","Q4"],"quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.en_gb");dijit.nls.loading.en_gb={"loadingState":"Loading...","errorState":"Sorry, an error occurred"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.en_gb");dijit.nls.common.en_gb={"buttonOk":"OK","buttonCancel":"Cancel","buttonSave":"Save","itemClose":"Close"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.en_gb");dijit.form.nls.validate.en_gb={"rangeMessage":"This value is out of range.","invalidMessage":"The value entered is not valid.","missingMessage":"This value is required."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.en_gb");dojo.cldr.nls.number.en_gb={"currencyFormat":"¤#,##0.00","group":",","percentSign":"%","exponential":"E","percentFormat":"#,##0%","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":".","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.en_gb");dijit.form.nls.ComboBox.en_gb={"previousMessage":"Previous choices","nextMessage":"More choices"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_en-us.js b/UNGProject/dojo/dojo/nls/refimpldojo_en-us.js
new file mode 100644
index 0000000000000000000000000000000000000000..d6c4b8d05d841475ccdf5bfc29edd45026f36c92
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_en-us.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_en-us");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.en_us");dojo.cldr.nls.gregorian.en_us={"dateFormatItem-yM":"M/yyyy","field-dayperiod":"AM/PM","dateFormatItem-yQ":"Q yyyy","field-minute":"Minute","eraNames":["Before Christ","Anno Domini"],"dateFormatItem-MMMEd":"E, MMM d","field-weekday":"Day of the Week","dateFormatItem-yQQQ":"QQQ yyyy","days-standAlone-wide":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"dateFormatItem-MMM":"LLL","months-standAlone-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"field-era":"Era","field-hour":"Hour","dateFormatItem-y":"yyyy","timeFormat-full":"h:mm:ss a v","months-standAlone-abbr":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"dateFormatItem-yMMM":"MMM yyyy","days-standAlone-narrow":["S","M","T","W","T","F","S"],"eraAbbr":["BC","AD"],"dateFormat-long":"MMMM d, yyyy","timeFormat-medium":"h:mm:ss a","field-zone":"Zone","dateFormatItem-Hm":"HH:mm","dateFormat-medium":"MMM d, yyyy","dateFormatItem-Hms":"HH:mm:ss","quarters-standAlone-wide":["1st quarter","2nd quarter","3rd quarter","4th quarter"],"dateTimeFormat":"{1} {0}","dateFormatItem-yMMMM":"MMMM yyyy","dateFormatItem-ms":"mm:ss","field-year":"Year","quarters-standAlone-narrow":["1","2","3","4"],"months-standAlone-wide":["January","February","March","April","May","June","July","August","September","October","November","December"],"field-week":"Week","dateFormatItem-MMMMEd":"E, MMMM d","dateFormatItem-MMMd":"MMM d","timeFormat-long":"h:mm:ss a z","months-format-abbr":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"timeFormat-short":"h:mm a","field-month":"Month","dateFormatItem-MMMMd":"MMMM d","quarters-format-abbr":["Q1","Q2","Q3","Q4"],"days-format-abbr":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"pm":"PM","dateFormatItem-M":"L","days-format-narrow":["S","M","T","W","T","F","S"],"field-second":"Second","field-day":"Day","dateFormatItem-MEd":"E, M/d","months-format-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"dateFormatItem-hm":"h:mm a","am":"AM","days-standAlone-abbr":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"dateFormat-short":"M/d/yy","dateFormatItem-yMMMEd":"EEE, MMM d, yyyy","dateFormat-full":"EEEE, MMMM d, yyyy","dateFormatItem-Md":"M/d","dateFormatItem-yMEd":"EEE, M/d/yyyy","months-format-wide":["January","February","March","April","May","June","July","August","September","October","November","December"],"dateFormatItem-d":"d","quarters-format-wide":["1st quarter","2nd quarter","3rd quarter","4th quarter"],"days-format-wide":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"eraNarrow":["B","A"],"dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","patternChars":"GyMdkHmsSEDFwWahKzYeugAZvcL","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-standAlone-abbr":["Q1","Q2","Q3","Q4"],"quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.en_us");dijit.nls.loading.en_us={"loadingState":"Loading...","errorState":"Sorry, an error occurred"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.en_us");dijit.nls.common.en_us={"buttonOk":"OK","buttonCancel":"Cancel","buttonSave":"Save","itemClose":"Close"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.en_us");dijit.form.nls.validate.en_us={"rangeMessage":"This value is out of range.","invalidMessage":"The value entered is not valid.","missingMessage":"This value is required."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.en_us");dojo.cldr.nls.number.en_us={"currencyFormat":"¤#,##0.00;(¤#,##0.00)","group":",","percentSign":"%","exponential":"E","percentFormat":"#,##0%","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":".","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.en_us");dijit.form.nls.ComboBox.en_us={"previousMessage":"Previous choices","nextMessage":"More choices"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_en.js b/UNGProject/dojo/dojo/nls/refimpldojo_en.js
new file mode 100644
index 0000000000000000000000000000000000000000..711bbf7b425825464fadab15e101e267d53ec6a0
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_en.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_en");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.en");dojo.cldr.nls.gregorian.en={"dateFormatItem-yM":"M/yyyy","field-dayperiod":"AM/PM","dateFormatItem-yQ":"Q yyyy","field-minute":"Minute","eraNames":["Before Christ","Anno Domini"],"dateFormatItem-MMMEd":"E, MMM d","field-weekday":"Day of the Week","dateFormatItem-yQQQ":"QQQ yyyy","days-standAlone-wide":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"dateFormatItem-MMM":"LLL","months-standAlone-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"field-era":"Era","field-hour":"Hour","dateFormatItem-y":"yyyy","timeFormat-full":"h:mm:ss a v","months-standAlone-abbr":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"dateFormatItem-yMMM":"MMM yyyy","days-standAlone-narrow":["S","M","T","W","T","F","S"],"eraAbbr":["BC","AD"],"dateFormat-long":"MMMM d, yyyy","timeFormat-medium":"h:mm:ss a","field-zone":"Zone","dateFormatItem-Hm":"HH:mm","dateFormat-medium":"MMM d, yyyy","dateFormatItem-Hms":"HH:mm:ss","quarters-standAlone-wide":["1st quarter","2nd quarter","3rd quarter","4th quarter"],"dateTimeFormat":"{1} {0}","dateFormatItem-yMMMM":"MMMM yyyy","dateFormatItem-ms":"mm:ss","field-year":"Year","quarters-standAlone-narrow":["1","2","3","4"],"months-standAlone-wide":["January","February","March","April","May","June","July","August","September","October","November","December"],"field-week":"Week","dateFormatItem-MMMMEd":"E, MMMM d","dateFormatItem-MMMd":"MMM d","timeFormat-long":"h:mm:ss a z","months-format-abbr":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"timeFormat-short":"h:mm a","field-month":"Month","dateFormatItem-MMMMd":"MMMM d","quarters-format-abbr":["Q1","Q2","Q3","Q4"],"days-format-abbr":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"pm":"PM","dateFormatItem-M":"L","days-format-narrow":["S","M","T","W","T","F","S"],"field-second":"Second","field-day":"Day","dateFormatItem-MEd":"E, M/d","months-format-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"dateFormatItem-hm":"h:mm a","am":"AM","days-standAlone-abbr":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"dateFormat-short":"M/d/yy","dateFormatItem-yMMMEd":"EEE, MMM d, yyyy","dateFormat-full":"EEEE, MMMM d, yyyy","dateFormatItem-Md":"M/d","dateFormatItem-yMEd":"EEE, M/d/yyyy","months-format-wide":["January","February","March","April","May","June","July","August","September","October","November","December"],"dateFormatItem-d":"d","quarters-format-wide":["1st quarter","2nd quarter","3rd quarter","4th quarter"],"days-format-wide":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"eraNarrow":["B","A"],"dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","patternChars":"GyMdkHmsSEDFwWahKzYeugAZvcL","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-standAlone-abbr":["Q1","Q2","Q3","Q4"],"quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.en");dijit.nls.loading.en={"loadingState":"Loading...","errorState":"Sorry, an error occurred"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.en");dijit.nls.common.en={"buttonOk":"OK","buttonCancel":"Cancel","buttonSave":"Save","itemClose":"Close"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.en");dijit.form.nls.validate.en={"rangeMessage":"This value is out of range.","invalidMessage":"The value entered is not valid.","missingMessage":"This value is required."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.en");dojo.cldr.nls.number.en={"group":",","percentSign":"%","exponential":"E","percentFormat":"#,##0%","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":".","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","currencyFormat":"¤#,##0.00;(¤#,##0.00)","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.en");dijit.form.nls.ComboBox.en={"previousMessage":"Previous choices","nextMessage":"More choices"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_es-es.js b/UNGProject/dojo/dojo/nls/refimpldojo_es-es.js
new file mode 100644
index 0000000000000000000000000000000000000000..f4b0f50114d5d2067e77e2b399a30bf8f87fa6d4
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_es-es.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_es-es");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.es_es");dojo.cldr.nls.gregorian.es_es={"timeFormat-medium":"H:mm:ss","timeFormat-full":"HH'H'mm''ss\" v","timeFormat-short":"H:mm","months-format-narrow":["E","F","M","A","M","J","J","A","S","O","N","D"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"día de la semana","dateFormatItem-yyQQQQ":"QQQQ 'de' yy","dateFormatItem-yQQQ":"QQQ yyyy","dateFormatItem-yMEd":"EEE d/M/yyyy","dateFormatItem-MMMEd":"E d MMM","eraNarrow":["a.C.","d.C."],"dateFormatItem-MMMdd":"dd-MMM","dateFormat-long":"d 'de' MMMM 'de' yyyy","months-format-wide":["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],"dateFormat-full":"EEEE d 'de' MMMM 'de' yyyy","dateFormatItem-Md":"d/M","field-era":"era","dateFormatItem-yM":"M/yyyy","months-standAlone-wide":["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],"quarters-format-wide":["1er trimestre","2º trimestre","3er trimestre","4º trimestre"],"dateTimeFormat":"{1} {0}","timeFormat-long":"HH:mm:ss z","field-year":"año","dateFormatItem-yMMM":"MMM yyyy","dateFormatItem-yQ":"Q yyyy","field-hour":"hora","months-format-abbr":["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],"dateFormatItem-yyQ":"Q yy","patternChars":"GuMtkHmsSEDFwWahKzUeygAZvcL","am":"a.m.","months-standAlone-abbr":["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],"quarters-format-abbr":["T1","T2","T3","T4"],"quarters-standAlone-wide":["1er trimestre","2º trimestre","3er trimestre","4º trimestre"],"dateFormatItem-HHmmss":"HH:mm:ss","dateFormatItem-hhmmss":"hh:mm:ss a","dateFormatItem-M":"L","days-standAlone-wide":["domingo","lunes","martes","miércoles","jueves","viernes","sábado"],"dateFormatItem-MMMMd":"d 'de' MMMM","dateFormatItem-yyMMM":"MMM-yy","dateFormatItem-Hm":"H:mm","quarters-standAlone-abbr":["T1","T2","T3","T4"],"eraAbbr":["a.C.","d.C."],"field-minute":"minuto","field-dayperiod":"periodo del día","days-standAlone-abbr":["dom","lun","mar","mié","jue","vie","sáb"],"dateFormatItem-d":"d","dateFormatItem-ms":"mm:ss","dateFormatItem-MMMd":"d MMM","dateFormatItem-MEd":"E, d-M","dateFormatItem-yMMMM":"MMMM 'de' yyyy","field-day":"día","days-format-wide":["domingo","lunes","martes","miércoles","jueves","viernes","sábado"],"field-zone":"zona","dateFormatItem-yyyyMM":"MM/yyyy","dateFormatItem-y":"yyyy","months-standAlone-narrow":["E","F","M","A","M","J","J","A","S","O","N","D"],"dateFormatItem-yyMM":"MM/yy","days-format-abbr":["dom","lun","mar","mié","jue","vie","sáb"],"eraNames":["antes de Cristo","anno Dómini"],"days-format-narrow":["D","L","M","M","J","V","S"],"field-month":"mes","days-standAlone-narrow":["D","L","M","M","J","V","S"],"dateFormatItem-MMM":"LLL","dateFormatItem-HHmm":"HH:mm","pm":"p.m.","dateFormatItem-MMMMEd":"E d MMMM","dateFormat-short":"dd/MM/yy","dateFormatItem-MMd":"d/MM","field-second":"segundo","dateFormatItem-yMMMEd":"EEE, d MMM yyyy","dateFormatItem-hhmm":"hh:mm a","field-week":"semana","dateFormat-medium":"dd/MM/yyyy","dateFormatItem-mmss":"mm:ss","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.es_es");dijit.nls.loading.es_es={"loadingState":"Cargando...","errorState":"Lo siento, se ha producido un error"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.es_es");dijit.nls.common.es_es={"buttonOk":"Aceptar","buttonCancel":"Cancelar","buttonSave":"Guardar","itemClose":"Cerrar"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.es_es");dijit.form.nls.validate.es_es={"rangeMessage":"Este valor está fuera del intervalo.","invalidMessage":"El valor especificado no es válido.","missingMessage":"Este valor es necesario."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.es_es");dojo.cldr.nls.number.es_es={"currencyFormat":"#,##0.00 ¤","decimalFormat":"#,##0.###","group":".","scientificFormat":"#E0","percentFormat":"#,##0%","decimal":",","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","infinity":"∞","list":";","percentSign":"%","minusSign":"-","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","nan":"NaN","nativeZeroDigit":"0","plusSign":"+","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","perMille":"‰","patternDigit":"#","currencySpacing-beforeCurrency-insertBetween":" ","exponential":"E"};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.es_es");dijit.form.nls.ComboBox.es_es={"previousMessage":"Opciones anteriores","nextMessage":"Más opciones"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_es.js b/UNGProject/dojo/dojo/nls/refimpldojo_es.js
new file mode 100644
index 0000000000000000000000000000000000000000..9c59ec53b69c51d8a839ee7142247b9ead15b665
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_es.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_es");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.es");dojo.cldr.nls.gregorian.es={"months-format-narrow":["E","F","M","A","M","J","J","A","S","O","N","D"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"día de la semana","dateFormatItem-yyQQQQ":"QQQQ 'de' yy","dateFormatItem-yQQQ":"QQQ yyyy","dateFormatItem-yMEd":"EEE d/M/yyyy","dateFormatItem-MMMEd":"E d MMM","eraNarrow":["a.C.","d.C."],"dateFormatItem-MMMdd":"dd-MMM","dateFormat-long":"d 'de' MMMM 'de' yyyy","months-format-wide":["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],"dateFormat-full":"EEEE d 'de' MMMM 'de' yyyy","dateFormatItem-Md":"d/M","field-era":"era","dateFormatItem-yM":"M/yyyy","months-standAlone-wide":["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],"timeFormat-short":"HH:mm","quarters-format-wide":["1er trimestre","2º trimestre","3er trimestre","4º trimestre"],"dateTimeFormat":"{1} {0}","timeFormat-long":"HH:mm:ss z","field-year":"año","dateFormatItem-yMMM":"MMM yyyy","dateFormatItem-yQ":"Q yyyy","field-hour":"hora","months-format-abbr":["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],"dateFormatItem-yyQ":"Q yy","patternChars":"GuMtkHmsSEDFwWahKzUeygAZvcL","timeFormat-full":"hh:mm:ss a v","am":"a.m.","months-standAlone-abbr":["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],"quarters-format-abbr":["T1","T2","T3","T4"],"quarters-standAlone-wide":["1er trimestre","2º trimestre","3er trimestre","4º trimestre"],"dateFormatItem-HHmmss":"HH:mm:ss","dateFormatItem-hhmmss":"hh:mm:ss a","dateFormatItem-M":"L","days-standAlone-wide":["domingo","lunes","martes","miércoles","jueves","viernes","sábado"],"dateFormatItem-MMMMd":"d 'de' MMMM","dateFormatItem-yyMMM":"MMM-yy","timeFormat-medium":"HH:mm:ss","dateFormatItem-Hm":"H:mm","quarters-standAlone-abbr":["T1","T2","T3","T4"],"eraAbbr":["a.C.","d.C."],"field-minute":"minuto","field-dayperiod":"periodo del día","days-standAlone-abbr":["dom","lun","mar","mié","jue","vie","sáb"],"dateFormatItem-d":"d","dateFormatItem-ms":"mm:ss","dateFormatItem-MMMd":"d MMM","dateFormatItem-MEd":"E, d-M","dateFormatItem-yMMMM":"MMMM 'de' yyyy","field-day":"día","days-format-wide":["domingo","lunes","martes","miércoles","jueves","viernes","sábado"],"field-zone":"zona","dateFormatItem-yyyyMM":"MM/yyyy","dateFormatItem-y":"yyyy","months-standAlone-narrow":["E","F","M","A","M","J","J","A","S","O","N","D"],"dateFormatItem-yyMM":"MM/yy","days-format-abbr":["dom","lun","mar","mié","jue","vie","sáb"],"eraNames":["antes de Cristo","anno Dómini"],"days-format-narrow":["D","L","M","M","J","V","S"],"field-month":"mes","days-standAlone-narrow":["D","L","M","M","J","V","S"],"dateFormatItem-MMM":"LLL","dateFormatItem-HHmm":"HH:mm","pm":"p.m.","dateFormatItem-MMMMEd":"E d MMMM","dateFormat-short":"dd/MM/yy","dateFormatItem-MMd":"d/MM","field-second":"segundo","dateFormatItem-yMMMEd":"EEE, d MMM yyyy","dateFormatItem-hhmm":"hh:mm a","field-week":"semana","dateFormat-medium":"dd/MM/yyyy","dateFormatItem-mmss":"mm:ss","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.es");dijit.nls.loading.es={"loadingState":"Cargando...","errorState":"Lo siento, se ha producido un error"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.es");dijit.nls.common.es={"buttonOk":"Aceptar","buttonCancel":"Cancelar","buttonSave":"Guardar","itemClose":"Cerrar"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.es");dijit.form.nls.validate.es={"rangeMessage":"Este valor está fuera del intervalo.","invalidMessage":"El valor especificado no es válido.","missingMessage":"Este valor es necesario."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.es");dojo.cldr.nls.number.es={"decimalFormat":"#,##0.###","group":".","scientificFormat":"#E0","percentFormat":"#,##0%","currencyFormat":"¤ #,##0.00","decimal":",","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","infinity":"∞","list":";","percentSign":"%","minusSign":"-","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","nan":"NaN","nativeZeroDigit":"0","plusSign":"+","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","perMille":"‰","patternDigit":"#","currencySpacing-beforeCurrency-insertBetween":" ","exponential":"E"};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.es");dijit.form.nls.ComboBox.es={"previousMessage":"Opciones anteriores","nextMessage":"Más opciones"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_fi-fi.js b/UNGProject/dojo/dojo/nls/refimpldojo_fi-fi.js
new file mode 100644
index 0000000000000000000000000000000000000000..4193f2a2684dff8a07e221b4ca77e28fc5670cc8
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_fi-fi.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_fi-fi");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.fi_fi");dojo.cldr.nls.gregorian.fi_fi={"months-format-narrow":["T","H","M","H","T","K","H","E","S","L","M","J"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"viikonpäivä","dateFormatItem-yQQQ":"QQQ yyyy","dateFormatItem-yMEd":"EEE d.M.yyyy","dateFormatItem-MMMEd":"E d. MMM","eraNarrow":["eKr.","jKr."],"dateFormat-long":"d. MMMM yyyy","months-format-wide":["tammikuuta","helmikuuta","maaliskuuta","huhtikuuta","toukokuuta","kesäkuuta","heinäkuuta","elokuuta","syyskuuta","lokakuuta","marraskuuta","joulukuuta"],"dateFormat-full":"EEEE d. MMMM yyyy","dateFormatItem-Md":"d.M.","field-era":"aikakausi","dateFormatItem-yM":"L.yyyy","months-standAlone-wide":["tammikuuta","helmikuuta","maaliskuuta","huhtikuuta","toukokuuta","kesäkuuta","heinäkuuta","elokuuta","syyskuuta","lokakuuta","marraskuuta","joulukuuta"],"timeFormat-short":"H.mm","quarters-format-wide":["1. neljännes","2. neljännes","3. neljännes","4. neljännes"],"dateTimeFormat":"{1} {0}","timeFormat-long":"H.mm.ss z","field-year":"vuosi","dateFormatItem-yMMM":"LLL yyyy","dateFormatItem-yQ":"Q/yyyy","dateFormatItem-yyyyMMMM":"LLLL yyyy","field-hour":"tunti","months-format-abbr":["tammi","helmi","maalis","huhti","touko","kesä","heinä","elo","syys","loka","marras","joulu"],"dateFormatItem-yyQ":"Q/yy","patternChars":"GanjkHmsSEDFwWxhKzAeugXZvcL","timeFormat-full":"H.mm.ss v","dateFormatItem-yyyyMEEEd":"EEE d.M.yyyy","am":"ap.","months-standAlone-abbr":["tammi","helmi","maalis","huhti","touko","kesä","heinä","elo","syys","loka","marras","joulu"],"quarters-format-abbr":["1. nelj.","2. nelj.","3. nelj.","4. nelj."],"quarters-standAlone-wide":["1. neljännes","2. neljännes","3. neljännes","4. neljännes"],"dateFormatItem-HHmmss":"HH.mm.ss","dateFormatItem-M":"L","days-standAlone-wide":["sunnuntaina","maanantaina","tiistaina","keskiviikkona","torstaina","perjantaina","lauantaina"],"dateFormatItem-MMMMd":"d. MMMM","dateFormatItem-yyMMM":"MMM yy","timeFormat-medium":"H.mm.ss","dateFormatItem-Hm":"H.mm","quarters-standAlone-abbr":["1. nelj.","2. nelj.","3. nelj.","4. nelj."],"eraAbbr":["eKr.","jKr."],"field-minute":"minuutti","field-dayperiod":"ap/ip","days-standAlone-abbr":["su","ma","ti","ke","to","pe","la"],"dateFormatItem-d":"d","dateFormatItem-ms":"mm.ss","dateFormatItem-MMMd":"d. MMM","dateFormatItem-MEd":"E d.M.","dateFormatItem-yMMMM":"LLLL yyyy","field-day":"päivä","days-format-wide":["sunnuntaina","maanantaina","tiistaina","keskiviikkona","torstaina","perjantaina","lauantaina"],"field-zone":"aikavyöhyke","dateFormatItem-y":"yyyy","months-standAlone-narrow":["T","H","M","H","T","K","H","E","S","L","M","J"],"dateFormatItem-yyMM":"M/yy","days-format-abbr":["su","ma","ti","ke","to","pe","la"],"eraNames":["ennen Kristuksen syntymää","jälkeen Kristuksen syntymän"],"days-format-narrow":["S","M","T","K","T","P","L"],"field-month":"kuukausi","days-standAlone-narrow":["S","M","T","K","T","P","L"],"dateFormatItem-MMM":"LLL","dateFormatItem-HHmm":"HH.mm","pm":"ip.","dateFormatItem-MMMMEd":"E d. MMMM","dateFormat-short":"d.M.yyyy","field-second":"sekunti","dateFormatItem-yMMMEd":"EEE d. MMM yyyy","field-week":"viikko","dateFormat-medium":"d.M.yyyy","dateFormatItem-yyyyM":"M/yyyy","dateFormatItem-mmss":"mm.ss","dateFormatItem-yyyyQQQQ":"QQQQ yyyy","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.fi_fi");dijit.nls.loading.fi_fi={"loadingState":"Lataus on meneillään...","errorState":"On ilmennyt virhe."};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.fi_fi");dijit.nls.common.fi_fi={"buttonOk":"OK","buttonCancel":"Peruuta","buttonSave":"Tallenna","itemClose":"Sulje"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.fi_fi");dijit.form.nls.validate.fi_fi={"rangeMessage":"Tämä arvo on sallitun alueen ulkopuolella.","invalidMessage":"Annettu arvo ei kelpaa.","missingMessage":"Tämä arvo on pakollinen."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.fi_fi");dojo.cldr.nls.number.fi_fi={"group":" ","percentSign":"%","exponential":"E","percentFormat":"#,##0 %","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":",","nan":"epäluku","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","currencyFormat":"#,##0.00 ¤","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.fi_fi");dijit.form.nls.ComboBox.fi_fi={"previousMessage":"Edelliset valinnat","nextMessage":"Lisää valintoja"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_fi.js b/UNGProject/dojo/dojo/nls/refimpldojo_fi.js
new file mode 100644
index 0000000000000000000000000000000000000000..266441901659180d691a33b975abeedc907c493f
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_fi.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_fi");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.fi");dojo.cldr.nls.gregorian.fi={"months-format-narrow":["T","H","M","H","T","K","H","E","S","L","M","J"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"viikonpäivä","dateFormatItem-yQQQ":"QQQ yyyy","dateFormatItem-yMEd":"EEE d.M.yyyy","dateFormatItem-MMMEd":"E d. MMM","eraNarrow":["eKr.","jKr."],"dateFormat-long":"d. MMMM yyyy","months-format-wide":["tammikuuta","helmikuuta","maaliskuuta","huhtikuuta","toukokuuta","kesäkuuta","heinäkuuta","elokuuta","syyskuuta","lokakuuta","marraskuuta","joulukuuta"],"dateFormat-full":"EEEE d. MMMM yyyy","dateFormatItem-Md":"d.M.","field-era":"aikakausi","dateFormatItem-yM":"L.yyyy","months-standAlone-wide":["tammikuuta","helmikuuta","maaliskuuta","huhtikuuta","toukokuuta","kesäkuuta","heinäkuuta","elokuuta","syyskuuta","lokakuuta","marraskuuta","joulukuuta"],"timeFormat-short":"H.mm","quarters-format-wide":["1. neljännes","2. neljännes","3. neljännes","4. neljännes"],"dateTimeFormat":"{1} {0}","timeFormat-long":"H.mm.ss z","field-year":"vuosi","dateFormatItem-yMMM":"LLL yyyy","dateFormatItem-yQ":"Q/yyyy","dateFormatItem-yyyyMMMM":"LLLL yyyy","field-hour":"tunti","months-format-abbr":["tammi","helmi","maalis","huhti","touko","kesä","heinä","elo","syys","loka","marras","joulu"],"dateFormatItem-yyQ":"Q/yy","patternChars":"GanjkHmsSEDFwWxhKzAeugXZvcL","timeFormat-full":"H.mm.ss v","dateFormatItem-yyyyMEEEd":"EEE d.M.yyyy","am":"ap.","months-standAlone-abbr":["tammi","helmi","maalis","huhti","touko","kesä","heinä","elo","syys","loka","marras","joulu"],"quarters-format-abbr":["1. nelj.","2. nelj.","3. nelj.","4. nelj."],"quarters-standAlone-wide":["1. neljännes","2. neljännes","3. neljännes","4. neljännes"],"dateFormatItem-HHmmss":"HH.mm.ss","dateFormatItem-M":"L","days-standAlone-wide":["sunnuntaina","maanantaina","tiistaina","keskiviikkona","torstaina","perjantaina","lauantaina"],"dateFormatItem-MMMMd":"d. MMMM","dateFormatItem-yyMMM":"MMM yy","timeFormat-medium":"H.mm.ss","dateFormatItem-Hm":"H.mm","quarters-standAlone-abbr":["1. nelj.","2. nelj.","3. nelj.","4. nelj."],"eraAbbr":["eKr.","jKr."],"field-minute":"minuutti","field-dayperiod":"ap/ip","days-standAlone-abbr":["su","ma","ti","ke","to","pe","la"],"dateFormatItem-d":"d","dateFormatItem-ms":"mm.ss","dateFormatItem-MMMd":"d. MMM","dateFormatItem-MEd":"E d.M.","dateFormatItem-yMMMM":"LLLL yyyy","field-day":"päivä","days-format-wide":["sunnuntaina","maanantaina","tiistaina","keskiviikkona","torstaina","perjantaina","lauantaina"],"field-zone":"aikavyöhyke","dateFormatItem-y":"yyyy","months-standAlone-narrow":["T","H","M","H","T","K","H","E","S","L","M","J"],"dateFormatItem-yyMM":"M/yy","days-format-abbr":["su","ma","ti","ke","to","pe","la"],"eraNames":["ennen Kristuksen syntymää","jälkeen Kristuksen syntymän"],"days-format-narrow":["S","M","T","K","T","P","L"],"field-month":"kuukausi","days-standAlone-narrow":["S","M","T","K","T","P","L"],"dateFormatItem-MMM":"LLL","dateFormatItem-HHmm":"HH.mm","pm":"ip.","dateFormatItem-MMMMEd":"E d. MMMM","dateFormat-short":"d.M.yyyy","field-second":"sekunti","dateFormatItem-yMMMEd":"EEE d. MMM yyyy","field-week":"viikko","dateFormat-medium":"d.M.yyyy","dateFormatItem-yyyyM":"M/yyyy","dateFormatItem-mmss":"mm.ss","dateFormatItem-yyyyQQQQ":"QQQQ yyyy","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.fi");dijit.nls.loading.fi={"loadingState":"Lataus on meneillään...","errorState":"On ilmennyt virhe."};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.fi");dijit.nls.common.fi={"buttonOk":"OK","buttonCancel":"Peruuta","buttonSave":"Tallenna","itemClose":"Sulje"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.fi");dijit.form.nls.validate.fi={"rangeMessage":"Tämä arvo on sallitun alueen ulkopuolella.","invalidMessage":"Annettu arvo ei kelpaa.","missingMessage":"Tämä arvo on pakollinen."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.fi");dojo.cldr.nls.number.fi={"group":" ","percentSign":"%","exponential":"E","percentFormat":"#,##0 %","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":",","nan":"epäluku","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","currencyFormat":"#,##0.00 ¤","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.fi");dijit.form.nls.ComboBox.fi={"previousMessage":"Edelliset valinnat","nextMessage":"Lisää valintoja"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_fr-fr.js b/UNGProject/dojo/dojo/nls/refimpldojo_fr-fr.js
new file mode 100644
index 0000000000000000000000000000000000000000..f67e4fceb4c1678a2dffad52089df15c19dcaf77
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_fr-fr.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_fr-fr");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.fr_fr");dojo.cldr.nls.gregorian.fr_fr={"months-format-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"jour de la semaine","dateFormatItem-yyQQQQ":"QQQQ yy","dateFormatItem-yQQQ":"QQQ yyyy","dateFormatItem-yMEd":"EEE d/M/yyyy","dateFormatItem-MMMEd":"E d MMM","eraNarrow":["av. J.-C.","ap. J.-C."],"dateFormatItem-MMMdd":"dd MMM","dateFormat-long":"d MMMM yyyy","months-format-wide":["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],"dateFormat-full":"EEEE d MMMM yyyy","dateFormatItem-Md":"d/M","field-era":"ère","dateFormatItem-yM":"M/yyyy","months-standAlone-wide":["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],"timeFormat-short":"HH:mm","quarters-format-wide":["1er trimestre","2e trimestre","3e trimestre","4e trimestre"],"dateTimeFormat":"{1} {0}","timeFormat-long":"HH:mm:ss z","field-year":"année","dateFormatItem-yMMM":"MMM yyyy","dateFormatItem-yQ":"'T'Q yyyy","dateFormatItem-yyyyMMMM":"MMMM yyyy","field-hour":"heure","dateFormatItem-MMdd":"dd/MM","months-format-abbr":["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"dateFormatItem-yyQ":"'T'Q yy","patternChars":"GaMjkHmsSEDFwWxhKzAeugXZvcL","timeFormat-full":"HH:mm:ss v","am":"AM","months-standAlone-abbr":["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"quarters-format-abbr":["T1","T2","T3","T4"],"quarters-standAlone-wide":["1er trimestre","2e trimestre","3e trimestre","4e trimestre"],"dateFormatItem-HHmmss":"HH:mm:ss","dateFormatItem-hhmmss":"HH:mm:ss","dateFormatItem-M":"L","days-standAlone-wide":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"dateFormatItem-MMMMd":"d MMMM","dateFormatItem-yyMMMEEEd":"EEE d MMM yy","dateFormatItem-yyMMM":"MMM yy","timeFormat-medium":"HH:mm:ss","dateFormatItem-Hm":"H:mm","quarters-standAlone-abbr":["T1","T2","T3","T4"],"eraAbbr":["av. J.-C.","ap. J.-C."],"field-minute":"minute","field-dayperiod":"cadran","days-standAlone-abbr":["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],"dateFormatItem-yyMMMd":"d MMM yy","dateFormatItem-d":"d","dateFormatItem-ms":"mm:ss","dateFormatItem-MMMd":"d MMM","dateFormatItem-MEd":"EEE d/M","dateFormatItem-yMMMM":"MMMM yyyy","field-day":"jour","days-format-wide":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"field-zone":"fuseau horaire","dateFormatItem-y":"yyyy","months-standAlone-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"dateFormatItem-yyMM":"MM/yy","days-format-abbr":["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],"eraNames":["avant Jésus-Christ","après Jésus-Christ"],"days-format-narrow":["D","L","M","M","J","V","S"],"field-month":"mois","days-standAlone-narrow":["D","L","M","M","J","V","S"],"dateFormatItem-MMM":"LLL","dateFormatItem-HHmm":"HH:mm","pm":"PM","dateFormatItem-MMMMEd":"EEE d MMMM","dateFormat-short":"dd/MM/yy","dateFormatItem-MMd":"d/MM","field-second":"seconde","dateFormatItem-yMMMEd":"EEE d MMM yyyy","dateFormatItem-hhmm":"HH:mm","field-week":"semaine","dateFormat-medium":"d MMM yyyy","dateFormatItem-mmss":"mm:ss","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.fr_fr");dijit.nls.loading.fr_fr={"loadingState":"Chargement...","errorState":"Une erreur est survenue"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.fr_fr");dijit.nls.common.fr_fr={"buttonOk":"OK","buttonCancel":"Annuler","buttonSave":"Sauvegarder","itemClose":"Fermer"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.fr_fr");dijit.form.nls.validate.fr_fr={"rangeMessage":"Cette valeur n'est pas comprise dans la plage autorisée.","invalidMessage":"La valeur indiquée n'est pas correcte.","missingMessage":"Cette valeur est requise."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.fr_fr");dojo.cldr.nls.number.fr_fr={"group":" ","percentSign":"%","exponential":"E","percentFormat":"#,##0 %","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":",","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","currencyFormat":"#,##0.00 ¤","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.fr_fr");dijit.form.nls.ComboBox.fr_fr={"previousMessage":"Choix précédents","nextMessage":"Plus de choix"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_fr.js b/UNGProject/dojo/dojo/nls/refimpldojo_fr.js
new file mode 100644
index 0000000000000000000000000000000000000000..74cf5b8e64e08adbcd50f6160aaf21dd4ee24443
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_fr.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_fr");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.fr");dojo.cldr.nls.gregorian.fr={"months-format-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"jour de la semaine","dateFormatItem-yyQQQQ":"QQQQ yy","dateFormatItem-yQQQ":"QQQ yyyy","dateFormatItem-yMEd":"EEE d/M/yyyy","dateFormatItem-MMMEd":"E d MMM","eraNarrow":["av. J.-C.","ap. J.-C."],"dateFormatItem-MMMdd":"dd MMM","dateFormat-long":"d MMMM yyyy","months-format-wide":["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],"dateFormat-full":"EEEE d MMMM yyyy","dateFormatItem-Md":"d/M","field-era":"ère","dateFormatItem-yM":"M/yyyy","months-standAlone-wide":["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],"timeFormat-short":"HH:mm","quarters-format-wide":["1er trimestre","2e trimestre","3e trimestre","4e trimestre"],"dateTimeFormat":"{1} {0}","timeFormat-long":"HH:mm:ss z","field-year":"année","dateFormatItem-yMMM":"MMM yyyy","dateFormatItem-yQ":"'T'Q yyyy","dateFormatItem-yyyyMMMM":"MMMM yyyy","field-hour":"heure","dateFormatItem-MMdd":"dd/MM","months-format-abbr":["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"dateFormatItem-yyQ":"'T'Q yy","patternChars":"GaMjkHmsSEDFwWxhKzAeugXZvcL","timeFormat-full":"HH:mm:ss v","am":"AM","months-standAlone-abbr":["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],"quarters-format-abbr":["T1","T2","T3","T4"],"quarters-standAlone-wide":["1er trimestre","2e trimestre","3e trimestre","4e trimestre"],"dateFormatItem-HHmmss":"HH:mm:ss","dateFormatItem-hhmmss":"HH:mm:ss","dateFormatItem-M":"L","days-standAlone-wide":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"dateFormatItem-MMMMd":"d MMMM","dateFormatItem-yyMMMEEEd":"EEE d MMM yy","dateFormatItem-yyMMM":"MMM yy","timeFormat-medium":"HH:mm:ss","dateFormatItem-Hm":"H:mm","quarters-standAlone-abbr":["T1","T2","T3","T4"],"eraAbbr":["av. J.-C.","ap. J.-C."],"field-minute":"minute","field-dayperiod":"cadran","days-standAlone-abbr":["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],"dateFormatItem-yyMMMd":"d MMM yy","dateFormatItem-d":"d","dateFormatItem-ms":"mm:ss","dateFormatItem-MMMd":"d MMM","dateFormatItem-MEd":"EEE d/M","dateFormatItem-yMMMM":"MMMM yyyy","field-day":"jour","days-format-wide":["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],"field-zone":"fuseau horaire","dateFormatItem-y":"yyyy","months-standAlone-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"dateFormatItem-yyMM":"MM/yy","days-format-abbr":["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],"eraNames":["avant Jésus-Christ","après Jésus-Christ"],"days-format-narrow":["D","L","M","M","J","V","S"],"field-month":"mois","days-standAlone-narrow":["D","L","M","M","J","V","S"],"dateFormatItem-MMM":"LLL","dateFormatItem-HHmm":"HH:mm","pm":"PM","dateFormatItem-MMMMEd":"EEE d MMMM","dateFormat-short":"dd/MM/yy","dateFormatItem-MMd":"d/MM","field-second":"seconde","dateFormatItem-yMMMEd":"EEE d MMM yyyy","dateFormatItem-hhmm":"HH:mm","field-week":"semaine","dateFormat-medium":"d MMM yyyy","dateFormatItem-mmss":"mm:ss","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.fr");dijit.nls.loading.fr={"loadingState":"Chargement...","errorState":"Une erreur est survenue"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.fr");dijit.nls.common.fr={"buttonOk":"OK","buttonCancel":"Annuler","buttonSave":"Sauvegarder","itemClose":"Fermer"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.fr");dijit.form.nls.validate.fr={"rangeMessage":"Cette valeur n'est pas comprise dans la plage autorisée.","invalidMessage":"La valeur indiquée n'est pas correcte.","missingMessage":"Cette valeur est requise."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.fr");dojo.cldr.nls.number.fr={"group":" ","percentSign":"%","exponential":"E","percentFormat":"#,##0 %","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":",","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","currencyFormat":"#,##0.00 ¤","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.fr");dijit.form.nls.ComboBox.fr={"previousMessage":"Choix précédents","nextMessage":"Plus de choix"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_he-il.js b/UNGProject/dojo/dojo/nls/refimpldojo_he-il.js
new file mode 100644
index 0000000000000000000000000000000000000000..b42d6abe5b214376ee5d9caefb0afbc99ca4bcc8
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_he-il.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_he-il");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.he_il");dojo.cldr.nls.gregorian.he_il={"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"יום בשבוע","dateFormatItem-yQQQ":"yyyy QQQ","dateFormatItem-yMEd":"EEE, yyyy-M-d","dateFormatItem-MMMEd":"E d MMM","eraNarrow":["לפנה״ס","לסה״נ"],"dateFormat-long":"d MMMM yyyy","months-format-wide":["ינואר","פברואר","מרץ","אפריל","מאי","יוני","יולי","אוגוסט","ספטמבר","אוקטובר","נובמבר","דצמבר"],"dateFormat-full":"EEEE d MMMM yyyy","dateFormatItem-Md":"d/M","field-era":"תקופה","dateFormatItem-yM":"yyyy-M","months-standAlone-wide":["ינואר","פברואר","מרס","אפריל","מאי","יוני","יולי","אוגוסט","ספטמבר","אוקטובר","נובמבר","דצמבר"],"timeFormat-short":"HH:mm","quarters-format-wide":["רבעון 1","רבעון 2","רבעון 3","רבעון 4"],"dateTimeFormat":"{1} {0}","timeFormat-long":"HH:mm:ss z","field-year":"שנה","dateFormatItem-yMMM":"yyyy MMM","dateFormatItem-yQ":"yyyy Q","dateFormatItem-yyyyMMMM":"MMMM yyyy","field-hour":"שעה","dateFormatItem-MMdd":"dd/MM","months-format-abbr":["ינו","פבר","מרץ","אפר","מאי","יונ","יול","אוג","ספט","אוק","נוב","דצמ"],"dateFormatItem-yyQ":"Q yy","patternChars":"GanjkHmsSEDFwWxhKzAeugXZvcL","timeFormat-full":"HH:mm:ss v","am":"לפנה\"צ","dateFormatItem-H":"H","months-standAlone-abbr":["ינו","פבר","מרס","אפר","מאי","יונ","יול","אוג","ספט","אוק","נוב","דצמ"],"quarters-format-abbr":["רבעון 1","רבעון 2","רבעון 3","רבעון 4"],"quarters-standAlone-wide":["רבעון 1","רבעון 2","רבעון 3","רבעון 4"],"dateFormatItem-HHmmss":"HH:mm:ss","dateFormatItem-M":"L","days-standAlone-wide":["יום ראשון","יום שני","יום שלישי","יום רביעי","יום חמישי","יום שישי","שבת"],"dateFormatItem-MMMMd":"d MMMM","dateFormatItem-yyMMM":"MMM yy","timeFormat-medium":"HH:mm:ss","dateFormatItem-Hm":"H:mm","quarters-standAlone-abbr":["רבעון 1","רבעון 2","רבעון 3","רבעון 4"],"eraAbbr":["לפנה״ס","לסה״נ"],"field-minute":"דקה","field-dayperiod":"Dayperiod","days-standAlone-abbr":["א","ב","ג","ד","ה","ו","ש"],"dateFormatItem-d":"d","dateFormatItem-ms":"mm:ss","dateFormatItem-MMMd":"MMM d","dateFormatItem-MEd":"E, M-d","dateFormatItem-yMMMM":"yyyy MMMM","field-day":"יום","days-format-wide":["יום ראשון","יום שני","יום שלישי","יום רביעי","יום חמישי","יום שישי","שבת"],"field-zone":"אזור","dateFormatItem-yyyyMM":"MM/yyyy","dateFormatItem-y":"yyyy","months-standAlone-narrow":["1","2","3","4","5","6","7","8","9","10","11","12"],"dateFormatItem-yyMM":"MM/yy","days-format-abbr":["א","ב","ג","ד","ה","ו","ש"],"eraNames":["לפני הספירה","לספירה"],"days-format-narrow":["א","ב","ג","ד","ה","ו","ש"],"field-month":"חודש","days-standAlone-narrow":["א","ב","ג","ד","ה","ו","ש"],"dateFormatItem-MMM":"LLL","dateFormatItem-HHmm":"HH:mm","pm":"אחה\"צ","dateFormatItem-MMMMEd":"E MMMM d","dateFormat-short":"dd/MM/yy","field-second":"שנייה","dateFormatItem-yMMMEd":"EEE, yyyy MMM d","dateFormatItem-Ed":"E d","field-week":"שבוע","dateFormat-medium":"dd/MM/yyyy","dateFormatItem-mmss":"mm:ss","dateFormatItem-yyyy":"yyyy","months-format-narrow":["1","2","3","4","5","6","7","8","9","10","11","12"],"dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.he_il");dijit.nls.loading.he_il={"loadingState":"טעינה...‏","errorState":"אירעה שגיאה"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.he_il");dijit.nls.common.he_il={"buttonOk":"אישור","buttonCancel":"ביטול","buttonSave":"שמירה","itemClose":"סגירה"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.he_il");dijit.form.nls.validate.he_il={"rangeMessage":"הערך מחוץ לטווח.","invalidMessage":"הערך שצוין אינו חוקי.","missingMessage":"זהו ערך דרוש."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.he_il");dojo.cldr.nls.number.he_il={"group":",","percentSign":"%","exponential":"E","percentFormat":"#,##0%","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":".","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","currencyFormat":"#,##0.00 ¤","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.he_il");dijit.form.nls.ComboBox.he_il={"previousMessage":"האפשרויות הקודמות","nextMessage":"אפשרויות נוספות"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_he.js b/UNGProject/dojo/dojo/nls/refimpldojo_he.js
new file mode 100644
index 0000000000000000000000000000000000000000..045d0982d66b97760066a3727261fae4f60eca04
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_he.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_he");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.he");dojo.cldr.nls.gregorian.he={"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"יום בשבוע","dateFormatItem-yQQQ":"yyyy QQQ","dateFormatItem-yMEd":"EEE, yyyy-M-d","dateFormatItem-MMMEd":"E d MMM","eraNarrow":["לפנה״ס","לסה״נ"],"dateFormat-long":"d MMMM yyyy","months-format-wide":["ינואר","פברואר","מרץ","אפריל","מאי","יוני","יולי","אוגוסט","ספטמבר","אוקטובר","נובמבר","דצמבר"],"dateFormat-full":"EEEE d MMMM yyyy","dateFormatItem-Md":"d/M","field-era":"תקופה","dateFormatItem-yM":"yyyy-M","months-standAlone-wide":["ינואר","פברואר","מרס","אפריל","מאי","יוני","יולי","אוגוסט","ספטמבר","אוקטובר","נובמבר","דצמבר"],"timeFormat-short":"HH:mm","quarters-format-wide":["רבעון 1","רבעון 2","רבעון 3","רבעון 4"],"dateTimeFormat":"{1} {0}","timeFormat-long":"HH:mm:ss z","field-year":"שנה","dateFormatItem-yMMM":"yyyy MMM","dateFormatItem-yQ":"yyyy Q","dateFormatItem-yyyyMMMM":"MMMM yyyy","field-hour":"שעה","dateFormatItem-MMdd":"dd/MM","months-format-abbr":["ינו","פבר","מרץ","אפר","מאי","יונ","יול","אוג","ספט","אוק","נוב","דצמ"],"dateFormatItem-yyQ":"Q yy","patternChars":"GanjkHmsSEDFwWxhKzAeugXZvcL","timeFormat-full":"HH:mm:ss v","am":"לפנה\"צ","dateFormatItem-H":"H","months-standAlone-abbr":["ינו","פבר","מרס","אפר","מאי","יונ","יול","אוג","ספט","אוק","נוב","דצמ"],"quarters-format-abbr":["רבעון 1","רבעון 2","רבעון 3","רבעון 4"],"quarters-standAlone-wide":["רבעון 1","רבעון 2","רבעון 3","רבעון 4"],"dateFormatItem-HHmmss":"HH:mm:ss","dateFormatItem-M":"L","days-standAlone-wide":["יום ראשון","יום שני","יום שלישי","יום רביעי","יום חמישי","יום שישי","שבת"],"dateFormatItem-MMMMd":"d MMMM","dateFormatItem-yyMMM":"MMM yy","timeFormat-medium":"HH:mm:ss","dateFormatItem-Hm":"H:mm","quarters-standAlone-abbr":["רבעון 1","רבעון 2","רבעון 3","רבעון 4"],"eraAbbr":["לפנה״ס","לסה״נ"],"field-minute":"דקה","field-dayperiod":"Dayperiod","days-standAlone-abbr":["א","ב","ג","ד","ה","ו","ש"],"dateFormatItem-d":"d","dateFormatItem-ms":"mm:ss","dateFormatItem-MMMd":"MMM d","dateFormatItem-MEd":"E, M-d","dateFormatItem-yMMMM":"yyyy MMMM","field-day":"יום","days-format-wide":["יום ראשון","יום שני","יום שלישי","יום רביעי","יום חמישי","יום שישי","שבת"],"field-zone":"אזור","dateFormatItem-yyyyMM":"MM/yyyy","dateFormatItem-y":"yyyy","months-standAlone-narrow":["1","2","3","4","5","6","7","8","9","10","11","12"],"dateFormatItem-yyMM":"MM/yy","days-format-abbr":["א","ב","ג","ד","ה","ו","ש"],"eraNames":["לפני הספירה","לספירה"],"days-format-narrow":["א","ב","ג","ד","ה","ו","ש"],"field-month":"חודש","days-standAlone-narrow":["א","ב","ג","ד","ה","ו","ש"],"dateFormatItem-MMM":"LLL","dateFormatItem-HHmm":"HH:mm","pm":"אחה\"צ","dateFormatItem-MMMMEd":"E MMMM d","dateFormat-short":"dd/MM/yy","field-second":"שנייה","dateFormatItem-yMMMEd":"EEE, yyyy MMM d","dateFormatItem-Ed":"E d","field-week":"שבוע","dateFormat-medium":"dd/MM/yyyy","dateFormatItem-mmss":"mm:ss","dateFormatItem-yyyy":"yyyy","months-format-narrow":["1","2","3","4","5","6","7","8","9","10","11","12"],"dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.he");dijit.nls.loading.he={"loadingState":"טעינה...‏","errorState":"אירעה שגיאה"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.he");dijit.nls.common.he={"buttonOk":"אישור","buttonCancel":"ביטול","buttonSave":"שמירה","itemClose":"סגירה"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.he");dijit.form.nls.validate.he={"rangeMessage":"הערך מחוץ לטווח.","invalidMessage":"הערך שצוין אינו חוקי.","missingMessage":"זהו ערך דרוש."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.he");dojo.cldr.nls.number.he={"group":",","percentSign":"%","exponential":"E","percentFormat":"#,##0%","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":".","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","currencyFormat":"#,##0.00 ¤","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.he");dijit.form.nls.ComboBox.he={"previousMessage":"האפשרויות הקודמות","nextMessage":"אפשרויות נוספות"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_hu.js b/UNGProject/dojo/dojo/nls/refimpldojo_hu.js
new file mode 100644
index 0000000000000000000000000000000000000000..a6116035688696fa562be068faf48eacdeccf34a
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_hu.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_hu");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.hu");dojo.cldr.nls.gregorian.hu={"field-dayperiod":"napszak","field-minute":"perc","eraNames":["időszámításunk előtt","időszámításunk szerint"],"field-weekday":"hét napja","dateFormatItem-MMdd":"MM.dd.","days-standAlone-wide":["vasárnap","hétfő","kedd","szerda","csütörtök","péntek","szombat"],"dateFormatItem-MMM":"LLL","patternChars":"GanjkHmsSEDFwWxhKzAeugXZvcL","months-standAlone-narrow":["J","F","M","Á","M","J","J","A","S","O","N","D"],"field-era":"éra","field-hour":"óra","quarters-standAlone-abbr":["N1","N2","N3","N4"],"timeFormat-full":"H:mm:ss v","months-standAlone-abbr":["jan.","febr.","márc.","ápr.","máj.","jún.","júl.","aug.","szept.","okt.","nov.","dec."],"days-standAlone-narrow":["V","H","K","S","C","P","S"],"eraAbbr":["i. e.","i. sz."],"dateFormatItem-yyyyMM":"yyyy.MM","dateFormatItem-yyyyMMMM":"yyyy. MMMM","dateFormat-long":"yyyy. MMMM d.","timeFormat-medium":"H:mm:ss","field-zone":"zóna","dateFormatItem-Hm":"HH:mm","dateFormat-medium":"yyyy.MM.dd.","quarters-standAlone-wide":["I. negyedév","II. negyedév","III. negyedév","IV. negyedév"],"dateTimeFormat":"{1} {0}","field-year":"év","quarters-standAlone-narrow":["1","2","3","4"],"months-standAlone-wide":["január","február","március","április","május","június","július","augusztus","szeptember","október","november","december"],"field-week":"hét","dateFormatItem-MMMd":"MMM d","dateFormatItem-yyQ":"Q yy","timeFormat-long":"H:mm:ss z","months-format-abbr":["jan.","febr.","márc.","ápr.","máj.","jún.","júl.","aug.","szept.","okt.","nov.","dec."],"timeFormat-short":"H:mm","field-month":"hónap","dateFormatItem-MMMMd":"MMMM d.","quarters-format-abbr":["N1","N2","N3","N4"],"days-format-abbr":["V","H","K","Sze","Cs","P","Szo"],"pm":"du.","dateFormatItem-mmss":"mm:ss","dateFormatItem-M":"L","days-format-narrow":["V","H","K","S","C","P","S"],"field-second":"másodperc","field-day":"nap","dateFormatItem-MEd":"M. d., E","months-format-narrow":["J","F","M","Á","M","J","J","A","S","O","N","D"],"am":"de.","days-standAlone-abbr":["V","H","K","Sze","Cs","P","Szo"],"dateFormat-short":"yyyy.MM.dd.","dateFormat-full":"yyyy. MMMM d.","dateFormatItem-Md":"M. d.","months-format-wide":["január","február","március","április","május","június","július","augusztus","szeptember","október","november","december"],"dateFormatItem-d":"d","quarters-format-wide":["I. negyedév","II. negyedév","III. negyedév","IV. negyedév"],"days-format-wide":["vasárnap","hétfő","kedd","szerda","csütörtök","péntek","szombat"],"eraNarrow":["i. e.","i. sz."],"dateFormatItem-yQQQ":"yyyy QQQ","dateFormatItem-yMEd":"EEE, yyyy-M-d","dateFormatItem-MMMEd":"E MMM d","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateFormatItem-yM":"yyyy-M","dateFormatItem-yMMM":"yyyy MMM","dateFormatItem-yQ":"yyyy Q","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","dateFormatItem-ms":"mm:ss","quarters-format-narrow":["1","2","3","4"],"dateFormatItem-yMMMM":"yyyy MMMM","dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateFormatItem-y":"yyyy","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateFormatItem-MMMMEd":"E MMMM d","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateFormatItem-yMMMEd":"EEE, yyyy MMM d","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.hu");dijit.nls.loading.hu={"loadingState":"Betöltés...","errorState":"Sajnálom, hiba történt"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.hu");dijit.nls.common.hu={"buttonOk":"OK","buttonCancel":"Mégse","buttonSave":"Mentés","itemClose":"Bezárás"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.hu");dijit.form.nls.validate.hu={"rangeMessage":"Az érték kívül van a megengedett tartományon.","invalidMessage":"A megadott érték érvénytelen.","missingMessage":"Meg kell adni egy értéket."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.hu");dojo.cldr.nls.number.hu={"group":" ","percentSign":"%","exponential":"E","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":",","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","currencyFormat":"#,##0.00 ¤","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","percentFormat":"#,##0%","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.hu");dijit.form.nls.ComboBox.hu={"previousMessage":"Előző menüpontok","nextMessage":"További menüpontok"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_it-it.js b/UNGProject/dojo/dojo/nls/refimpldojo_it-it.js
new file mode 100644
index 0000000000000000000000000000000000000000..df54d57df84d586373def7cd3c0442337f466652
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_it-it.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_it-it");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.it_it");dojo.cldr.nls.gregorian.it_it={"timeFormat-long":"H:mm:ss z","dateFormatItem-yM":"M/yyyy","field-dayperiod":"periodo del giorno","dateFormatItem-yQ":"Q-yyyy","field-minute":"minuto","eraNames":["a.C.","d.C"],"dateFormatItem-MMMEd":"EEE d MMM","field-weekday":"giorno della settimana","dateFormatItem-yQQQ":"QQQ yyyy","dateFormatItem-MMdd":"dd/MM","days-standAlone-wide":["Domenica","Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato"],"dateFormatItem-MMM":"LLL","months-standAlone-narrow":["G","F","M","A","M","G","L","A","S","O","N","D"],"field-era":"era","field-hour":"ora","dateFormatItem-hhmm":"hh.mm a","quarters-standAlone-abbr":["T1","T2","T3","T4"],"dateFormatItem-y":"yyyy","timeFormat-full":"HH.mm.ss v","months-standAlone-abbr":["gen","feb","mar","apr","mag","giu","lug","ago","set","ott","nov","dic"],"dateFormatItem-yMMM":"MMM yyyy","days-standAlone-narrow":["D","L","M","M","G","V","S"],"eraAbbr":["aC","dC"],"dateFormatItem-yyyyMMMM":"MMMM yyyy","dateFormat-long":"dd MMMM yyyy","timeFormat-medium":"HH.mm.ss","field-zone":"zona","dateFormatItem-Hm":"HH:mm","dateFormatItem-yyMM":"MM/yy","dateFormat-medium":"dd/MMM/yyyy","dateFormatItem-yyQQQQ":"QQQQ yy","quarters-standAlone-wide":["1o trimestre","2o trimestre","3o trimestre","4o trimestre"],"dateTimeFormat":"{1} {0}","dateFormatItem-yMMMM":"MMMM yyyy","dateFormatItem-ms":"mm:ss","field-year":"anno","quarters-standAlone-narrow":["1","2","3","4"],"dateFormatItem-HHmmss":"HH.mm.ss","months-standAlone-wide":["Gennaio","Febbraio","Marzo","Aprile","Maggio","Giugno","Luglio","agosto","settembre","ottobre","novembre","dicembre"],"field-week":"settimana","dateFormatItem-MMMMEd":"EEE d MMMM","dateFormatItem-MMMd":"d MMM","dateFormatItem-HHmm":"HH.mm","dateFormatItem-yyQ":"Q yy","months-format-abbr":["gen","feb","mar","apr","mag","giu","lug","ago","set","ott","nov","dic"],"timeFormat-short":"HH.mm","field-month":"mese","dateFormatItem-MMMMd":"d MMMM","quarters-format-abbr":["T1","T2","T3","T4"],"days-format-abbr":["dom","lun","mar","mer","gio","ven","sab"],"dateFormatItem-MMMMdd":"dd MMMM","pm":"p.","dateFormatItem-M":"L","days-format-narrow":["D","L","M","M","G","V","S"],"field-second":"secondo","field-day":"giorno","dateFormatItem-MEd":"EEE d/M","months-format-narrow":["G","F","M","A","M","G","L","A","S","O","N","D"],"dateFormatItem-hhmmss":"hh.mm.ss a","am":"m.","days-standAlone-abbr":["dom","lun","mar","mer","gio","ven","sab"],"dateFormat-short":"dd/MM/yy","dateFormatItem-yMMMEd":"EEE d MMM yyyy","dateFormat-full":"EEEE d MMMM yyyy","dateFormatItem-Md":"d/M","dateFormatItem-yMEd":"EEE, d-M-yyyy","months-format-wide":["gennaio","febbraio","marzo","aprile","maggio","giugno","Luglio","agosto","settembre","ottobre","novembre","dicembre"],"dateFormatItem-d":"d","quarters-format-wide":["1o trimestre","2o trimestre","3o trimestre","4o trimestre"],"days-format-wide":["domenica","lunedì","martedì","mercoledì","giovedì","venerdì","sabato"],"eraNarrow":["aC","dC"],"dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","patternChars":"GyMdkHmsSEDFwWahKzYeugAZvcL","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.it_it");dijit.nls.loading.it_it={"loadingState":"Caricamento in corso...","errorState":"Si è verificato un errore"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.it_it");dijit.nls.common.it_it={"buttonOk":"OK","buttonCancel":"Annulla","buttonSave":"Salva","itemClose":"Chiudi"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.it_it");dijit.form.nls.validate.it_it={"rangeMessage":"Questo valore non è compreso nell'intervallo.","invalidMessage":"Il valore immesso non è valido.","missingMessage":"Questo valore è obbligatorio."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.it_it");dojo.cldr.nls.number.it_it={"decimalFormat":"#,##0.###","group":".","scientificFormat":"#E0","percentFormat":"#,##0%","currencyFormat":"¤ #,##0.00","decimal":",","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","infinity":"∞","list":";","percentSign":"%","minusSign":"-","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","nan":"NaN","nativeZeroDigit":"0","plusSign":"+","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","perMille":"‰","patternDigit":"#","currencySpacing-beforeCurrency-insertBetween":" ","exponential":"E"};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.it_it");dijit.form.nls.ComboBox.it_it={"previousMessage":"Scelte precedenti","nextMessage":"Altre scelte"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_it.js b/UNGProject/dojo/dojo/nls/refimpldojo_it.js
new file mode 100644
index 0000000000000000000000000000000000000000..a97a0b9c43b7abe88267c5b4554c70f7e21c034e
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_it.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_it");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.it");dojo.cldr.nls.gregorian.it={"dateFormatItem-yM":"M/yyyy","field-dayperiod":"periodo del giorno","dateFormatItem-yQ":"Q-yyyy","field-minute":"minuto","eraNames":["a.C.","d.C"],"dateFormatItem-MMMEd":"EEE d MMM","field-weekday":"giorno della settimana","dateFormatItem-yQQQ":"QQQ yyyy","dateFormatItem-MMdd":"dd/MM","days-standAlone-wide":["Domenica","Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato"],"dateFormatItem-MMM":"LLL","months-standAlone-narrow":["G","F","M","A","M","G","L","A","S","O","N","D"],"field-era":"era","field-hour":"ora","dateFormatItem-hhmm":"hh.mm a","quarters-standAlone-abbr":["T1","T2","T3","T4"],"dateFormatItem-y":"yyyy","timeFormat-full":"HH.mm.ss v","months-standAlone-abbr":["gen","feb","mar","apr","mag","giu","lug","ago","set","ott","nov","dic"],"dateFormatItem-yMMM":"MMM yyyy","days-standAlone-narrow":["D","L","M","M","G","V","S"],"eraAbbr":["aC","dC"],"dateFormatItem-yyyyMMMM":"MMMM yyyy","dateFormat-long":"dd MMMM yyyy","timeFormat-medium":"HH.mm.ss","field-zone":"zona","dateFormatItem-Hm":"HH:mm","dateFormatItem-yyMM":"MM/yy","dateFormat-medium":"dd/MMM/yyyy","dateFormatItem-yyQQQQ":"QQQQ yy","quarters-standAlone-wide":["1o trimestre","2o trimestre","3o trimestre","4o trimestre"],"dateTimeFormat":"{1} {0}","dateFormatItem-yMMMM":"MMMM yyyy","dateFormatItem-ms":"mm:ss","field-year":"anno","quarters-standAlone-narrow":["1","2","3","4"],"dateFormatItem-HHmmss":"HH.mm.ss","months-standAlone-wide":["Gennaio","Febbraio","Marzo","Aprile","Maggio","Giugno","Luglio","agosto","settembre","ottobre","novembre","dicembre"],"field-week":"settimana","dateFormatItem-MMMMEd":"EEE d MMMM","dateFormatItem-MMMd":"d MMM","dateFormatItem-HHmm":"HH.mm","dateFormatItem-yyQ":"Q yy","timeFormat-long":"HH.mm.ss z","months-format-abbr":["gen","feb","mar","apr","mag","giu","lug","ago","set","ott","nov","dic"],"timeFormat-short":"HH.mm","field-month":"mese","dateFormatItem-MMMMd":"d MMMM","quarters-format-abbr":["T1","T2","T3","T4"],"days-format-abbr":["dom","lun","mar","mer","gio","ven","sab"],"dateFormatItem-MMMMdd":"dd MMMM","pm":"p.","dateFormatItem-M":"L","days-format-narrow":["D","L","M","M","G","V","S"],"field-second":"secondo","field-day":"giorno","dateFormatItem-MEd":"EEE d/M","months-format-narrow":["G","F","M","A","M","G","L","A","S","O","N","D"],"dateFormatItem-hhmmss":"hh.mm.ss a","am":"m.","days-standAlone-abbr":["dom","lun","mar","mer","gio","ven","sab"],"dateFormat-short":"dd/MM/yy","dateFormatItem-yMMMEd":"EEE d MMM yyyy","dateFormat-full":"EEEE d MMMM yyyy","dateFormatItem-Md":"d/M","dateFormatItem-yMEd":"EEE, d-M-yyyy","months-format-wide":["gennaio","febbraio","marzo","aprile","maggio","giugno","Luglio","agosto","settembre","ottobre","novembre","dicembre"],"dateFormatItem-d":"d","quarters-format-wide":["1o trimestre","2o trimestre","3o trimestre","4o trimestre"],"days-format-wide":["domenica","lunedì","martedì","mercoledì","giovedì","venerdì","sabato"],"eraNarrow":["aC","dC"],"dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","patternChars":"GyMdkHmsSEDFwWahKzYeugAZvcL","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.it");dijit.nls.loading.it={"loadingState":"Caricamento in corso...","errorState":"Si è verificato un errore"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.it");dijit.nls.common.it={"buttonOk":"OK","buttonCancel":"Annulla","buttonSave":"Salva","itemClose":"Chiudi"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.it");dijit.form.nls.validate.it={"rangeMessage":"Questo valore non è compreso nell'intervallo.","invalidMessage":"Il valore immesso non è valido.","missingMessage":"Questo valore è obbligatorio."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.it");dojo.cldr.nls.number.it={"decimalFormat":"#,##0.###","group":".","scientificFormat":"#E0","percentFormat":"#,##0%","currencyFormat":"¤ #,##0.00","decimal":",","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","infinity":"∞","list":";","percentSign":"%","minusSign":"-","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","nan":"NaN","nativeZeroDigit":"0","plusSign":"+","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","perMille":"‰","patternDigit":"#","currencySpacing-beforeCurrency-insertBetween":" ","exponential":"E"};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.it");dijit.form.nls.ComboBox.it={"previousMessage":"Scelte precedenti","nextMessage":"Altre scelte"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_ja-jp.js b/UNGProject/dojo/dojo/nls/refimpldojo_ja-jp.js
new file mode 100644
index 0000000000000000000000000000000000000000..39e7efc240126f7afb7368fafda2891f787e1dc8
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_ja-jp.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_ja-jp");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.ja_jp");dojo.cldr.nls.gregorian.ja_jp={"dateFormatItem-yM":"y/M","field-dayperiod":"午前/午後","dateFormatItem-yQ":"y/Q","dateFormatItem-GGGGyMd":"GGGGy年M月d日","field-minute":"分","eraNames":["紀元前","西暦"],"dateFormatItem-MMMEd":"M月d日(E)","field-weekday":"曜日","dateFormatItem-yQQQ":"yyyyQQQ","dateFormatItem-MMdd":"MM/dd","days-standAlone-wide":["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"],"dateFormatItem-MMM":"LLL","patternChars":"GanjkHmsSEDFwWxhKzAeugXZvcL","months-standAlone-narrow":["1","2","3","4","5","6","7","8","9","10","11","12"],"field-era":"時代","field-hour":"時","dateFormatItem-y":"y","timeFormat-full":"H時mm分ss秒v","dateFormatItem-yyyy":"y年","months-standAlone-abbr":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"dateFormatItem-Ed":"d日(EEE)","dateFormatItem-yMMM":"y年M月","days-standAlone-narrow":["日","月","火","水","木","金","土"],"eraAbbr":["紀元前","西暦"],"dateFormatItem-yyyyMM":"yyyy/MM","dateFormat-long":"yyyy年M月d日","timeFormat-medium":"H:mm:ss","field-zone":"タイムゾーン","dateFormatItem-Hm":"H:mm","dateFormat-medium":"yyyy/MM/dd","dateFormatItem-yyMMM":"y年M月","quarters-standAlone-wide":["第1四半期","第2四半期","第3四半期","第4四半期"],"dateTimeFormat":"{1} {0}","dateFormatItem-yMMMM":"y年M月","dateFormatItem-ms":"mm:ss","field-year":"年","quarters-standAlone-narrow":["1","2","3","4"],"field-week":"週","months-standAlone-wide":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"dateFormatItem-MMMMEd":"M月d日(E)","dateFormatItem-MMMd":"M月d日","dateFormatItem-yyQ":"yy/Q","timeFormat-long":"HH:mm:ssz","months-format-abbr":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"timeFormat-short":"H:mm","dateFormatItem-H":"H時","field-month":"月","dateFormatItem-MMMMd":"M月d日","quarters-format-abbr":["Q1","Q2","Q3","Q4"],"days-format-abbr":["日","月","火","水","木","金","土"],"pm":"午後","dateFormatItem-M":"L","dateFormatItem-mmss":"mm:ss","days-format-narrow":["日","月","火","水","木","金","土"],"field-second":"秒","field-day":"日","dateFormatItem-MEd":"M/d(E)","am":"午前","days-standAlone-abbr":["日","月","火","水","木","金","土"],"dateFormat-short":"yy/MM/dd","dateFormatItem-yMMMEd":"y年M月d日(EEE)","dateFormat-full":"yyyy年M月d日EEEE","dateFormatItem-Md":"M/d","dateFormatItem-yMEd":"y/M/d(EEE)","months-format-wide":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"dateFormatItem-d":"d日","quarters-format-wide":["第1四半期","第2四半期","第3四半期","第4四半期"],"days-format-wide":["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"],"eraNarrow":["紀元前","西暦"],"months-format-narrow":["1","2","3","4","5","6","7","8","9","10","11","12"],"dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-standAlone-abbr":["Q1","Q2","Q3","Q4"],"quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.ja_jp");dijit.nls.loading.ja_jp={"loadingState":"ロード中...","errorState":"エラーが発生しました。"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.ja_jp");dijit.nls.common.ja_jp={"buttonOk":"OK","buttonCancel":"キャンセル","buttonSave":"保存","itemClose":"閉じる"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.ja_jp");dijit.form.nls.validate.ja_jp={"rangeMessage":"この値は範囲外です。","invalidMessage":"入力した値は無効です。","missingMessage":"この値は必須です。"};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.ja_jp");dojo.cldr.nls.number.ja_jp={"currencyFormat":"¤#,##0.00","decimalFormat":"#,##0.###","group":",","scientificFormat":"#E0","percentFormat":"#,##0%","decimal":".","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","infinity":"∞","list":";","percentSign":"%","minusSign":"-","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","nan":"NaN","nativeZeroDigit":"0","plusSign":"+","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","perMille":"‰","patternDigit":"#","currencySpacing-beforeCurrency-insertBetween":" ","exponential":"E"};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.ja_jp");dijit.form.nls.ComboBox.ja_jp={"previousMessage":"以前の選択項目","nextMessage":"追加の選択項目"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_ja.js b/UNGProject/dojo/dojo/nls/refimpldojo_ja.js
new file mode 100644
index 0000000000000000000000000000000000000000..6de019dbe5421d7ec76250f38d629c9490567ca3
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_ja.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_ja");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.ja");dojo.cldr.nls.gregorian.ja={"dateFormatItem-yM":"y/M","field-dayperiod":"午前/午後","dateFormatItem-yQ":"y/Q","dateFormatItem-GGGGyMd":"GGGGy年M月d日","field-minute":"分","eraNames":["紀元前","西暦"],"dateFormatItem-MMMEd":"M月d日(E)","field-weekday":"曜日","dateFormatItem-yQQQ":"yyyyQQQ","dateFormatItem-MMdd":"MM/dd","days-standAlone-wide":["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"],"dateFormatItem-MMM":"LLL","patternChars":"GanjkHmsSEDFwWxhKzAeugXZvcL","months-standAlone-narrow":["1","2","3","4","5","6","7","8","9","10","11","12"],"field-era":"時代","field-hour":"時","dateFormatItem-y":"y","timeFormat-full":"H時mm分ss秒v","dateFormatItem-yyyy":"y年","months-standAlone-abbr":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"dateFormatItem-Ed":"d日(EEE)","dateFormatItem-yMMM":"y年M月","days-standAlone-narrow":["日","月","火","水","木","金","土"],"eraAbbr":["紀元前","西暦"],"dateFormatItem-yyyyMM":"yyyy/MM","dateFormat-long":"yyyy年M月d日","timeFormat-medium":"H:mm:ss","field-zone":"タイムゾーン","dateFormatItem-Hm":"H:mm","dateFormat-medium":"yyyy/MM/dd","dateFormatItem-yyMMM":"y年M月","quarters-standAlone-wide":["第1四半期","第2四半期","第3四半期","第4四半期"],"dateTimeFormat":"{1} {0}","dateFormatItem-yMMMM":"y年M月","dateFormatItem-ms":"mm:ss","field-year":"年","quarters-standAlone-narrow":["1","2","3","4"],"field-week":"週","months-standAlone-wide":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"dateFormatItem-MMMMEd":"M月d日(E)","dateFormatItem-MMMd":"M月d日","dateFormatItem-yyQ":"yy/Q","timeFormat-long":"HH:mm:ssz","months-format-abbr":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"timeFormat-short":"H:mm","dateFormatItem-H":"H時","field-month":"月","dateFormatItem-MMMMd":"M月d日","quarters-format-abbr":["Q1","Q2","Q3","Q4"],"days-format-abbr":["日","月","火","水","木","金","土"],"pm":"午後","dateFormatItem-M":"L","dateFormatItem-mmss":"mm:ss","days-format-narrow":["日","月","火","水","木","金","土"],"field-second":"秒","field-day":"日","dateFormatItem-MEd":"M/d(E)","am":"午前","days-standAlone-abbr":["日","月","火","水","木","金","土"],"dateFormat-short":"yy/MM/dd","dateFormatItem-yMMMEd":"y年M月d日(EEE)","dateFormat-full":"yyyy年M月d日EEEE","dateFormatItem-Md":"M/d","dateFormatItem-yMEd":"y/M/d(EEE)","months-format-wide":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"dateFormatItem-d":"d日","quarters-format-wide":["第1四半期","第2四半期","第3四半期","第4四半期"],"days-format-wide":["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"],"eraNarrow":["紀元前","西暦"],"months-format-narrow":["1","2","3","4","5","6","7","8","9","10","11","12"],"dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-standAlone-abbr":["Q1","Q2","Q3","Q4"],"quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.ja");dijit.nls.loading.ja={"loadingState":"ロード中...","errorState":"エラーが発生しました。"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.ja");dijit.nls.common.ja={"buttonOk":"OK","buttonCancel":"キャンセル","buttonSave":"保存","itemClose":"閉じる"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.ja");dijit.form.nls.validate.ja={"rangeMessage":"この値は範囲外です。","invalidMessage":"入力した値は無効です。","missingMessage":"この値は必須です。"};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.ja");dojo.cldr.nls.number.ja={"decimalFormat":"#,##0.###","group":",","scientificFormat":"#E0","percentFormat":"#,##0%","currencyFormat":"¤#,##0.00","decimal":".","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","infinity":"∞","list":";","percentSign":"%","minusSign":"-","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","nan":"NaN","nativeZeroDigit":"0","plusSign":"+","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","perMille":"‰","patternDigit":"#","currencySpacing-beforeCurrency-insertBetween":" ","exponential":"E"};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.ja");dijit.form.nls.ComboBox.ja={"previousMessage":"以前の選択項目","nextMessage":"追加の選択項目"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_ko-kr.js b/UNGProject/dojo/dojo/nls/refimpldojo_ko-kr.js
new file mode 100644
index 0000000000000000000000000000000000000000..66a934c64ff4a7783c14b2ede7fdbef9324244f5
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_ko-kr.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_ko-kr");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.ko_kr");dojo.cldr.nls.gregorian.ko_kr={"timeFormat-medium":"a h:mm:ss","timeFormat-short":"a h:mm","months-format-narrow":["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"요일","dateFormatItem-yQQQ":"yyyy년 QQQ","dateFormatItem-yMEd":"yyyy. M. d. EEE","dateFormatItem-MMMEd":"MMM d일 (E)","eraNarrow":["기원전","서기"],"dateFormat-long":"yyyy년 M월 d일","months-format-wide":["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],"dateFormat-full":"yyyy년 M월 d일 EEEE","dateFormatItem-Md":"M. d.","field-era":"연호","dateFormatItem-yM":"yyyy. M.","months-standAlone-wide":["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],"quarters-format-wide":["제 1/4분기","제 2/4분기","제 3/4분기","제 4/4분기"],"dateTimeFormat":"{1} {0}","timeFormat-long":"a hh시 mm분 ss초 z","field-year":"년","dateFormatItem-yMMM":"yyyy년 MMM","dateFormatItem-yQ":"yyyy년 Q분기","field-hour":"시","dateFormatItem-MMdd":"MM. dd","months-format-abbr":["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],"dateFormatItem-yyQ":"yy년 Q분기","patternChars":"GanjkHmsSEDFwWxhKzAeugXZvcL","timeFormat-full":"a hh시 mm분 ss초 v","am":"오전","months-standAlone-abbr":["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],"quarters-format-abbr":["1분기","2분기","3분기","4분기"],"quarters-standAlone-wide":["제 1/4분기","제 2/4분기","제 3/4분기","제 4/4분기"],"dateFormatItem-HHmmss":"HH:mm:ss","dateFormatItem-M":"L","days-standAlone-wide":["일요일","월요일","화요일","수요일","목요일","금요일","토요일"],"dateFormatItem-MMMMd":"MMMM d일","dateFormatItem-yyMMM":"yy년 MMM","dateFormatItem-Hm":"H:mm","quarters-standAlone-abbr":["1분기","2분기","3분기","4분기"],"eraAbbr":["기원전","서기"],"field-minute":"분","field-dayperiod":"오전/오후","days-standAlone-abbr":["일","월","화","수","목","금","토"],"dateFormatItem-d":"d","dateFormatItem-ms":"mm:ss","dateFormatItem-MMMd":"MMM d일","dateFormatItem-MEd":"M. d. (E)","dateFormatItem-yMMMM":"yyyy년 MMMM","field-day":"일","days-format-wide":["일요일","월요일","화요일","수요일","목요일","금요일","토요일"],"field-zone":"시간대","dateFormatItem-yyyyMM":"yyyy. MM","dateFormatItem-y":"yyyy","months-standAlone-narrow":["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],"dateFormatItem-yyMM":"YY. M.","days-format-abbr":["일","월","화","수","목","금","토"],"eraNames":["서력기원전","서력기원"],"days-format-narrow":["일","월","화","수","목","금","토"],"field-month":"월","days-standAlone-narrow":["일","월","화","수","목","금","토"],"dateFormatItem-MMM":"LLL","dateFormatItem-HHmm":"HH:mm","pm":"오후","dateFormatItem-MMMMEd":"MMMM d일 (E)","dateFormat-short":"yy. M. d.","field-second":"초","dateFormatItem-yMMMEd":"yyyy년 MMM d일 EEE","dateFormatItem-Ed":"d일 (E)","field-week":"주","dateFormat-medium":"yyyy. M. d.","dateFormatItem-mmss":"mm:ss","dateFormatItem-Hms":"H시 m분 s초","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.ko_kr");dijit.nls.loading.ko_kr={"loadingState":"로드 중...","errorState":"죄송합니다. 오류가 발생했습니다."};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.ko_kr");dijit.nls.common.ko_kr={"buttonOk":"확인","buttonCancel":"취소","buttonSave":"저장","itemClose":"닫기"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.ko_kr");dijit.form.nls.validate.ko_kr={"rangeMessage":"이 값은 범위를 벗어납니다.","invalidMessage":"입력된 값이 올바르지 않습니다.","missingMessage":"이 값은 필수입니다."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.ko_kr");dojo.cldr.nls.number.ko_kr={"currencyFormat":"¤#,##0.00","group":",","percentSign":"%","exponential":"E","percentFormat":"#,##0%","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":".","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.ko_kr");dijit.form.nls.ComboBox.ko_kr={"previousMessage":"이전 선택사항","nextMessage":"기타 선택사항"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_ko.js b/UNGProject/dojo/dojo/nls/refimpldojo_ko.js
new file mode 100644
index 0000000000000000000000000000000000000000..4c792cf88532d4ee2e72881c46df463465bf2a51
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_ko.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_ko");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.ko");dojo.cldr.nls.gregorian.ko={"months-format-narrow":["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"요일","dateFormatItem-yQQQ":"yyyy년 QQQ","dateFormatItem-yMEd":"yyyy. M. d. EEE","dateFormatItem-MMMEd":"MMM d일 (E)","eraNarrow":["기원전","서기"],"dateFormat-long":"yyyy년 M월 d일","months-format-wide":["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],"dateFormat-full":"yyyy년 M월 d일 EEEE","dateFormatItem-Md":"M. d.","field-era":"연호","dateFormatItem-yM":"yyyy. M.","months-standAlone-wide":["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],"timeFormat-short":"a h:mm","quarters-format-wide":["제 1/4분기","제 2/4분기","제 3/4분기","제 4/4분기"],"dateTimeFormat":"{1} {0}","timeFormat-long":"a hh시 mm분 ss초 z","field-year":"년","dateFormatItem-yMMM":"yyyy년 MMM","dateFormatItem-yQ":"yyyy년 Q분기","field-hour":"시","dateFormatItem-MMdd":"MM. dd","months-format-abbr":["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],"dateFormatItem-yyQ":"yy년 Q분기","patternChars":"GanjkHmsSEDFwWxhKzAeugXZvcL","timeFormat-full":"a hh시 mm분 ss초 v","am":"오전","months-standAlone-abbr":["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],"quarters-format-abbr":["1분기","2분기","3분기","4분기"],"quarters-standAlone-wide":["제 1/4분기","제 2/4분기","제 3/4분기","제 4/4분기"],"dateFormatItem-HHmmss":"HH:mm:ss","dateFormatItem-M":"L","days-standAlone-wide":["일요일","월요일","화요일","수요일","목요일","금요일","토요일"],"dateFormatItem-MMMMd":"MMMM d일","dateFormatItem-yyMMM":"yy년 MMM","timeFormat-medium":"a h:mm:ss","dateFormatItem-Hm":"H:mm","quarters-standAlone-abbr":["1분기","2분기","3분기","4분기"],"eraAbbr":["기원전","서기"],"field-minute":"분","field-dayperiod":"오전/오후","days-standAlone-abbr":["일","월","화","수","목","금","토"],"dateFormatItem-d":"d","dateFormatItem-ms":"mm:ss","dateFormatItem-MMMd":"MMM d일","dateFormatItem-MEd":"M. d. (E)","dateFormatItem-yMMMM":"yyyy년 MMMM","field-day":"일","days-format-wide":["일요일","월요일","화요일","수요일","목요일","금요일","토요일"],"field-zone":"시간대","dateFormatItem-yyyyMM":"yyyy. MM","dateFormatItem-y":"yyyy","months-standAlone-narrow":["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],"dateFormatItem-yyMM":"YY. M.","days-format-abbr":["일","월","화","수","목","금","토"],"eraNames":["서력기원전","서력기원"],"days-format-narrow":["일","월","화","수","목","금","토"],"field-month":"월","days-standAlone-narrow":["일","월","화","수","목","금","토"],"dateFormatItem-MMM":"LLL","dateFormatItem-HHmm":"HH:mm","pm":"오후","dateFormatItem-MMMMEd":"MMMM d일 (E)","dateFormat-short":"yy. M. d.","field-second":"초","dateFormatItem-yMMMEd":"yyyy년 MMM d일 EEE","dateFormatItem-Ed":"d일 (E)","field-week":"주","dateFormat-medium":"yyyy. M. d.","dateFormatItem-mmss":"mm:ss","dateFormatItem-Hms":"H시 m분 s초","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.ko");dijit.nls.loading.ko={"loadingState":"로드 중...","errorState":"죄송합니다. 오류가 발생했습니다."};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.ko");dijit.nls.common.ko={"buttonOk":"확인","buttonCancel":"취소","buttonSave":"저장","itemClose":"닫기"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.ko");dijit.form.nls.validate.ko={"rangeMessage":"이 값은 범위를 벗어납니다.","invalidMessage":"입력된 값이 올바르지 않습니다.","missingMessage":"이 값은 필수입니다."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.ko");dojo.cldr.nls.number.ko={"group":",","percentSign":"%","exponential":"E","percentFormat":"#,##0%","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":".","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","currencyFormat":"¤#,##0.00","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.ko");dijit.form.nls.ComboBox.ko={"previousMessage":"이전 선택사항","nextMessage":"기타 선택사항"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_nl-nl.js b/UNGProject/dojo/dojo/nls/refimpldojo_nl-nl.js
new file mode 100644
index 0000000000000000000000000000000000000000..3df1e7658b0a04f13d96d90b43a745a88219a4eb
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_nl-nl.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_nl-nl");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.nl_nl");dojo.cldr.nls.gregorian.nl_nl={"dateFormatItem-yM":"M-yyyy","field-dayperiod":"AM/PM","dateFormatItem-yQ":"Q yyyy","field-minute":"Minuut","eraNames":["Voor Christus","Anno Domini"],"dateFormatItem-MMMEd":"E d MMM","field-weekday":"Dag van de week","dateFormatItem-yQQQ":"QQQ yyyy","dateFormatItem-MMdd":"dd-MM","days-standAlone-wide":["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],"dateFormatItem-MMM":"LLL","months-standAlone-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"field-era":"Tijdperk","field-hour":"Uur","quarters-standAlone-abbr":["K1","K2","K3","K4"],"dateFormatItem-y":"yyyy","timeFormat-full":"HH:mm:ss v","months-standAlone-abbr":["jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec"],"dateFormatItem-yMMM":"MMM yyyy","days-standAlone-narrow":["Z","M","D","W","D","V","Z"],"eraAbbr":["v. Chr.","n. Chr."],"dateFormatItem-yyyyMMMM":"MMMM yyyy","dateFormat-long":"d MMMM yyyy","timeFormat-medium":"HH:mm:ss","field-zone":"Zone","dateFormatItem-Hm":"HH:mm","dateFormatItem-MMd":"d-MM","dateFormatItem-yyMM":"MM-yy","dateFormat-medium":"d MMM yyyy","dateFormatItem-yyMMM":"MMM yy","dateFormatItem-yyQQQQ":"QQQQ yy","quarters-standAlone-wide":["1e kwartaal","2e kwartaal","3e kwartaal","4e kwartaal"],"dateTimeFormat":"{1} {0}","dateFormatItem-yMMMM":"MMMM yyyy","dateFormatItem-ms":"mm:ss","field-year":"Jaar","quarters-standAlone-narrow":["1","2","3","4"],"field-week":"Week","months-standAlone-wide":["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],"dateFormatItem-MMMMEd":"E d MMMM","dateFormatItem-MMMd":"d-MMM","dateFormatItem-yyQ":"Q yy","timeFormat-long":"HH:mm:ss z","months-format-abbr":["jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec"],"timeFormat-short":"HH:mm","field-month":"Maand","dateFormatItem-MMMMd":"d MMMM","quarters-format-abbr":["K1","K2","K3","K4"],"days-format-abbr":["zo","ma","di","wo","do","vr","za"],"pm":"PM","dateFormatItem-mmss":"mm:ss","dateFormatItem-M":"L","days-format-narrow":["Z","M","D","W","D","V","Z"],"field-second":"Seconde","field-day":"Dag","dateFormatItem-MEd":"E, d-M","months-format-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"am":"AM","days-standAlone-abbr":["zo","ma","di","wo","do","vr","za"],"dateFormat-short":"dd-MM-yy","dateFormatItem-yMMMEd":"EEE, d MMM yyyy","dateFormat-full":"EEEE d MMMM yyyy","dateFormatItem-Md":"d-M","dateFormatItem-yMEd":"EEE, d-M-yyyy","months-format-wide":["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],"dateFormatItem-d":"d","quarters-format-wide":["1e kwartaal","2e kwartaal","3e kwartaal","4e kwartaal"],"days-format-wide":["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],"eraNarrow":["v. Chr.","n. Chr."],"dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","patternChars":"GyMdkHmsSEDFwWahKzYeugAZvcL","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.nl_nl");dijit.nls.loading.nl_nl={"loadingState":"Bezig met laden...","errorState":"Er is een fout opgetreden"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.nl_nl");dijit.nls.common.nl_nl={"buttonOk":"OK","buttonCancel":"Annuleren","buttonSave":"Opslaan","itemClose":"Sluiten"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.nl_nl");dijit.form.nls.validate.nl_nl={"rangeMessage":"Deze waarde is niet toegestaan.","invalidMessage":"De opgegeven waarde is ongeldig.","missingMessage":"Deze waarde is verplicht."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.nl_nl");dojo.cldr.nls.number.nl_nl={"group":".","percentSign":"%","exponential":"E","percentFormat":"#,##0%","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":",","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","currencyFormat":"¤ #,##0.00;¤ #,##0.00-","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.nl_nl");dijit.form.nls.ComboBox.nl_nl={"previousMessage":"Eerdere opties","nextMessage":"Meer opties"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_nl.js b/UNGProject/dojo/dojo/nls/refimpldojo_nl.js
new file mode 100644
index 0000000000000000000000000000000000000000..f59f2777af0933e82c10c2b4efee286c56bb83f6
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_nl.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_nl");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.nl");dojo.cldr.nls.gregorian.nl={"dateFormatItem-yM":"M-yyyy","field-dayperiod":"AM/PM","dateFormatItem-yQ":"Q yyyy","field-minute":"Minuut","eraNames":["Voor Christus","Anno Domini"],"dateFormatItem-MMMEd":"E d MMM","field-weekday":"Dag van de week","dateFormatItem-yQQQ":"QQQ yyyy","dateFormatItem-MMdd":"dd-MM","days-standAlone-wide":["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],"dateFormatItem-MMM":"LLL","months-standAlone-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"field-era":"Tijdperk","field-hour":"Uur","quarters-standAlone-abbr":["K1","K2","K3","K4"],"dateFormatItem-y":"yyyy","timeFormat-full":"HH:mm:ss v","months-standAlone-abbr":["jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec"],"dateFormatItem-yMMM":"MMM yyyy","days-standAlone-narrow":["Z","M","D","W","D","V","Z"],"eraAbbr":["v. Chr.","n. Chr."],"dateFormatItem-yyyyMMMM":"MMMM yyyy","dateFormat-long":"d MMMM yyyy","timeFormat-medium":"HH:mm:ss","field-zone":"Zone","dateFormatItem-Hm":"HH:mm","dateFormatItem-MMd":"d-MM","dateFormatItem-yyMM":"MM-yy","dateFormat-medium":"d MMM yyyy","dateFormatItem-yyMMM":"MMM yy","dateFormatItem-yyQQQQ":"QQQQ yy","quarters-standAlone-wide":["1e kwartaal","2e kwartaal","3e kwartaal","4e kwartaal"],"dateTimeFormat":"{1} {0}","dateFormatItem-yMMMM":"MMMM yyyy","dateFormatItem-ms":"mm:ss","field-year":"Jaar","quarters-standAlone-narrow":["1","2","3","4"],"field-week":"Week","months-standAlone-wide":["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],"dateFormatItem-MMMMEd":"E d MMMM","dateFormatItem-MMMd":"d-MMM","dateFormatItem-yyQ":"Q yy","timeFormat-long":"HH:mm:ss z","months-format-abbr":["jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec"],"timeFormat-short":"HH:mm","field-month":"Maand","dateFormatItem-MMMMd":"d MMMM","quarters-format-abbr":["K1","K2","K3","K4"],"days-format-abbr":["zo","ma","di","wo","do","vr","za"],"pm":"PM","dateFormatItem-mmss":"mm:ss","dateFormatItem-M":"L","days-format-narrow":["Z","M","D","W","D","V","Z"],"field-second":"Seconde","field-day":"Dag","dateFormatItem-MEd":"E, d-M","months-format-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"am":"AM","days-standAlone-abbr":["zo","ma","di","wo","do","vr","za"],"dateFormat-short":"dd-MM-yy","dateFormatItem-yMMMEd":"EEE, d MMM yyyy","dateFormat-full":"EEEE d MMMM yyyy","dateFormatItem-Md":"d-M","dateFormatItem-yMEd":"EEE, d-M-yyyy","months-format-wide":["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],"dateFormatItem-d":"d","quarters-format-wide":["1e kwartaal","2e kwartaal","3e kwartaal","4e kwartaal"],"days-format-wide":["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],"eraNarrow":["v. Chr.","n. Chr."],"dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","patternChars":"GyMdkHmsSEDFwWahKzYeugAZvcL","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.nl");dijit.nls.loading.nl={"loadingState":"Bezig met laden...","errorState":"Er is een fout opgetreden"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.nl");dijit.nls.common.nl={"buttonOk":"OK","buttonCancel":"Annuleren","buttonSave":"Opslaan","itemClose":"Sluiten"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.nl");dijit.form.nls.validate.nl={"rangeMessage":"Deze waarde is niet toegestaan.","invalidMessage":"De opgegeven waarde is ongeldig.","missingMessage":"Deze waarde is verplicht."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.nl");dojo.cldr.nls.number.nl={"group":".","percentSign":"%","exponential":"E","percentFormat":"#,##0%","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":",","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","currencyFormat":"¤ #,##0.00;¤ #,##0.00-","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.nl");dijit.form.nls.ComboBox.nl={"previousMessage":"Eerdere opties","nextMessage":"Meer opties"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_no.js b/UNGProject/dojo/dojo/nls/refimpldojo_no.js
new file mode 100644
index 0000000000000000000000000000000000000000..667cac2b93488b692184f2bece3e1ebcf75947b5
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_no.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_no");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.no");dojo.cldr.nls.gregorian.no={"months-format-narrow":["1","2","3","4","5","6","7","8","9","10","11","12"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"Day of the Week","dateFormatItem-yQQQ":"yyyy QQQ","dateFormatItem-yMEd":"EEE, yyyy-M-d","dateFormatItem-MMMEd":"E MMM d","eraNarrow":["BCE","CE"],"dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateFormat-long":"yyyy MMMM d","months-format-wide":["1","2","3","4","5","6","7","8","9","10","11","12"],"dateFormat-full":"EEEE, yyyy MMMM dd","dateFormatItem-Md":"M-d","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","field-era":"Era","dateFormatItem-yM":"yyyy-M","months-standAlone-wide":["1","2","3","4","5","6","7","8","9","10","11","12"],"timeFormat-short":"HH:mm","quarters-format-wide":["Q1","Q2","Q3","Q4"],"dateTimeFormat":"{1} {0}","timeFormat-long":"HH:mm:ss z","field-year":"Year","dateFormatItem-yMMM":"yyyy MMM","dateFormatItem-yQ":"yyyy Q","dateTimeFormats-appendItem-Era":"{0} {1}","field-hour":"Hour","months-format-abbr":["1","2","3","4","5","6","7","8","9","10","11","12"],"patternChars":"GyMdkHmsSEDFwWahKzYeugAZvcL","timeFormat-full":"HH:mm:ss v","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","am":"AM","months-standAlone-abbr":["1","2","3","4","5","6","7","8","9","10","11","12"],"quarters-format-abbr":["Q1","Q2","Q3","Q4"],"quarters-standAlone-wide":["Q1","Q2","Q3","Q4"],"dateFormatItem-M":"L","days-standAlone-wide":["1","2","3","4","5","6","7"],"dateFormatItem-MMMMd":"MMMM d","timeFormat-medium":"HH:mm:ss","dateFormatItem-Hm":"H:mm","quarters-standAlone-abbr":["Q1","Q2","Q3","Q4"],"eraAbbr":["BCE","CE"],"field-minute":"Minute","field-dayperiod":"Dayperiod","days-standAlone-abbr":["1","2","3","4","5","6","7"],"dateFormatItem-d":"d","dateFormatItem-ms":"mm:ss","quarters-format-narrow":["1","2","3","4"],"dateFormatItem-MMMd":"MMM d","dateFormatItem-MEd":"E, M-d","dateFormatItem-yMMMM":"yyyy MMMM","field-day":"Day","days-format-wide":["1","2","3","4","5","6","7"],"field-zone":"Zone","dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateFormatItem-y":"yyyy","months-standAlone-narrow":["1","2","3","4","5","6","7","8","9","10","11","12"],"dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","days-format-abbr":["1","2","3","4","5","6","7"],"eraNames":["BCE","CE"],"days-format-narrow":["1","2","3","4","5","6","7"],"field-month":"Month","days-standAlone-narrow":["1","2","3","4","5","6","7"],"dateFormatItem-MMM":"LLL","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","pm":"PM","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateFormatItem-MMMMEd":"E MMMM d","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateFormat-short":"yyyy-MM-dd","field-second":"Second","dateFormatItem-yMMMEd":"EEE, yyyy MMM d","dateTimeFormats-appendItem-Timezone":"{0} {1}","field-week":"Week","dateFormat-medium":"yyyy MMM d"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.no");dijit.nls.loading.no={"loadingState":"Loading...","errorState":"Sorry, an error occurred"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.no");dijit.nls.common.no={"buttonOk":"OK","buttonCancel":"Cancel","buttonSave":"Save","itemClose":"Close"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.no");dijit.form.nls.validate.no={"rangeMessage":"This value is out of range.","invalidMessage":"The value entered is not valid.","missingMessage":"This value is required."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.no");dojo.cldr.nls.number.no={"scientificFormat":"#E0","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","infinity":"∞","list":";","percentSign":"%","minusSign":"-","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","nan":"NaN","nativeZeroDigit":"0","plusSign":"+","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencyFormat":"¤ #,##0.00","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","perMille":"‰","group":",","percentFormat":"#,##0%","decimalFormat":"#,##0.###","decimal":".","patternDigit":"#","currencySpacing-beforeCurrency-insertBetween":" ","exponential":"E"};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.no");dijit.form.nls.ComboBox.no={"previousMessage":"Previous choices","nextMessage":"More choices"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_pl.js b/UNGProject/dojo/dojo/nls/refimpldojo_pl.js
new file mode 100644
index 0000000000000000000000000000000000000000..31ff16d8728f2c7ff93e9c1700f70ca21224a4ec
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_pl.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_pl");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.pl");dojo.cldr.nls.gregorian.pl={"dateFormatItem-yM":"yyyy-M","field-dayperiod":"Dayperiod","dateFormatItem-yQ":"yyyy Q","field-minute":"Minuta","eraNames":["p.n.e.","n.e."],"dateFormatItem-MMMEd":"d MMM E","field-weekday":"Dzień tygodnia","dateFormatItem-yQQQ":"yyyy QQQ","dateFormatItem-MMdd":"MM-dd","days-standAlone-wide":["niedziela","poniedziałek","wtorek","środa","czwartek","piątek","sobota"],"dateFormatItem-MMM":"LLL","months-standAlone-narrow":["s","l","m","k","m","c","l","s","w","p","l","g"],"field-era":"Era","field-hour":"Godzina","dateFormatItem-hhmm":"hh:mm a","quarters-standAlone-abbr":["1 kw.","2 kw.","3 kw.","4 kw."],"dateFormatItem-y":"yyyy","timeFormat-full":"HH:mm:ss v","months-standAlone-abbr":["sty","lut","mar","kwi","maj","cze","lip","sie","wrz","paź","lis","gru"],"days-standAlone-narrow":["N","P","W","Ś","C","P","S"],"eraAbbr":["p.n.e.","n.e."],"dateFormatItem-yyyyMM":"yyyy-MM","dateFormatItem-yyyyMMMM":"LLLL yyyy","dateFormat-long":"d MMMM yyyy","timeFormat-medium":"HH:mm:ss","field-zone":"Strefa","dateFormatItem-Hm":"H:mm","dateFormatItem-yyMM":"MM/yy","dateFormat-medium":"yyyy-MM-dd","dateFormatItem-yyMMM":"MMM yy","quarters-standAlone-wide":["I kwartał","II kwartał","III kwartał","IV kwartał"],"dateTimeFormat":"{1} {0}","dateFormatItem-yMMMM":"LLLL yyyy","dateFormatItem-ms":"mm:ss","field-year":"Rok","quarters-standAlone-narrow":["1","2","3","4"],"dateFormatItem-HHmmss":"HH:mm:ss","months-standAlone-wide":["styczeń","luty","marzec","kwiecień","maj","czerwiec","lipiec","sierpień","wrzesień","październik","listopad","grudzień"],"field-week":"Tydzień","dateFormatItem-MMMMEd":"d MMMM E","dateFormatItem-MMMd":"MMM d","dateFormatItem-HHmm":"HH:mm","dateFormatItem-yyQ":"Q yy","timeFormat-long":"HH:mm:ss z","months-format-abbr":["sty","lut","mar","kwi","maj","cze","lip","sie","wrz","paź","lis","gru"],"timeFormat-short":"HH:mm","field-month":"Miesiąc","dateFormatItem-MMMMd":"d MMMM","quarters-format-abbr":["K1","K2","K3","K4"],"days-format-abbr":["niedz.","pon.","wt.","śr.","czw.","pt.","sob."],"pm":"PM","dateFormatItem-M":"L","dateFormatItem-mmss":"mm:ss","days-format-narrow":["N","P","W","Ś","C","P","S"],"field-second":"Sekunda","field-day":"Dzień","dateFormatItem-MEd":"E, M-d","months-format-narrow":["s","l","m","k","m","c","l","s","w","p","l","g"],"dateFormatItem-hhmmss":"hh:mm:ss a","am":"AM","days-standAlone-abbr":["niedz.","pon.","wt.","śr.","czw.","pt.","sob."],"dateFormat-short":"yy-MM-dd","dateFormatItem-yMMMEd":"EEE, d MMM yyyy","dateFormat-full":"EEEE, d MMMM yyyy","dateFormatItem-Md":"d.M","dateFormatItem-yMEd":"EEE, d.M.yyyy","months-format-wide":["stycznia","lutego","marca","kwietnia","maja","czerwca","lipca","sierpnia","września","października","listopada","grudnia"],"dateFormatItem-d":"d","quarters-format-wide":["I kwartał","II kwartał","III kwartał","IV kwartał"],"days-format-wide":["niedziela","poniedziałek","wtorek","środa","czwartek","piątek","sobota"],"eraNarrow":["p.n.e.","n.e."],"dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateFormatItem-yMMM":"yyyy MMM","dateTimeFormats-appendItem-Era":"{0} {1}","patternChars":"GyMdkHmsSEDFwWahKzYeugAZvcL","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.pl");dijit.nls.loading.pl={"loadingState":"Ładowanie...","errorState":"Niestety, wystąpił błąd"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.pl");dijit.nls.common.pl={"buttonOk":"OK","buttonCancel":"Anuluj","buttonSave":"Zapisz","itemClose":"Zamknij"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.pl");dijit.form.nls.validate.pl={"rangeMessage":"Ta wartość jest spoza zakresu.","invalidMessage":"Wprowadzona wartość jest niepoprawna.","missingMessage":"Ta wartość jest wymagana."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.pl");dojo.cldr.nls.number.pl={"group":" ","percentSign":"%","exponential":"E","percentFormat":"#,##0%","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":",","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","currencyFormat":"#,##0.00 ¤","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.pl");dijit.form.nls.ComboBox.pl={"previousMessage":"Poprzednie wybory","nextMessage":"Więcej wyborów"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_pt-br.js b/UNGProject/dojo/dojo/nls/refimpldojo_pt-br.js
new file mode 100644
index 0000000000000000000000000000000000000000..bf70e47ebe6987c04bc155eac5956a261effe145
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_pt-br.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_pt-br");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.pt_br");dojo.cldr.nls.gregorian.pt_br={"field-hour":"Hora","field-dayperiod":"Período do dia","field-minute":"Minuto","timeFormat-full":"HH'h'mm'min'ss's' z","field-week":"Semana","field-weekday":"Dia da semana","field-second":"Segundo","dateFormat-medium":"dd/MM/yyyy","field-day":"Dia","timeFormat-long":"H'h'm'min's's' z","field-month":"Mês","field-year":"Ano","dateFormat-short":"dd/MM/yy","field-zone":"Fuso","months-format-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"quarters-standAlone-narrow":["1","2","3","4"],"dateFormatItem-yQQQ":"yyyy QQQ","dateFormatItem-yMEd":"EEE, dd/MM/yyyy","dateFormatItem-MMMEd":"EEE, d MMM","eraNarrow":["a.C.","d.C."],"dateFormat-long":"d 'de' MMMM 'de' yyyy","months-format-wide":["janeiro","fevereiro","março","abril","maio","junho","julho","agosto","setembro","outubro","novembro","dezembro"],"dateFormat-full":"EEEE, d 'de' MMMM 'de' yyyy","dateFormatItem-Md":"d/M","field-era":"Era","dateFormatItem-yM":"MM/yyyy","months-standAlone-wide":["janeiro","fevereiro","março","abril","maio","junho","julho","agosto","setembro","outubro","novembro","dezembro"],"timeFormat-short":"HH:mm","quarters-format-wide":["1º trimestre","2º trimestre","3º trimestre","4º trimestre"],"dateTimeFormat":"{1} {0}","dateFormatItem-yMMM":"MMM 'de' yyyy","dateFormatItem-yQ":"yyyy Q","dateFormatItem-MMdd":"dd/MM","months-format-abbr":["jan","fev","mar","abr","mai","jun","jul","ago","set","out","nov","dez"],"dateFormatItem-yyQ":"Q yy","am":"AM","months-standAlone-abbr":["jan","fev","mar","abr","mai","jun","jul","ago","set","out","nov","dez"],"quarters-format-abbr":["T1","T2","T3","T4"],"quarters-standAlone-wide":["1º trimestre","2º trimestre","3º trimestre","4º trimestre"],"dateFormatItem-HHmmss":"HH:mm:ss","dateFormatItem-M":"L","days-standAlone-wide":["domingo","segunda-feira","terça-feira","quarta-feira","quinta-feira","sexta-feira","sábado"],"dateFormatItem-yyyyMMM":"MMM 'de' yyyy","dateFormatItem-MMMMd":"d MMMM","dateFormatItem-yyMMMEEEd":"EEE, d 'de' MMM 'de' yy","dateFormatItem-yyMMM":"MMM yy","timeFormat-medium":"HH:mm:ss","dateFormatItem-Hm":"H:mm","quarters-standAlone-abbr":["T1","T2","T3","T4"],"eraAbbr":["a.C.","d.C."],"days-standAlone-abbr":["dom","seg","ter","qua","qui","sex","sáb"],"dateFormatItem-yyMMMd":"d 'de' MMM 'de' yy","dateFormatItem-d":"d","dateFormatItem-ms":"mm:ss","dateFormatItem-MMMd":"d MMM","dateFormatItem-MEd":"EEE, dd/MM","dateFormatItem-yMMMM":"MMMM 'de' yyyy","days-format-wide":["domingo","segunda-feira","terça-feira","quarta-feira","quinta-feira","sexta-feira","sábado"],"dateFormatItem-yyyyMM":"MM/yyyy","dateFormatItem-y":"yyyy","months-standAlone-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"dateFormatItem-yyMM":"MM/yy","days-format-abbr":["dom","seg","ter","qua","qui","sex","sáb"],"eraNames":["Antes de Cristo","Ano do Senhor"],"days-format-narrow":["D","S","T","Q","Q","S","S"],"days-standAlone-narrow":["D","S","T","Q","Q","S","S"],"dateFormatItem-MMM":"LLL","dateFormatItem-HHmm":"HH:mm","pm":"PM","dateFormatItem-MMMMEd":"EEE, d MMMM","dateFormatItem-yMMMEd":"EEE, d 'de' MMM 'de' yyyy","dateFormatItem-mmss":"mm:ss","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","patternChars":"GyMdkHmsSEDFwWahKzYeugAZvcL","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.pt_br");dijit.nls.loading.pt_br={"loadingState":"Carregando...","errorState":"Desculpe, ocorreu um erro"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.pt_br");dijit.nls.common.pt_br={"buttonOk":"OK","buttonCancel":"Cancelar","buttonSave":"Salvar","itemClose":"Fechar"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.pt_br");dijit.form.nls.validate.pt_br={"rangeMessage":"Este valor está fora do intervalo. ","invalidMessage":"O valor inserido não é válido.","missingMessage":"Este valor é necessário."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.pt_br");dojo.cldr.nls.number.pt_br={"group":".","percentSign":"%","exponential":"E","percentFormat":"#,##0%","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":",","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","currencyFormat":"¤#,##0.00;(¤#,##0.00)","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.pt_br");dijit.form.nls.ComboBox.pt_br={"previousMessage":"Opções anteriores","nextMessage":"Mais opções"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_pt-pt.js b/UNGProject/dojo/dojo/nls/refimpldojo_pt-pt.js
new file mode 100644
index 0000000000000000000000000000000000000000..362f70cbc77c1661b9f5dcdfa871e1e64411aade
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_pt-pt.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_pt-pt");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.pt_pt");dojo.cldr.nls.gregorian.pt_pt={"quarters-standAlone-wide":["1.º trimestre","2.º trimestre","3.º trimestre","4.º trimestre"],"quarters-format-abbr":["1.º trimestre","2.º trimestre","3.º trimestre","4.º trimestre"],"dateFormat-medium":"yyyy/MM/dd","dateFormatItem-MMMEd":"E d MMM","quarters-standAlone-abbr":["1.º trimestre","2.º trimestre","3.º trimestre","4.º trimestre"],"pm":"Depois do meio-dia","timeFormat-full":"HH'H'mm'm'ss's' v","dateFormatItem-Md":"d-M","months-standAlone-wide":["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],"eraNames":["a.C.","d.C."],"am":"Antes do meio-dia","dateFormatItem-MMMMEd":"EEE, d 'de' MMMM","dateFormatItem-MMMMd":"d 'de' MMMM","months-standAlone-abbr":["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],"dateFormatItem-yyyyMM":"MM-yyyy","dateFormatItem-yyMM":"MM-yy","dateFormat-short":"yy/MM/dd","months-format-wide":["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],"months-format-abbr":["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],"quarters-format-wide":["1.º trimestre","2.º trimestre","3.º trimestre","4.º trimestre"],"dateFormatItem-MMMd":"d 'de' MMM","months-format-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"Dia da semana","dateFormatItem-yQQQ":"yyyy QQQ","dateFormatItem-yMEd":"EEE, dd/MM/yyyy","eraNarrow":["a.C.","d.C."],"dateFormat-long":"d 'de' MMMM 'de' yyyy","dateFormat-full":"EEEE, d 'de' MMMM 'de' yyyy","field-era":"Era","dateFormatItem-yM":"MM/yyyy","timeFormat-short":"HH:mm","dateTimeFormat":"{1} {0}","timeFormat-long":"HH:mm:ss z","field-year":"Ano","dateFormatItem-yMMM":"MMM 'de' yyyy","dateFormatItem-yQ":"yyyy Q","field-hour":"Hora","dateFormatItem-MMdd":"dd/MM","dateFormatItem-yyQ":"Q yy","dateFormatItem-HHmmss":"HH:mm:ss","dateFormatItem-M":"L","days-standAlone-wide":["domingo","segunda-feira","terça-feira","quarta-feira","quinta-feira","sexta-feira","sábado"],"dateFormatItem-yyyyMMM":"MMM 'de' yyyy","dateFormatItem-yyMMMEEEd":"EEE, d 'de' MMM 'de' yy","dateFormatItem-yyMMM":"MMM yy","timeFormat-medium":"HH:mm:ss","dateFormatItem-Hm":"H:mm","eraAbbr":["a.C.","d.C."],"field-minute":"Minuto","field-dayperiod":"Período do dia","days-standAlone-abbr":["dom","seg","ter","qua","qui","sex","sáb"],"dateFormatItem-yyMMMd":"d 'de' MMM 'de' yy","dateFormatItem-d":"d","dateFormatItem-ms":"mm:ss","dateFormatItem-MEd":"EEE, dd/MM","dateFormatItem-yMMMM":"MMMM 'de' yyyy","field-day":"Dia","days-format-wide":["domingo","segunda-feira","terça-feira","quarta-feira","quinta-feira","sexta-feira","sábado"],"field-zone":"Fuso","dateFormatItem-y":"yyyy","months-standAlone-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"days-format-abbr":["dom","seg","ter","qua","qui","sex","sáb"],"days-format-narrow":["D","S","T","Q","Q","S","S"],"field-month":"Mês","days-standAlone-narrow":["D","S","T","Q","Q","S","S"],"dateFormatItem-MMM":"LLL","dateFormatItem-HHmm":"HH:mm","field-second":"Segundo","dateFormatItem-yMMMEd":"EEE, d 'de' MMM 'de' yyyy","field-week":"Semana","dateFormatItem-mmss":"mm:ss","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","patternChars":"GyMdkHmsSEDFwWahKzYeugAZvcL","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.pt_pt");dijit.nls.loading.pt_pt={"loadingState":"A carregar...","errorState":"Lamentamos, mas ocorreu um erro"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.pt_pt");dijit.nls.common.pt_pt={"buttonOk":"OK","buttonCancel":"Cancelar","buttonSave":"Guardar","itemClose":"Fechar"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.pt_pt");dijit.form.nls.validate.pt_pt={"rangeMessage":"Este valor encontra-se fora do intervalo.","invalidMessage":"O valor introduzido não é válido.","missingMessage":"Este valor é requerido."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.pt_pt");dojo.cldr.nls.number.pt_pt={"currencyFormat":"#,##0.00 ¤","group":" ","percentSign":"%","exponential":"E","percentFormat":"#,##0%","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":",","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.pt_pt");dijit.form.nls.ComboBox.pt_pt={"previousMessage":"Opções anteriores","nextMessage":"Mais opções"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_pt.js b/UNGProject/dojo/dojo/nls/refimpldojo_pt.js
new file mode 100644
index 0000000000000000000000000000000000000000..10ad5f557baee21ce76a6ebfe6f5a2126fbed212
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_pt.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_pt");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.pt");dojo.cldr.nls.gregorian.pt={"months-format-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"Dia da semana","dateFormatItem-yQQQ":"yyyy QQQ","dateFormatItem-yMEd":"EEE, dd/MM/yyyy","dateFormatItem-MMMEd":"EEE, d MMM","eraNarrow":["a.C.","d.C."],"dateFormat-long":"d 'de' MMMM 'de' yyyy","months-format-wide":["janeiro","fevereiro","março","abril","maio","junho","julho","agosto","setembro","outubro","novembro","dezembro"],"dateFormat-full":"EEEE, d 'de' MMMM 'de' yyyy","dateFormatItem-Md":"d/M","field-era":"Era","dateFormatItem-yM":"MM/yyyy","months-standAlone-wide":["janeiro","fevereiro","março","abril","maio","junho","julho","agosto","setembro","outubro","novembro","dezembro"],"timeFormat-short":"HH:mm","quarters-format-wide":["1º trimestre","2º trimestre","3º trimestre","4º trimestre"],"dateTimeFormat":"{1} {0}","timeFormat-long":"HH:mm:ss z","field-year":"Ano","dateFormatItem-yMMM":"MMM 'de' yyyy","dateFormatItem-yQ":"yyyy Q","field-hour":"Hora","dateFormatItem-MMdd":"dd/MM","months-format-abbr":["jan","fev","mar","abr","mai","jun","jul","ago","set","out","nov","dez"],"dateFormatItem-yyQ":"Q yy","timeFormat-full":"HH'h'mm'min'ss's' v","am":"AM","months-standAlone-abbr":["jan","fev","mar","abr","mai","jun","jul","ago","set","out","nov","dez"],"quarters-format-abbr":["T1","T2","T3","T4"],"quarters-standAlone-wide":["1º trimestre","2º trimestre","3º trimestre","4º trimestre"],"dateFormatItem-HHmmss":"HH:mm:ss","dateFormatItem-M":"L","days-standAlone-wide":["domingo","segunda-feira","terça-feira","quarta-feira","quinta-feira","sexta-feira","sábado"],"dateFormatItem-yyyyMMM":"MMM 'de' yyyy","dateFormatItem-MMMMd":"d MMMM","dateFormatItem-yyMMMEEEd":"EEE, d 'de' MMM 'de' yy","dateFormatItem-yyMMM":"MMM yy","timeFormat-medium":"HH:mm:ss","dateFormatItem-Hm":"H:mm","quarters-standAlone-abbr":["T1","T2","T3","T4"],"eraAbbr":["a.C.","d.C."],"field-minute":"Minuto","field-dayperiod":"Período do dia","days-standAlone-abbr":["dom","seg","ter","qua","qui","sex","sáb"],"dateFormatItem-yyMMMd":"d 'de' MMM 'de' yy","dateFormatItem-d":"d","dateFormatItem-ms":"mm:ss","dateFormatItem-MMMd":"d MMM","dateFormatItem-MEd":"EEE, dd/MM","dateFormatItem-yMMMM":"MMMM 'de' yyyy","field-day":"Dia","days-format-wide":["domingo","segunda-feira","terça-feira","quarta-feira","quinta-feira","sexta-feira","sábado"],"field-zone":"Fuso","dateFormatItem-yyyyMM":"MM/yyyy","dateFormatItem-y":"yyyy","months-standAlone-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"dateFormatItem-yyMM":"MM/yy","days-format-abbr":["dom","seg","ter","qua","qui","sex","sáb"],"eraNames":["Antes de Cristo","Ano do Senhor"],"days-format-narrow":["D","S","T","Q","Q","S","S"],"field-month":"Mês","days-standAlone-narrow":["D","S","T","Q","Q","S","S"],"dateFormatItem-MMM":"LLL","dateFormatItem-HHmm":"HH:mm","pm":"PM","dateFormatItem-MMMMEd":"EEE, d MMMM","dateFormat-short":"dd/MM/yy","field-second":"Segundo","dateFormatItem-yMMMEd":"EEE, d 'de' MMM 'de' yyyy","field-week":"Semana","dateFormat-medium":"dd/MM/yyyy","dateFormatItem-mmss":"mm:ss","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","patternChars":"GyMdkHmsSEDFwWahKzYeugAZvcL","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.pt");dijit.nls.loading.pt={"loadingState":"Carregando...","errorState":"Desculpe, ocorreu um erro"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.pt");dijit.nls.common.pt={"buttonOk":"OK","buttonCancel":"Cancelar","buttonSave":"Salvar","itemClose":"Fechar"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.pt");dijit.form.nls.validate.pt={"rangeMessage":"Este valor está fora do intervalo. ","invalidMessage":"O valor inserido não é válido.","missingMessage":"Este valor é necessário."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.pt");dojo.cldr.nls.number.pt={"group":".","percentSign":"%","exponential":"E","percentFormat":"#,##0%","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":",","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","currencyFormat":"¤#,##0.00;(¤#,##0.00)","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.pt");dijit.form.nls.ComboBox.pt={"previousMessage":"Opções anteriores","nextMessage":"Mais opções"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_ru.js b/UNGProject/dojo/dojo/nls/refimpldojo_ru.js
new file mode 100644
index 0000000000000000000000000000000000000000..48d63347f1dfa76603587c274ed36583749f96ad
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_ru.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_ru");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.ru");dojo.cldr.nls.gregorian.ru={"months-format-narrow":["Я","Ф","М","А","М","И","И","А","С","О","Н","Д"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"День недели","dateFormatItem-yQQQ":"yyyy QQQ","dateFormatItem-yMEd":"EEE, yyyy-M-d","dateFormatItem-yyyyLLLL":"LLLL yyyy","dateFormatItem-MMMEd":"E MMM d","eraNarrow":["до н.э.","н.э."],"dateFormat-long":"d MMMM yyyy 'г'.","months-format-wide":["января","февраля","марта","апреля","мая","июня","июля","августа","сентября","октября","ноября","декабря"],"dateFormat-full":"EEEE, d MMMM yyyy 'г'.","dateFormatItem-Md":"d.M","field-era":"Эра","dateFormatItem-yM":"yyyy-M","months-standAlone-wide":["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],"timeFormat-short":"H:mm","quarters-format-wide":["1-й квартал","2-й квартал","3-й квартал","4-й квартал"],"dateTimeFormat":"{1} {0}","timeFormat-long":"H:mm:ss z","field-year":"Год","dateFormatItem-yMMM":"MMM. y","dateFormatItem-yyyyMMMM":"MMMM yyyy","field-hour":"Час","dateFormatItem-MMdd":"dd.MM","months-format-abbr":["янв.","февр.","марта","апр.","мая","июня","июля","авг.","сент.","окт.","нояб.","дек."],"dateFormatItem-yyQ":"Q yy","patternChars":"GanjkHmsSEDFwWxhKzAeugXZvcL","timeFormat-full":"H:mm:ss v","am":"AM","dateFormatItem-H":"H","months-standAlone-abbr":["янв.","февр.","март","апр.","май","июнь","июль","авг.","сент.","окт.","нояб.","дек."],"quarters-format-abbr":["1-й кв.","2-й кв.","3-й кв.","4-й кв."],"quarters-standAlone-wide":["1-й квартал","2-й квартал","3-й квартал","4-й квартал"],"dateFormatItem-HHmmss":"HH:mm:ss","dateFormatItem-M":"L","days-standAlone-wide":["Воскресенье","Понедельник","Вторник","Среда","Четверг","Пятница","Суббота"],"dateFormatItem-MMMMd":"d MMMM","dateFormatItem-yyMMMEEEd":"EEE, d MMM yy","dateFormatItem-yyMMM":"MMM yy","timeFormat-medium":"H:mm:ss","dateFormatItem-Hm":"H:mm","quarters-standAlone-abbr":["1-й кв.","2-й кв.","3-й кв.","4-й кв."],"eraAbbr":["до н.э.","н.э."],"field-minute":"Минута","field-dayperiod":"AM/PM","days-standAlone-abbr":["Вс","Пн","Вт","Ср","Чт","Пт","Сб"],"dateFormatItem-d":"d","dateFormatItem-ms":"mm:ss","dateFormatItem-MMMd":"d MMM","dateFormatItem-MEd":"E, M-d","dateFormatItem-yMMMM":"MMMM y","field-day":"День","days-format-wide":["воскресенье","понедельник","вторник","среда","четверг","пятница","суббота"],"field-zone":"Часовой пояс","dateFormatItem-yyyyMM":"MM.yyyy","dateFormatItem-y":"yyyy","months-standAlone-narrow":["Я","Ф","М","А","М","И","И","А","С","О","Н","Д"],"dateFormatItem-yyMM":"MM.yy","days-format-abbr":["Вс","Пн","Вт","Ср","Чт","Пт","Сб"],"eraNames":["до н.э.","н.э."],"days-format-narrow":["В","П","В","С","Ч","П","С"],"field-month":"Месяц","days-standAlone-narrow":["В","П","В","С","Ч","П","С"],"dateFormatItem-MMM":"LLL","dateFormatItem-HHmm":"HH:mm","pm":"PM","dateFormatItem-MMMMEd":"E MMMM d","dateFormat-short":"dd.MM.yy","field-second":"Секунда","dateFormatItem-yMMMEd":"E, d MMM. y","dateFormatItem-Ed":"E d","field-week":"Неделя","dateFormat-medium":"dd.MM.yyyy","dateFormatItem-mmss":"mm:ss","dateFormatItem-yyyyQQQQ":"QQQQ yyyy 'г'.","dateFormatItem-yyyy":"yyyy","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateFormatItem-yQ":"yyyy Q","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.ru");dijit.nls.loading.ru={"loadingState":"Загрузка...","errorState":"Извините, возникла ошибка"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.ru");dijit.nls.common.ru={"buttonOk":"ОК","buttonCancel":"Отмена","buttonSave":"Сохранить","itemClose":"Закрыть"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.ru");dijit.form.nls.validate.ru={"rangeMessage":"Это значение вне диапазона.","invalidMessage":"Указано недопустимое значение.","missingMessage":"Это обязательное значение."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.ru");dojo.cldr.nls.number.ru={"group":" ","percentSign":"%","exponential":"E","percentFormat":"#,##0 %","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":",","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","currencyFormat":"#,##0.00 ¤","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","nan":"NaN","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.ru");dijit.form.nls.ComboBox.ru={"previousMessage":"Предыдущие варианты","nextMessage":"Следующие варианты"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_sk.js b/UNGProject/dojo/dojo/nls/refimpldojo_sk.js
new file mode 100644
index 0000000000000000000000000000000000000000..76d40a050e9e4c58110efa3b9ca7e9f60ecb526e
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_sk.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_sk");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.sk");dojo.cldr.nls.gregorian.sk={"field-minute":"minúta","eraNames":["pred n.l.","n.l."],"field-weekday":"deň v týždni","days-standAlone-wide":["Nedeľa","Pondelok","Utorok","Streda","Štvrtok","Piatok","Sobota"],"patternChars":"GanjkHmsSEDFwWxhKzAeugXZvcL","months-standAlone-narrow":["j","f","m","a","m","j","j","a","s","o","n","d"],"field-era":"éra","field-hour":"hodina","quarters-standAlone-abbr":["1. štvrťrok","2. štvrťrok","3. štvrťrok","4. štvrťrok"],"timeFormat-full":"H:mm:ss v","months-standAlone-abbr":["jan","feb","mar","apr","máj","jún","júl","aug","sep","okt","nov","dec"],"days-standAlone-narrow":["N","P","U","S","Š","P","S"],"eraAbbr":["pred n.l.","n.l."],"dateFormat-long":"d. MMMM yyyy","timeFormat-medium":"H:mm:ss","field-zone":"zóna","dateFormat-medium":"d.M.yyyy","quarters-standAlone-wide":["1. štvrťrok","2. štvrťrok","3. štvrťrok","4. štvrťrok"],"field-year":"rok","months-standAlone-wide":["január","február","marec","apríl","máj","jún","júl","august","september","október","november","december"],"field-week":"týždeň","timeFormat-long":"H:mm:ss z","months-format-abbr":["jan","feb","mar","apr","máj","jún","júl","aug","sep","okt","nov","dec"],"timeFormat-short":"H:mm","field-month":"mesiac","quarters-format-abbr":["1. štvrťrok","2. štvrťrok","3. štvrťrok","4. štvrťrok"],"days-format-abbr":["Ne","Po","Ut","St","Št","Pi","So"],"days-format-narrow":["N","P","U","S","Š","P","S"],"field-second":"sekunda","field-day":"deň","months-format-narrow":["j","f","m","a","m","j","j","a","s","o","n","d"],"days-standAlone-abbr":["Ne","Po","Ut","St","Št","Pi","So"],"dateFormat-short":"d.M.yyyy","dateFormat-full":"EEEE, d. MMMM yyyy","months-format-wide":["január","február","marec","apríl","máj","jún","júl","august","september","október","november","december"],"quarters-format-wide":["1. štvrťrok","2. štvrťrok","3. štvrťrok","4. štvrťrok"],"days-format-wide":["Nedeľa","Pondelok","Utorok","Streda","Štvrtok","Piatok","Sobota"],"eraNarrow":["pred n.l.","n.l."],"quarters-standAlone-narrow":["1","2","3","4"],"dateFormatItem-yQQQ":"yyyy QQQ","dateFormatItem-yMEd":"EEE, yyyy-M-d","dateFormatItem-MMMEd":"E MMM d","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateFormatItem-Md":"M-d","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateFormatItem-yM":"yyyy-M","dateTimeFormat":"{1} {0}","dateFormatItem-yMMM":"yyyy MMM","dateFormatItem-yQ":"yyyy Q","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","am":"AM","dateFormatItem-M":"L","dateFormatItem-MMMMd":"MMMM d","dateFormatItem-Hm":"H:mm","field-dayperiod":"Dayperiod","dateFormatItem-d":"d","dateFormatItem-ms":"mm:ss","quarters-format-narrow":["1","2","3","4"],"dateFormatItem-MMMd":"MMM d","dateFormatItem-MEd":"E, M-d","dateFormatItem-yMMMM":"yyyy MMMM","dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateFormatItem-y":"yyyy","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateFormatItem-MMM":"LLL","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","pm":"PM","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateFormatItem-MMMMEd":"E MMMM d","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateFormatItem-yMMMEd":"EEE, yyyy MMM d","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.sk");dijit.nls.loading.sk={"loadingState":"Zavádzanie...","errorState":"Nastala chyba"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.sk");dijit.nls.common.sk={"buttonOk":"OK","buttonCancel":"Zrušiť","buttonSave":"Uložiť","itemClose":"Zatvoriť"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.sk");dijit.form.nls.validate.sk={"rangeMessage":"Táto hodnota je mimo rozsah.","invalidMessage":"Zadaná hodnota nie je platná.","missingMessage":"Táto hodnota je vyžadovaná."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.sk");dojo.cldr.nls.number.sk={"currencyFormat":"#,##0.00 ¤","group":" ","decimal":",","scientificFormat":"#E0","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","infinity":"∞","list":";","percentSign":"%","minusSign":"-","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","nan":"NaN","nativeZeroDigit":"0","plusSign":"+","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","perMille":"‰","percentFormat":"#,##0%","decimalFormat":"#,##0.###","patternDigit":"#","currencySpacing-beforeCurrency-insertBetween":" ","exponential":"E"};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.sk");dijit.form.nls.ComboBox.sk={"previousMessage":"Predchádzajúce voľby","nextMessage":"Ďalšie voľby"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_sl.js b/UNGProject/dojo/dojo/nls/refimpldojo_sl.js
new file mode 100644
index 0000000000000000000000000000000000000000..c9b97ca44dcc28b959cf76acce76e56d95b959d2
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_sl.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_sl");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.sl");dojo.cldr.nls.gregorian.sl={"dateFormat-medium":"d.M.yyyy","eraNarrow":["pr.n.š.","po Kr."],"months-format-narrow":["j","f","m","a","m","j","j","a","s","o","n","d"],"timeFormat-full":"H:mm:ss v","months-standAlone-narrow":["j","f","m","a","m","j","j","a","s","o","n","d"],"months-standAlone-wide":["januar","februar","marec","april","maj","junij","julij","avgust","september","oktober","november","december"],"eraNames":["pr.n.š.","po Kr."],"days-standAlone-narrow":["n","p","t","s","č","p","s"],"dateFormatItem-MMMMd":"d MMMM","months-standAlone-abbr":["jan","feb","mar","apr","maj","jun","jul","avg","sep","okt","nov","dec"],"timeFormat-medium":"H:mm:ss","dateFormat-long":"dd. MMMM yyyy","dateFormat-short":"d.M.yy","months-format-wide":["januar","februar","marec","april","maj","junij","julij","avgust","september","oktober","november","december"],"days-standAlone-wide":["nedelja","ponedeljek","torek","sreda","četrtek","petek","sobota"],"days-format-narrow":["n","p","t","s","č","p","s"],"timeFormat-short":"H:mm","months-format-abbr":["jan","feb","mar","apr","maj","jun","jul","avg","sep","okt","nov","dec"],"days-standAlone-abbr":["ned","pon","tor","sre","čet","pet","sob"],"days-format-wide":["nedelja","ponedeljek","torek","sreda","četrtek","petek","sobota"],"timeFormat-long":"H:mm:ss z","eraAbbr":["pr.n.š.","po Kr."],"patternChars":"GanjkHmsSEDFwWxhKzAeugXZvcL","dateFormat-full":"EEEE, dd. MMMM yyyy","days-format-abbr":["ned","pon","tor","sre","čet","pet","sob"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"Day of the Week","dateFormatItem-yQQQ":"yyyy QQQ","dateFormatItem-yMEd":"EEE, yyyy-M-d","dateFormatItem-MMMEd":"E MMM d","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateFormatItem-Md":"M-d","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","field-era":"Era","dateFormatItem-yM":"yyyy-M","quarters-format-wide":["Q1","Q2","Q3","Q4"],"dateTimeFormat":"{1} {0}","field-year":"Year","dateFormatItem-yMMM":"yyyy MMM","dateFormatItem-yQ":"yyyy Q","dateTimeFormats-appendItem-Era":"{0} {1}","field-hour":"Hour","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","am":"AM","quarters-format-abbr":["Q1","Q2","Q3","Q4"],"quarters-standAlone-wide":["Q1","Q2","Q3","Q4"],"dateFormatItem-M":"L","dateFormatItem-Hm":"H:mm","quarters-standAlone-abbr":["Q1","Q2","Q3","Q4"],"field-minute":"Minute","field-dayperiod":"Dayperiod","dateFormatItem-d":"d","dateFormatItem-ms":"mm:ss","quarters-format-narrow":["1","2","3","4"],"dateFormatItem-MMMd":"MMM d","dateFormatItem-MEd":"E, M-d","dateFormatItem-yMMMM":"yyyy MMMM","field-day":"Day","field-zone":"Zone","dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateFormatItem-y":"yyyy","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","field-month":"Month","dateFormatItem-MMM":"LLL","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","pm":"PM","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateFormatItem-MMMMEd":"E MMMM d","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","field-second":"Second","dateFormatItem-yMMMEd":"EEE, yyyy MMM d","dateTimeFormats-appendItem-Timezone":"{0} {1}","field-week":"Week"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.sl");dijit.nls.loading.sl={"loadingState":"Nalaganje...","errorState":"Oprostite, prišlo je do napake."};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.sl");dijit.nls.common.sl={"buttonOk":"V redu","buttonCancel":"Prekliči","buttonSave":"Shrani","itemClose":"Zapri"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.sl");dijit.form.nls.validate.sl={"rangeMessage":"Ta vrednost je zunaj obsega. ","invalidMessage":"Vnesena vrednost ni veljavna.","missingMessage":"Ta vrednost je zahtevana."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.sl");dojo.cldr.nls.number.sl={"group":".","percentSign":"%","exponential":"E","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":",","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","plusSign":"+","scientificFormat":"#E0","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencyFormat":"¤ #,##0.00","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","percentFormat":"#,##0%","decimalFormat":"#,##0.###","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.sl");dijit.form.nls.ComboBox.sl={"previousMessage":"Prejšnje možnosti","nextMessage":"Dodatne možnosti"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_sv.js b/UNGProject/dojo/dojo/nls/refimpldojo_sv.js
new file mode 100644
index 0000000000000000000000000000000000000000..17d7c4ddc620c887d57be5daa69519ace9a7b9f3
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_sv.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_sv");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.sv");dojo.cldr.nls.gregorian.sv={"months-format-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"veckodag","dateFormatItem-yQQQ":"yyyy QQQ","dateFormatItem-yMEd":"EEE, yyyy-MM-dd","dateFormatItem-MMMEd":"E d MMM","eraNarrow":["f.Kr.","e.Kr."],"dateFormat-long":"d MMMM yyyy","months-format-wide":["januari","februari","mars","april","maj","juni","juli","augusti","september","oktober","november","december"],"dateFormat-full":"EEEE 'den' d MMMM yyyy","dateFormatItem-Md":"d/M","dateFormatItem-MMMMEEEd":"EEE d MMMM","field-era":"era","dateFormatItem-yM":"yyyy-MM","months-standAlone-wide":["januari","februari","mars","april","maj","juni","juli","augusti","september","oktober","november","december"],"timeFormat-short":"HH.mm","quarters-format-wide":["1:a kvartalet","2:a kvartalet","3:e kvartalet","4:e kvartalet"],"dateTimeFormat":"{1} {0}","timeFormat-long":"HH.mm.ss z","field-year":"år","dateFormatItem-yMMM":"yyyy MMM","dateFormatItem-yQ":"yyyy Q","field-hour":"timme","dateFormatItem-MMdd":"dd/MM","months-format-abbr":["jan","feb","mar","apr","maj","jun","jul","aug","sep","okt","nov","dec"],"dateFormatItem-yyQ":"Q yy","timeFormat-full":"'kl'. HH.mm.ss v","am":"fm","months-standAlone-abbr":["jan","feb","mar","apr","maj","jun","jul","aug","sep","okt","nov","dec"],"quarters-format-abbr":["K1","K2","K3","K4"],"quarters-standAlone-wide":["1:a kvartalet","2:a kvartalet","3:e kvartalet","4:e kvartalet"],"dateFormatItem-HHmmss":"HH.mm.ss","dateFormatItem-hhmmss":"HH:mm:ss","dateFormatItem-M":"L","days-standAlone-wide":["söndag","måndag","tisdag","onsdag","torsdag","fredag","lördag"],"dateFormatItem-yyyyMMM":"MMM yyyy","dateFormatItem-MMMMd":"d MMMM","dateFormatItem-yyMMM":"MMM -yy","timeFormat-medium":"HH.mm.ss","dateFormatItem-Hm":"H.mm","quarters-standAlone-abbr":["K1","K2","K3","K4"],"eraAbbr":["f.Kr.","e.Kr."],"field-minute":"minut","field-dayperiod":"tidsvisning","days-standAlone-abbr":["sön","mån","tis","ons","tors","fre","lör"],"dateFormatItem-d":"d","dateFormatItem-ms":"mm.ss","dateFormatItem-MMMd":"d MMM","dateFormatItem-MEd":"E d/M","dateFormatItem-yMMMM":"yyyy MMMM","field-day":"dag","days-format-wide":["söndag","måndag","tisdag","onsdag","torsdag","fredag","lördag"],"field-zone":"tidszon","dateFormatItem-yyyyMM":"yyyy-MM","dateFormatItem-y":"yyyy","months-standAlone-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"dateFormatItem-yyMM":"yy-MM","days-format-abbr":["sön","mån","tis","ons","tors","fre","lör"],"eraNames":["före Kristus","efter Kristus"],"days-format-narrow":["S","M","T","O","T","F","L"],"field-month":"månad","days-standAlone-narrow":["S","M","T","O","T","F","L"],"dateFormatItem-MMM":"LLL","dateFormatItem-HHmm":"HH.mm","pm":"em","dateFormatItem-MMMMEd":"E d MMMM","dateFormat-short":"yyyy-MM-dd","dateFormatItem-MMd":"d/M","field-second":"sekund","dateFormatItem-yMMMEd":"EEE d MMM yyyy","dateFormatItem-hhmm":"hh.mm","field-week":"vecka","dateFormat-medium":"d MMM yyyy","dateFormatItem-mmss":"mm.ss","dateFormatItem-yyyyQQQQ":"QQQQ yyyy","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","patternChars":"GyMdkHmsSEDFwWahKzYeugAZvcL","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.sv");dijit.nls.loading.sv={"loadingState":"Läser in...","errorState":"Det uppstod ett fel."};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.sv");dijit.nls.common.sv={"buttonOk":"OK","buttonCancel":"Avbryt","buttonSave":"Spara","itemClose":"Stäng"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.sv");dijit.form.nls.validate.sv={"rangeMessage":"Värdet är utanför intervallet.","invalidMessage":"Det angivna värdet är ogiltigt.","missingMessage":"Värdet är obligatoriskt."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.sv");dojo.cldr.nls.number.sv={"group":" ","percentSign":"%","exponential":"×10^","percentFormat":"#,##0 %","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"−","decimal":",","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","currencyFormat":"#,##0.00 ¤","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","nan":"NaN","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.sv");dijit.form.nls.ComboBox.sv={"previousMessage":"Föregående alternativ","nextMessage":"Fler alternativ"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_th.js b/UNGProject/dojo/dojo/nls/refimpldojo_th.js
new file mode 100644
index 0000000000000000000000000000000000000000..16191d1984ecea4e1370fe13e4da643b1d033397
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_th.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_th");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.th");dojo.cldr.nls.gregorian.th={"dateFormatItem-yM":"M/yyyy","field-dayperiod":"ช่วงวัน","dateFormatItem-yQ":"Q yyyy","field-minute":"นาที","eraNames":["ปีก่อนคริสต์ศักราชที่","คริสต์ศักราช"],"dateFormatItem-MMMEd":"E d MMM","field-weekday":"วันในสัปดาห์","dateFormatItem-yQQQ":"QQQ yyyy","days-standAlone-wide":["วันอาทิตย์","วันจันทร์","วันอังคาร","วันพุธ","วันพฤหัสบดี","วันศุกร์","วันเสาร์"],"dateFormatItem-MMM":"LLL","patternChars":"GanjkHmsSEDFwWxhKzAeugXZvcL","months-standAlone-narrow":["ม.ค.","ก.พ.","มี.ค.","เม.ย.","พ.ค.","มิ.ย.","ก.ค.","ส.ค.","ก.ย.","ต.ค.","พ.ย.","ธ.ค."],"field-era":"สมัย","field-hour":"ชั่วโมง","dateFormatItem-y":"yyyy","timeFormat-full":"H นาฬิกา m นาที ss วินาที v","months-standAlone-abbr":["ม.ค.","ก.พ.","มี.ค.","เม.ย.","พ.ค.","มิ.ย.","ก.ค.","ส.ค.","ก.ย.","ต.ค.","พ.ย.","ธ.ค."],"dateFormatItem-yMMM":"MMM yyyy","days-standAlone-narrow":["อ","จ","อ","พ","พ","ศ","ส"],"eraAbbr":["ปีก่อน ค.ศ. ที่","ค.ศ."],"dateFormatItem-yyyyMMMM":"MMMM yyyy","dateFormat-long":"d MMMM yyyy","timeFormat-medium":"H:mm:ss","field-zone":"เขต","dateFormatItem-Hm":"H:mm","dateFormat-medium":"d MMM yyyy","quarters-standAlone-wide":["ไตรมาส 1","ไตรมาส 2","ไตรมาส 3","ไตรมาส 4"],"dateTimeFormat":"{1}, {0}","dateFormatItem-yMMMM":"MMMM yyyy","dateFormatItem-ms":"mm:ss","field-year":"ปี","quarters-standAlone-narrow":["1","2","3","4"],"dateFormatItem-HHmmss":"HH:mm:ss","months-standAlone-wide":["มกราคม","กุมภาพันธ์","มีนาคม","เมษายน","พฤษภาคม","มิถุนายน","กรกฎาคม","สิงหาคม","กันยายน","ตุลาคม","พฤศจิกายน","ธันวาคม"],"field-week":"สัปดาห์","dateFormatItem-MMMMEd":"E d MMMM","dateFormatItem-MMMd":"d MMM","dateFormatItem-HHmm":"HH:mm","dateFormatItem-yyQ":"Q yy","timeFormat-long":"H นาฬิกา m นาที ss วินาที z","months-format-abbr":["ม.ค.","ก.พ.","มี.ค.","เม.ย.","พ.ค.","มิ.ย.","ก.ค.","ส.ค.","ก.ย.","ต.ค.","พ.ย.","ธ.ค."],"timeFormat-short":"H:mm","field-month":"เดือน","dateFormatItem-MMMMd":"d MMMM","quarters-format-abbr":["Q1","Q2","Q3","Q4"],"days-format-abbr":["อา.","จ.","อ.","พ.","พฤ.","ศ.","ส."],"pm":"หลังเที่ยง","days-format-narrow":["อ","จ","อ","พ","พฤ","ศ","ส"],"dateFormatItem-M":"L","dateFormatItem-mmss":"mm:ss","field-second":"วินาที","field-day":"วัน","dateFormatItem-MEd":"E, d-M","months-format-narrow":["ม.ค.","ก.พ.","มี.ค.","เม.ย.","พ.ค.","มิ.ย.","ก.ค.","ส.ค.","ก.ย.","ต.ค.","พ.ย.","ธ.ค."],"am":"ก่อนเที่ยง","days-standAlone-abbr":["อา.","จ.","อ.","พ.","พฤ.","ศ.","ส."],"dateFormat-short":"d/M/yyyy","dateFormatItem-yyyyM":"M/yyyy","dateFormatItem-yMMMEd":"EEE d MMM yyyy","dateFormat-full":"EEEEที่ d MMMM G yyyy","dateFormatItem-Md":"d/M","dateFormatItem-yMEd":"EEE d/M/yyyy","months-format-wide":["มกราคม","กุมภาพันธ์","มีนาคม","เมษายน","พฤษภาคม","มิถุนายน","กรกฎาคม","สิงหาคม","กันยายน","ตุลาคม","พฤศจิกายน","ธันวาคม"],"dateFormatItem-d":"d","quarters-format-wide":["ไตรมาส 1","ไตรมาส 2","ไตรมาส 3","ไตรมาส 4"],"days-format-wide":["วันอาทิตย์","วันจันทร์","วันอังคาร","วันพุธ","วันพฤหัสบดี","วันศุกร์","วันเสาร์"],"eraNarrow":["ปีก่อน ค.ศ. ที่","ค.ศ."],"dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-standAlone-abbr":["Q1","Q2","Q3","Q4"],"quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.th");dijit.nls.loading.th={"loadingState":"กำลังโหลด...","errorState":"ขออภัย เกิดข้อผิดพลาด"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.th");dijit.nls.common.th={"buttonOk":"ตกลง","buttonCancel":"ยกเลิก","buttonSave":"บันทึก","itemClose":"ปิด"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.th");dijit.form.nls.validate.th={"rangeMessage":"ค่านี้เกินช่วง","invalidMessage":"ค่าที่ป้อนไม่ถูกต้อง","missingMessage":"จำเป็นต้องมีค่านี้"};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.th");dojo.cldr.nls.number.th={"group":",","percentSign":"%","exponential":"E","percentFormat":"#,##0%","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":".","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","currencyFormat":"¤#,##0.00;¤-#,##0.00","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.th");dijit.form.nls.ComboBox.th={"previousMessage":"การเลือกก่อนหน้า","nextMessage":"การเลือกเพิ่มเติม"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_tr.js b/UNGProject/dojo/dojo/nls/refimpldojo_tr.js
new file mode 100644
index 0000000000000000000000000000000000000000..b92933af7e3b56013650cd6e90746392488970df
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_tr.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_tr");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.tr");dojo.cldr.nls.gregorian.tr={"dateFormatItem-yM":"M/yyyy","field-dayperiod":"AM/PM","dateFormatItem-yQ":"Q yyyy","field-minute":"Dakika","eraNames":["Milattan Önce","Milattan Sonra"],"dateFormatItem-MMMEd":"d MMM E","field-weekday":"Haftanın Günü","dateFormatItem-yQQQ":"QQQ yyyy","days-standAlone-wide":["Pazar","Pazartesi","Salı","Çarşamba","Perşembe","Cuma","Cumartesi"],"dateFormatItem-MMM":"LLL","patternChars":"GanjkHmsSEDFwWxhKzAeugXZvcL","months-standAlone-narrow":["O","Ş","M","N","M","H","T","A","E","E","K","A"],"field-era":"Miladi Dönem","field-hour":"Saat","quarters-standAlone-abbr":["Ç1","Ç2","Ç3","Ç4"],"dateFormatItem-y":"yyyy","timeFormat-full":"HH:mm:ss v","dateFormatItem-yyyy":"yyyy","months-standAlone-abbr":["Oca","Şub","Mar","Nis","May","Haz","Tem","Ağu","Eyl","Eki","Kas","Ara"],"dateFormatItem-Ed":"d E","dateFormatItem-yMMM":"MMM yyyy","days-standAlone-narrow":["P","P","S","Ç","P","C","C"],"eraAbbr":["MÖ","MS"],"dateFormat-long":"d MMMM yyyy","timeFormat-medium":"HH:mm:ss","field-zone":"Saat Dilimi","dateFormatItem-Hm":"HH:mm","dateFormatItem-yyMM":"MM/yy","dateFormat-medium":"dd.MMM.yyyy","dateFormatItem-yyMMM":"MMM yy","quarters-standAlone-wide":["1. çeyrek","2. çeyrek","3. çeyrek","4. çeyrek"],"dateTimeFormat":"{1} {0}","dateFormatItem-yMMMM":"MMMM yyyy","dateFormatItem-ms":"mm:ss","field-year":"Yıl","quarters-standAlone-narrow":["1","2","3","4"],"dateFormatItem-HHmmss":"HH:mm:ss","field-week":"Hafta","months-standAlone-wide":["Ocak","Şubat","Mart","Nisan","Mayıs","Haziran","Temmuz","Ağustos","Eylül","Ekim","Kasım","Aralık"],"dateFormatItem-MMMMEd":"d MMMM E","dateFormatItem-MMMd":"d MMM","dateFormatItem-HHmm":"HH:mm","dateFormatItem-yyQ":"Q yy","timeFormat-long":"HH:mm:ss z","months-format-abbr":["Oca","Şub","Mar","Nis","May","Haz","Tem","Ağu","Eyl","Eki","Kas","Ara"],"timeFormat-short":"HH:mm","dateFormatItem-H":"H","field-month":"Ay","dateFormatItem-MMMMd":"d MMMM","quarters-format-abbr":["Ç1","Ç2","Ç3","Ç4"],"days-format-abbr":["Paz","Pzt","Sal","Çar","Per","Cum","Cmt"],"pm":"PM","dateFormatItem-M":"L","dateFormatItem-mmss":"mm:ss","days-format-narrow":["P","P","S","Ç","P","C","C"],"field-second":"Saniye","field-day":"Gün","dateFormatItem-MEd":"d-M E","months-format-narrow":["O","Ş","M","N","M","H","T","A","E","E","K","A"],"am":"AM","days-standAlone-abbr":["Paz","Pzt","Sal","Çar","Per","Cum","Cmt"],"dateFormat-short":"dd.MM.yyyy","dateFormatItem-yMMMEd":"d MMM yyyy EEE","dateFormat-full":"dd MMMM yyyy EEEE","dateFormatItem-Md":"d/M","dateFormatItem-yMEd":"d/M/yyyy EEE","months-format-wide":["Ocak","Şubat","Mart","Nisan","Mayıs","Haziran","Temmuz","Ağustos","Eylül","Ekim","Kasım","Aralık"],"dateFormatItem-d":"d","quarters-format-wide":["1. çeyrek","2. çeyrek","3. çeyrek","4. çeyrek"],"days-format-wide":["Pazar","Pazartesi","Salı","Çarşamba","Perşembe","Cuma","Cumartesi"],"eraNarrow":["MÖ","MS"],"dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.tr");dijit.nls.loading.tr={"loadingState":"Yükleniyor...","errorState":"Üzgünüz, bir hata oluştu"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.tr");dijit.nls.common.tr={"buttonOk":"Tamam","buttonCancel":"İptal","buttonSave":"Kaydet","itemClose":"Kapat"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.tr");dijit.form.nls.validate.tr={"rangeMessage":"Bu değer aralık dışında.","invalidMessage":"Girilen değer geçersiz.","missingMessage":"Bu değer gerekli."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.tr");dojo.cldr.nls.number.tr={"group":".","percentSign":"%","exponential":"E","percentFormat":"% #,##0","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":",","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","currencyFormat":"#,##0.00 ¤","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-insertBetween":" "};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.tr");dijit.form.nls.ComboBox.tr={"previousMessage":"Önceki seçenekler","nextMessage":"Diğer seçenekler"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_xx.js b/UNGProject/dojo/dojo/nls/refimpldojo_xx.js
new file mode 100644
index 0000000000000000000000000000000000000000..21bc1b8454b75ea01578ae9b11aa201cc824820a
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_xx.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_xx");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.xx");dojo.cldr.nls.gregorian.xx={"months-format-narrow":["1","2","3","4","5","6","7","8","9","10","11","12"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"Day of the Week","dateFormatItem-yQQQ":"yyyy QQQ","dateFormatItem-yMEd":"EEE, yyyy-M-d","dateFormatItem-MMMEd":"E MMM d","eraNarrow":["BCE","CE"],"dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateFormat-long":"yyyy MMMM d","months-format-wide":["1","2","3","4","5","6","7","8","9","10","11","12"],"dateFormat-full":"EEEE, yyyy MMMM dd","dateFormatItem-Md":"M-d","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","field-era":"Era","dateFormatItem-yM":"yyyy-M","months-standAlone-wide":["1","2","3","4","5","6","7","8","9","10","11","12"],"timeFormat-short":"HH:mm","quarters-format-wide":["Q1","Q2","Q3","Q4"],"dateTimeFormat":"{1} {0}","timeFormat-long":"HH:mm:ss z","field-year":"Year","dateFormatItem-yMMM":"yyyy MMM","dateFormatItem-yQ":"yyyy Q","dateTimeFormats-appendItem-Era":"{0} {1}","field-hour":"Hour","months-format-abbr":["1","2","3","4","5","6","7","8","9","10","11","12"],"patternChars":"GyMdkHmsSEDFwWahKzYeugAZvcL","timeFormat-full":"HH:mm:ss v","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","am":"AM","months-standAlone-abbr":["1","2","3","4","5","6","7","8","9","10","11","12"],"quarters-format-abbr":["Q1","Q2","Q3","Q4"],"quarters-standAlone-wide":["Q1","Q2","Q3","Q4"],"dateFormatItem-M":"L","days-standAlone-wide":["1","2","3","4","5","6","7"],"dateFormatItem-MMMMd":"MMMM d","timeFormat-medium":"HH:mm:ss","dateFormatItem-Hm":"H:mm","quarters-standAlone-abbr":["Q1","Q2","Q3","Q4"],"eraAbbr":["BCE","CE"],"field-minute":"Minute","field-dayperiod":"Dayperiod","days-standAlone-abbr":["1","2","3","4","5","6","7"],"dateFormatItem-d":"d","dateFormatItem-ms":"mm:ss","quarters-format-narrow":["1","2","3","4"],"dateFormatItem-MMMd":"MMM d","dateFormatItem-MEd":"E, M-d","dateFormatItem-yMMMM":"yyyy MMMM","field-day":"Day","days-format-wide":["1","2","3","4","5","6","7"],"field-zone":"Zone","dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateFormatItem-y":"yyyy","months-standAlone-narrow":["1","2","3","4","5","6","7","8","9","10","11","12"],"dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","days-format-abbr":["1","2","3","4","5","6","7"],"eraNames":["BCE","CE"],"days-format-narrow":["1","2","3","4","5","6","7"],"field-month":"Month","days-standAlone-narrow":["1","2","3","4","5","6","7"],"dateFormatItem-MMM":"LLL","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","pm":"PM","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateFormatItem-MMMMEd":"E MMMM d","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateFormat-short":"yyyy-MM-dd","field-second":"Second","dateFormatItem-yMMMEd":"EEE, yyyy MMM d","dateTimeFormats-appendItem-Timezone":"{0} {1}","field-week":"Week","dateFormat-medium":"yyyy MMM d"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.xx");dijit.nls.loading.xx={"loadingState":"Loading...","errorState":"Sorry, an error occurred"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.xx");dijit.nls.common.xx={"buttonOk":"OK","buttonCancel":"Cancel","buttonSave":"Save","itemClose":"Close"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.xx");dijit.form.nls.validate.xx={"rangeMessage":"This value is out of range.","invalidMessage":"The value entered is not valid.","missingMessage":"This value is required."};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.xx");dojo.cldr.nls.number.xx={"scientificFormat":"#E0","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","infinity":"∞","list":";","percentSign":"%","minusSign":"-","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","nan":"NaN","nativeZeroDigit":"0","plusSign":"+","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencyFormat":"¤ #,##0.00","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","perMille":"‰","group":",","percentFormat":"#,##0%","decimalFormat":"#,##0.###","decimal":".","patternDigit":"#","currencySpacing-beforeCurrency-insertBetween":" ","exponential":"E"};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.xx");dijit.form.nls.ComboBox.xx={"previousMessage":"Previous choices","nextMessage":"More choices"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_zh-cn.js b/UNGProject/dojo/dojo/nls/refimpldojo_zh-cn.js
new file mode 100644
index 0000000000000000000000000000000000000000..1489c45e2abaae5a9289b5ea599f097a2e717cbc
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_zh-cn.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_zh-cn");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.zh_cn");dojo.cldr.nls.gregorian.zh_cn={"dateFormat-short":"yy-M-d","timeFormat-long":"ahh'时'mm'分'ss'秒'","dateFormat-medium":"yyyy-M-d","dateFormat-long":"yyyy'年'M'月'd'日'","timeFormat-medium":"ahh:mm:ss","timeFormat-short":"ah:mm","timeFormat-full":"ahh'时'mm'分'ss'秒' z","dateFormat-full":"yyyy'年'M'月'd'日'EEEE","months-format-narrow":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"周天","dateFormatItem-yQQQ":"y年QQQ","dateFormatItem-yMEd":"yyyy年M月d日,E","dateFormatItem-MMMEd":"MMMd日E","eraNarrow":["公元前","公元"],"months-format-wide":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"dateFormatItem-Md":"M-d","field-era":"时期","dateFormatItem-yM":"yyyy-M","months-standAlone-wide":["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],"quarters-format-wide":["第1季度","第2季度","第3季度","第4季度"],"dateTimeFormat":"{1} {0}","field-year":"年","dateFormatItem-yMMM":"yyyy年MMM","dateFormatItem-yQ":"yyyy年QQQ","dateFormatItem-yyyyMMMM":"yyyy年MMMM","field-hour":"小时","dateFormatItem-MMdd":"MM-dd","months-format-abbr":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"dateFormatItem-yyQ":"yy年第Q季度","patternChars":"GanjkHmsSEDFwWxhKzAeugXZvcL","am":"上午","dateFormatItem-H":"H时","months-standAlone-abbr":["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],"quarters-format-abbr":["1季","2季","3季","4季"],"quarters-standAlone-wide":["第1季度","第2季度","第3季度","第4季度"],"dateFormatItem-HHmmss":"HH:mm:ss","dateFormatItem-M":"L","days-standAlone-wide":["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],"dateFormatItem-MMMMd":"MMMMd日","dateFormatItem-yyMMM":"yy年MMM","dateFormatItem-Hm":"H:mm","quarters-standAlone-abbr":["1季","2季","3季","4季"],"eraAbbr":["公元前","公元"],"field-minute":"分钟","field-dayperiod":"上午/下午","days-standAlone-abbr":["周日","周一","周二","周三","周四","周五","周六"],"dateFormatItem-d":"d日","dateFormatItem-ms":"mm:ss","dateFormatItem-MMMd":"MMMd日","dateFormatItem-MEd":"M-dE","dateFormatItem-yMMMM":"yyyy年MMMM","field-day":"日","days-format-wide":["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],"field-zone":"区域","dateFormatItem-y":"yyyy年","months-standAlone-narrow":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"dateFormatItem-yyMM":"yy-MM","days-format-abbr":["周日","周一","周二","周三","周四","周五","周六"],"eraNames":["公元前","公元"],"days-format-narrow":["日","一","二","三","四","五","六"],"field-month":"月","days-standAlone-narrow":["日","一","二","三","四","五","六"],"dateFormatItem-MMM":"LLL","dateFormatItem-HHmm":"HH:mm","pm":"下午","dateFormatItem-MMMMEd":"MMMMd日E","dateFormatItem-MMMMdd":"MMMMdd日","field-second":"秒钟","dateFormatItem-yMMMEd":"yyyy年MMMd日EEE","dateFormatItem-Ed":"d日E","field-week":"周","dateFormatItem-yyyyM":"yyyy年M月","dateFormatItem-mmss":"mm:ss","dateFormatItem-yyyy":"yyyy年","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.zh_cn");dijit.nls.loading.zh_cn={"loadingState":"正在加载...","errorState":"对不起,发生了错误"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.zh_cn");dijit.nls.common.zh_cn={"buttonOk":"确定","buttonCancel":"取消","buttonSave":"保存","itemClose":"关闭"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.zh_cn");dijit.form.nls.validate.zh_cn={"rangeMessage":"此值超出范围。","invalidMessage":"输入的值无效。","missingMessage":"此值是必需值。"};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.zh_cn");dojo.cldr.nls.number.zh_cn={"currencyFormat":"¤#,##0.00","decimalFormat":"#,##0.###","group":",","scientificFormat":"#E0","percentFormat":"#,##0%","decimal":".","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","infinity":"∞","list":";","percentSign":"%","minusSign":"-","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","nan":"NaN","nativeZeroDigit":"0","plusSign":"+","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","perMille":"‰","patternDigit":"#","currencySpacing-beforeCurrency-insertBetween":" ","exponential":"E"};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.zh_cn");dijit.form.nls.ComboBox.zh_cn={"previousMessage":"先前选项","nextMessage":"更多选项"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_zh-tw.js b/UNGProject/dojo/dojo/nls/refimpldojo_zh-tw.js
new file mode 100644
index 0000000000000000000000000000000000000000..d6ec17c48014820c2ef01e3e5652650a329d3008
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_zh-tw.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_zh-tw");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.zh_tw");dojo.cldr.nls.gregorian.zh_tw={"quarters-standAlone-wide":["第1季","第2季","第3季","第4季"],"quarters-format-abbr":["第1季","第2季","第3季","第4季"],"dateFormat-medium":"yyyy/M/d","field-second":"秒","quarters-standAlone-abbr":["第1季","第2季","第3季","第4季"],"dateFormatItem-MMdd":"MM/dd","dateFormatItem-MEd":"M-d(E)","dateFormatItem-yMEd":"yyyy/M/d(EEE)","field-week":"週","months-format-narrow":["1","2","3","4","5","6","7","8","9","10","11","12"],"timeFormat-full":"ahh時mm分ss秒v","dateFormatItem-HHmmss":"H:mm:ss","dateTimeAvailableFormats":["d日(E)","H:mm","H:mm:ss","M-d(E)","MM/dd","M/d","yyyy/M","yyyy/M/d(EEE)","yyyy年M月","yyyy年M月","yyyy/MM","MMMMdd日","MMMd日","MM-dd","M-d","d日","mm:ss","mm:ss","yyyy年","yyyy-M","yyyy年M月d日,E","yyyy年MMM","yyyy年MMMd日EEE","yyyy年MMMM","yyyy年QQQ","y年QQQ","yy-MM","yy年MMM","yy年第Q季度","yyyy年","yyyy年M月","yyyy年MMMM"],"dateFormatItem-Md":"M/d","months-standAlone-narrow":["1","2","3","4","5","6","7","8","9","10","11","12"],"months-standAlone-wide":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"eraNames":["西元前","西元"],"months-standAlone-abbr":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"field-minute":"分鐘","timeFormat-medium":"ah:mm:ss","field-hour":"小時","dateFormatItem-yyMM":"yyyy/MM","dateFormat-short":"yyyy/M/d","dateFormatItem-yMMMM":"yyyy年M月","dateFormatItem-HHmm":"H:mm","field-era":"年代","dateFormatItem-yM":"yyyy/M","days-standAlone-abbr":["週日","週一","週二","週三","週四","週五","週六"],"timeFormat-long":"ahh時mm分ss秒z","dateFormatItem-yMMM":"yyyy年M月","quarters-format-wide":["第1季","第2季","第3季","第4季"],"field-weekday":"週天","days-format-abbr":["週日","週一","週二","週三","週四","週五","週六"],"field-zone":"區域","dateFormatItem-Ed":"d日(E)","quarters-standAlone-narrow":["1","2","3","4"],"dateFormatItem-yQQQ":"y年QQQ","dateFormatItem-MMMEd":"MMMd日E","eraNarrow":["公元前","公元"],"dateFormat-long":"yyyy年M月d日","months-format-wide":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"dateFormat-full":"yyyy年M月d日EEEE","timeFormat-short":"ah:mm","dateTimeFormat":"{1} {0}","field-year":"年","dateFormatItem-yQ":"yyyy年QQQ","dateFormatItem-yyyyMMMM":"yyyy年MMMM","months-format-abbr":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"dateFormatItem-yyQ":"yy年第Q季度","patternChars":"GanjkHmsSEDFwWxhKzAeugXZvcL","am":"上午","dateFormatItem-H":"H时","dateFormatItem-M":"L","days-standAlone-wide":["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],"dateFormatItem-MMMMd":"MMMMd日","dateFormatItem-yyMMM":"yy年MMM","dateFormatItem-Hm":"H:mm","eraAbbr":["公元前","公元"],"field-dayperiod":"上午/下午","dateFormatItem-d":"d日","dateFormatItem-ms":"mm:ss","dateFormatItem-MMMd":"MMMd日","field-day":"日","days-format-wide":["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],"dateFormatItem-y":"yyyy年","days-format-narrow":["日","一","二","三","四","五","六"],"field-month":"月","days-standAlone-narrow":["日","一","二","三","四","五","六"],"dateFormatItem-MMM":"LLL","pm":"下午","dateFormatItem-MMMMEd":"MMMMd日E","dateFormatItem-MMMMdd":"MMMMdd日","dateFormatItem-yMMMEd":"yyyy年MMMd日EEE","dateFormatItem-yyyyM":"yyyy年M月","dateFormatItem-mmss":"mm:ss","dateFormatItem-yyyy":"yyyy年","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.zh_tw");dijit.nls.loading.zh_tw={"loadingState":"載入中...","errorState":"抱歉,發生錯誤"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.zh_tw");dijit.nls.common.zh_tw={"buttonOk":"確定","buttonCancel":"取消","buttonSave":"儲存","itemClose":"關閉"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.zh_tw");dijit.form.nls.validate.zh_tw={"rangeMessage":"此值超出範圍。","invalidMessage":"輸入的值無效。","missingMessage":"必須提供此值。"};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.zh_tw");dojo.cldr.nls.number.zh_tw={"currencyFormat":"¤#,##0.00","group":",","list":";","decimalFormat":"#,##0.###","scientificFormat":"#E0","percentFormat":"#,##0%","decimal":".","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","infinity":"∞","percentSign":"%","minusSign":"-","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","nan":"NaN","nativeZeroDigit":"0","plusSign":"+","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","perMille":"‰","patternDigit":"#","currencySpacing-beforeCurrency-insertBetween":" ","exponential":"E"};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.zh_tw");dijit.form.nls.ComboBox.zh_tw={"previousMessage":"前一個選擇項","nextMessage":"其他選擇項"};
diff --git a/UNGProject/dojo/dojo/nls/refimpldojo_zh.js b/UNGProject/dojo/dojo/nls/refimpldojo_zh.js
new file mode 100644
index 0000000000000000000000000000000000000000..979015945e2293d2ff07efd4ed7bdb7f912cc7b0
--- /dev/null
+++ b/UNGProject/dojo/dojo/nls/refimpldojo_zh.js
@@ -0,0 +1 @@
+dojo.provide("dojo.nls.refimpldojo_zh");dojo.provide("dojo.cldr.nls.gregorian");dojo.cldr.nls.gregorian._built=true;dojo.provide("dojo.cldr.nls.gregorian.zh");dojo.cldr.nls.gregorian.zh={"months-format-narrow":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"周天","dateFormatItem-yQQQ":"y年QQQ","dateFormatItem-yMEd":"yyyy年M月d日,E","dateFormatItem-MMMEd":"MMMd日E","eraNarrow":["公元前","公元"],"dateFormat-long":"yyyy年M月d日","months-format-wide":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"dateFormat-full":"yyyy年M月d日EEEE","dateFormatItem-Md":"M-d","field-era":"时期","dateFormatItem-yM":"yyyy-M","months-standAlone-wide":["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],"timeFormat-short":"ah:mm","quarters-format-wide":["第1季度","第2季度","第3季度","第4季度"],"dateTimeFormat":"{1} {0}","timeFormat-long":"ahh时mm分ss秒z","field-year":"年","dateFormatItem-yMMM":"yyyy年MMM","dateFormatItem-yQ":"yyyy年QQQ","dateFormatItem-yyyyMMMM":"yyyy年MMMM","field-hour":"小时","dateFormatItem-MMdd":"MM-dd","months-format-abbr":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"dateFormatItem-yyQ":"yy年第Q季度","patternChars":"GanjkHmsSEDFwWxhKzAeugXZvcL","timeFormat-full":"ahh时mm分ss秒v","am":"上午","dateFormatItem-H":"H时","months-standAlone-abbr":["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],"quarters-format-abbr":["1季","2季","3季","4季"],"quarters-standAlone-wide":["第1季度","第2季度","第3季度","第4季度"],"dateFormatItem-HHmmss":"HH:mm:ss","dateFormatItem-M":"L","days-standAlone-wide":["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],"dateFormatItem-MMMMd":"MMMMd日","dateFormatItem-yyMMM":"yy年MMM","timeFormat-medium":"ahh:mm:ss","dateFormatItem-Hm":"H:mm","quarters-standAlone-abbr":["1季","2季","3季","4季"],"eraAbbr":["公元前","公元"],"field-minute":"分钟","field-dayperiod":"上午/下午","days-standAlone-abbr":["周日","周一","周二","周三","周四","周五","周六"],"dateFormatItem-d":"d日","dateFormatItem-ms":"mm:ss","dateFormatItem-MMMd":"MMMd日","dateFormatItem-MEd":"M-dE","dateFormatItem-yMMMM":"yyyy年MMMM","field-day":"日","days-format-wide":["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],"field-zone":"区域","dateFormatItem-y":"yyyy年","months-standAlone-narrow":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"dateFormatItem-yyMM":"yy-MM","days-format-abbr":["周日","周一","周二","周三","周四","周五","周六"],"eraNames":["公元前","公元"],"days-format-narrow":["日","一","二","三","四","五","六"],"field-month":"月","days-standAlone-narrow":["日","一","二","三","四","五","六"],"dateFormatItem-MMM":"LLL","dateFormatItem-HHmm":"HH:mm","pm":"下午","dateFormatItem-MMMMEd":"MMMMd日E","dateFormatItem-MMMMdd":"MMMMdd日","dateFormat-short":"yy-M-d","field-second":"秒钟","dateFormatItem-yMMMEd":"yyyy年MMMd日EEE","dateFormatItem-Ed":"d日E","field-week":"周","dateFormat-medium":"yyyy-M-d","dateFormatItem-yyyyM":"yyyy年M月","dateFormatItem-mmss":"mm:ss","dateFormatItem-yyyy":"yyyy年","dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateTimeFormats-appendItem-Era":"{0} {1}","dateTimeFormats-appendItem-Week":"{0} ({2}: {1})","quarters-format-narrow":["1","2","3","4"],"dateTimeFormats-appendItem-Day":"{0} ({2}: {1})","dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormats-appendItem-Hour":"{0} ({2}: {1})","dateTimeFormats-appendItem-Quarter":"{0} ({2}: {1})","dateTimeFormats-appendItem-Month":"{0} ({2}: {1})","dateTimeFormats-appendItem-Minute":"{0} ({2}: {1})","dateTimeFormats-appendItem-Timezone":"{0} {1}"};dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.zh");dijit.nls.loading.zh={"loadingState":"正在加载...","errorState":"对不起,发生了错误"};dojo.provide("dijit.nls.common");dijit.nls.common._built=true;dojo.provide("dijit.nls.common.zh");dijit.nls.common.zh={"buttonOk":"确定","buttonCancel":"取消","buttonSave":"保存","itemClose":"关闭"};dojo.provide("dijit.form.nls.validate");dijit.form.nls.validate._built=true;dojo.provide("dijit.form.nls.validate.zh");dijit.form.nls.validate.zh={"rangeMessage":"此值超出范围。","invalidMessage":"输入的值无效。","missingMessage":"此值是必需值。"};dojo.provide("dojo.cldr.nls.number");dojo.cldr.nls.number._built=true;dojo.provide("dojo.cldr.nls.number.zh");dojo.cldr.nls.number.zh={"decimalFormat":"#,##0.###","group":",","scientificFormat":"#E0","percentFormat":"#,##0%","currencyFormat":"¤#,##0.00","decimal":".","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","infinity":"∞","list":";","percentSign":"%","minusSign":"-","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","nan":"NaN","nativeZeroDigit":"0","plusSign":"+","currencySpacing-afterCurrency-surroundingMatch":"[:digit:]","currencySpacing-beforeCurrency-currencyMatch":"[:letter:]","perMille":"‰","patternDigit":"#","currencySpacing-beforeCurrency-insertBetween":" ","exponential":"E"};dojo.provide("dijit.form.nls.ComboBox");dijit.form.nls.ComboBox._built=true;dojo.provide("dijit.form.nls.ComboBox.zh");dijit.form.nls.ComboBox.zh={"previousMessage":"先前选项","nextMessage":"更多选项"};
diff --git a/UNGProject/gadgets.html b/UNGProject/gadgets.html
new file mode 100644
index 0000000000000000000000000000000000000000..099a732db05de19dda4b4960bb16eb54762d9935
--- /dev/null
+++ b/UNGProject/gadgets.html
@@ -0,0 +1,2 @@
+[{"name":"Color Palette","url":"http:\/\/localhost\/gadgets\/sample\/colorpalette_oam.xml"},
+{"name":"Date Listener","url":"http:\/\/localhost\/gadgets\/sample\/dateListener.oam.xml"}]
diff --git a/UNGProject/gadgets/layout/.gadgetsite.js.swp b/UNGProject/gadgets/layout/.gadgetsite.js.swp
new file mode 100644
index 0000000000000000000000000000000000000000..f57e87774f09e3b481e095734d69ada5001aaa5b
Binary files /dev/null and b/UNGProject/gadgets/layout/.gadgetsite.js.swp differ
diff --git a/UNGProject/gadgets/layout/absolutelayout/absolutelayout.css b/UNGProject/gadgets/layout/absolutelayout/absolutelayout.css
new file mode 100644
index 0000000000000000000000000000000000000000..3fa2ce54db20154707f7579b1dc947f7b5832133
--- /dev/null
+++ b/UNGProject/gadgets/layout/absolutelayout/absolutelayout.css
@@ -0,0 +1,3 @@
+.gadgetContainer { 
+    position:absolute;
+}
\ No newline at end of file
diff --git a/UNGProject/gadgets/layout/absolutelayout/absolutelayout.js b/UNGProject/gadgets/layout/absolutelayout/absolutelayout.js
new file mode 100644
index 0000000000000000000000000000000000000000..a34f377c1e4a01156630ccabe0ee9cbde4e110e4
--- /dev/null
+++ b/UNGProject/gadgets/layout/absolutelayout/absolutelayout.js
@@ -0,0 +1,378 @@
+function AbsoluteLayout(params)
+{
+    for (var obj in params) {
+        this[obj] = params[obj];
+    }
+    this._bindCallbacks();
+    this.registerLayout();
+
+    this._top = 0;
+}
+
+
+AbsoluteLayout.prototype._keyPress = function(event)
+{
+    event = event ? event : window.event;
+    var target = event.target ? event.target : event.srcElement;
+    if ((this._isDraggingGadget || this._isDraggingPaletteItem) && event.keyCode == 27) {
+        Browser.removeEventListener('mousemove', window.document, this._boundMouseMove);
+        this._hijackFrames(true);
+        if (this._isDraggingGadget) {
+          Browser.setAlpha(this._container, '1.0');
+          this._container.style.left = this._gadgetLeft + "px";
+          this._container.style.top = this._gadgetTop + "px";
+          this._isDraggingGadget = false;
+          this._container = null;
+        } else {
+          Browser.removeEventListener('click', window.document, this._boundClick);
+          this._isDraggingPaletteItem = false;
+          if (this._dragDIV) {
+            this._dragDIV = null;
+            delete this._dragDIVLeft;
+            delete this._dragDIVTop;
+          }
+          if (this._dragDoneCallback) {
+            this._dragDoneCallback(false, null);
+            this._dragDoneCallback = null;
+          }
+        }
+    }
+}
+
+AbsoluteLayout.prototype.getGadgets = function(element)
+{
+    var tables = element.getElementsByTagName('TABLE');
+    var inputs = new Array();
+    for (var i =0; i < tables.length; i++) {
+        var table = tables.item(i);
+        if (table.className == 'gadgetContainer') {
+            inputs.push(table);
+        }
+    }
+    var result = new Array();
+
+    for (var i = 0; i < inputs.length; i++) {
+        var id = inputs[i].getAttribute('_widgetid');
+        var gadget = mashupMaker.getWidgetModelFromID(id);
+        if (gadget) {
+            var site = gadget._site;
+            if (site && site.getContainer() != inputs[i]) {
+                site = new GadgetSite(inputs[i], id/*,
+                        mashupMaker.models[id].views*/);    // XXX JHP TODO handle views
+            }
+            result.push({gadget:gadget, site: site });
+        } 
+    }   
+    return(result);
+}
+
+AbsoluteLayout.prototype._bindCallbacks = function()
+{
+    this._boundMouseDown = Browser.bind(this._mouseDown, this);
+    this._boundMouseUp   = Browser.bind(this._mouseUp, this);
+    this._boundMouseMove = Browser.bind(this._mouseMove, this);
+    this._boundKeyPress  = Browser.bind(this._keyPress, this);
+    this._boundClick     = Browser.bind(this._click, this);
+
+}
+
+AbsoluteLayout.prototype._mouseDown  = function(event)
+{
+    if (this._isDraggingPaletteItem) {
+        // since we use sticky drag for palette items, we don't want to 
+        // do anything on mousedown if we are in the middle of one.
+        return(Browser.cancelEvent(event));
+    }
+    event = event ? event : window.event;
+    var target = event.target ? event.target : event.srcElement;
+    switch (target.className) {
+    case 'gadgetHeader':
+    case 'gadgetTitle':
+    case 'gadgetFooter':
+        this._dragGadget(this._getGadgetContainer(target), event.clientX, event.clientY);
+        return(Browser.cancelEvent(event));
+    case 'gadgetBoxFooter':
+    case 'absSizerImg':
+        this._sizeGadget(this._getGadgetContainer(target), event.clientX, event.clientY);
+        return(Browser.cancelEvent(event));
+    }       
+}
+
+AbsoluteLayout.prototype._mouseUp  = function(event)
+{
+    if (this._isDraggingPaletteItem) {
+        // since we use sticky drag for palette items, we don't want to 
+        // do anything on mousedown if we are in the middle of one.
+        return(Browser.cancelEvent(event));
+    }
+
+    event = event ? event : window.event;
+    var target = event.target ? event.target : event.srcElement;
+
+    switch (target.className) {
+        case 'absDeleteImg':
+            var container = this._getGadgetContainer(target);
+            if ( container.getAttribute("_widgetid") != "" ) {
+                mashupMaker.deleteGadget( container.getAttribute("_widgetid") );
+            } else {
+                container.parentNode.removeChild(container);
+                delete container;
+            }
+            return(Browser.cancelEvent(event));
+
+        case 'absPropEditImg':
+            return(false);
+    }
+
+    if (this._isSizing || this._isDraggingGadget) {
+        Browser.removeEventListener('mousemove', window.document, this._boundMouseMove);
+        if ( this._isSizing ) {
+            // We cannot use "target" in order to get the widget container,
+            // since the target may not be related to a part of the widget
+            // DOM structure (for example, if the widget is sized outside of the
+            // window, then target may come back as the top level "document").
+            // Instead, we save the container when sizing starts and use it here.
+            var container = this._sizingContainer;
+            this._isSizing = false;
+            this._sizingContainer = null;
+            var id = container.getAttribute("_widgetid"); 
+            if ( id != "" ) {
+                mashupMaker.handleWidgetResize( id );
+            }
+        }
+        if (this._saveIndex) {
+          if (this._container) {
+            this._container.style.zIndex =  this._saveIndex;
+            this._saveIndex = null;
+          }
+        }
+        this._hijackFrames(true);
+        if (this._isDraggingGadget) {
+          if (this._container) {
+            Browser.setAlpha(this._container, "1.0");
+          }
+          this._isDraggingGadget = false;
+        }
+        this._container = null;
+        return(Browser.cancelEvent(event));
+    }
+}
+
+AbsoluteLayout.prototype._mouseMove  = function(event) {
+    event = event ? event : window.event;
+    if (this._isSizing) {
+        var dx = event.clientX - this._lastX;
+        var dy = event.clientY - this._lastY;
+        var gadgetBody = this._site.getBody();
+        var pos = dojo.coords(gadgetBody);
+        
+        var newWidth = event.clientX - pos.x + this._offsetX;
+        var newHeight = event.clientY - pos.y + this._offsetY;
+        this._site.resize( newWidth, newHeight );
+
+        if (this._overlay) {
+            this._overlay.style.width = newWidth + "px";
+            this._overlay.style.height = newHeight + "px";
+        }
+
+        this._lastX = event.clientX;
+        this._lastY = event.clientY;
+        return(Browser.cancelEvent(event));
+    } else {
+        if (this._dragDIV) {
+          var dragX, dragY;
+          if (event.pageX || event.pageY) {
+            dragX = event.pageX - this._offsetX;
+            dragY = event.pageY - this._offsetY;
+          } else {
+            dragX = event.clientX + window.document.body.scrollLeft - window.document.body.clientLeft - this._offsetX;
+            dragY = event.clientY + window.document.body.scrollTop - window.document.body.clientTop - this._offsetY;
+          }
+          this._dragDIV.style.left = dragX + "px";
+          this._dragDIV.style.top = dragY + "px";
+        } else {
+          this._container.style.left = event.clientX - this._offsetX + "px";
+          this._container.style.top = event.clientY - this._offsetY + "px";
+          if (this._overlay) {
+              this._overlay.style.left = Browser.pixelValue(this._container.style.left) - this._overlayOffset.x + "px";
+              this._overlay.style.top = Browser.pixelValue(this._container.style.top) - this._overlayOffset.y + "px";
+          }
+        }
+
+        return(Browser.cancelEvent(event));
+    }
+}
+
+AbsoluteLayout.prototype._getGadgetContainer = function(div)
+{
+    while (div && div.className != 'gadgetContainer') {
+        div = div.parentNode;
+    }
+    return(div);
+}
+
+AbsoluteLayout.prototype._sizeGadget = function(container, startX, startY) 
+{
+    this._container = container;
+    var id = container.getAttribute('_widgetid');
+    this._site = new GadgetSite(container, id/*, mashupMaker.models[id].views*/); // XXX JHP TODO handle views
+    var pos = dojo.coords(this._site.getBody());
+
+    this._offsetX = pos.x + pos.w - startX;
+    this._offsetY = pos.y + pos.h - startY;
+
+    this._lastX = startX;
+    this._lastY = startY;
+    this._isSizing = true;
+    this._sizingContainer = container;
+    this._hijackFrames();
+    if (this._frames) {
+        this._overlay = this._frames[id];
+    } else {
+        this._overlay = null;
+    }
+    Browser.addEventListener('mousemove', window.document, this._boundMouseMove);
+}
+
+AbsoluteLayout.prototype._hijackFrames = function(destroy)
+{
+    if (destroy) {
+        if (this._frames) {
+            for (var frameID in this._frames) {
+                var div = this._frames[frameID];
+                div.parentNode.removeChild(div);
+                delete div;
+            }
+        }
+    } else {
+        var iframes = document.getElementsByTagName('IFRAME');
+        this._frames = new Array();
+        for (var i = 0; i < iframes.length; i++) {
+            var frame = iframes.item(i);
+            var container = this._getGadgetContainer(frame);
+            if (!container) {
+              // it is possible that dojo inserts iframes
+              continue;
+            }
+            var id = container.getAttribute('_widgetid');
+            if (! id) {
+                continue;
+            }
+            var div = document.createElement('DIV');
+            div.style.position = 'absolute';
+            var pos = dojo.coords(frame, true);
+            div.style.left   = pos.x + "px";
+            div.style.top    = pos.y + "px";
+            div.style.width  = pos.w + "px";
+            div.style.height = pos.h + "px";
+            div.style.zIndex = 10000;
+            div.style.background = 'white';                
+            div.innerHTML = '&nbsp;';
+            Browser.setAlpha(div, "0");
+            this._frames[id] = div;
+            document.body.appendChild(div);
+        }
+    }
+}
+AbsoluteLayout.prototype._dragGadget = function(container, startX, startY) 
+{
+    this._container = container;
+    this._offsetX = startX - container.offsetLeft;
+    this._offsetY = startY - container.offsetTop;
+
+    this._saveIndex = ++this._top;
+    this._container.style.zIndex = 10001;
+    this._isDraggingGadget = true;
+    this._hijackFrames();
+    if (this._frames) {
+        this._overlay = this._frames[this._container.getAttribute('_widgetid')];
+        if (this._overlay) {
+            var pos = dojo.coords(container, true);
+            this._overlayOffset = {x: pos.x - Browser.pixelValue(this._overlay.style.left),
+                                   y: pos.y - Browser.pixelValue(this._overlay.style.top)};
+            this._overlay.style.zIndex = Number(this._container.style.zIndex) + 1;
+        }
+    } else {
+        this._overlay = null;
+    }
+    Browser.setAlpha(container, "0.4");
+    this._gadgetLeft = container.offsetLeft;
+    this._gadgetTop = container.offsetTop;
+    Browser.addEventListener('mousemove', window.document, this._boundMouseMove);
+}
+
+AbsoluteLayout.prototype.putOnTop = function(container)
+{
+    while (container && container.className != 'gadgetContainer') {
+        container = container.parentNode;
+    }
+    if (container) {
+        container.style.zIndex  = ++this._top;
+        return true;
+    }
+    return false;
+}
+
+AbsoluteLayout.prototype.unregisterLayout = function() {
+    Browser.removeEventListener('mousedown', window.document, this._boundMouseDown);
+    Browser.removeEventListener('mouseup', window.document, this._boundMouseUp);
+    Browser.removeEventListener('keypress', window.document, this._boundKeyPress);
+}
+
+AbsoluteLayout.prototype.registerLayout = function() {
+    Browser.addEventListener('mousedown', window.document, this._boundMouseDown);
+    Browser.addEventListener('mouseup', window.document, this._boundMouseUp);
+    Browser.addEventListener('keypress', window.document, this._boundKeyPress);
+}
+AbsoluteLayout.prototype.setLayoutStyles = function(container) {
+  container.style.position = 'absolute';
+}
+AbsoluteLayout.prototype.removeLayoutStyles = function(container) {
+  container.style.position = '';
+}
+
+AbsoluteLayout.prototype.dragPaletteItem = function(dragDIV, startX, startY, callback) 
+{
+  this._dragDoneCallback = callback;
+  this._dragDIV = dragDIV;
+  this._offsetX = startX - dragDIV.offsetLeft;
+  this._offsetY = startY - dragDIV.offsetTop;
+
+  this._saveIndex = ++this._top;
+  this._dragDIV.style.zIndex = 10001;
+  this._isDraggingPaletteItem = true;
+  this._hijackFrames();
+  this._overlay = null;
+  this._dragDIVLeft = dragDIV.offsetLeft;
+  this._dragDIVTop = dragDIV.offsetTop;
+  Browser.addEventListener('mousemove', window.document, this._boundMouseMove);
+  Browser.addEventListener('click', window.document, this._boundClick);
+}
+AbsoluteLayout.prototype._click = function(event)
+{
+  if (!this._isDraggingPaletteItem) {
+    return;
+  }
+  this._isDraggingPaletteItem = false;
+  if (this._dragDIV) {
+    this._dragDIV = null;
+    delete this._dragDIVLeft;
+    delete this._dragDIVTop;
+  }
+  Browser.removeEventListener('click', window.document, this._boundClick);
+  Browser.removeEventListener('mousemove', window.document, this._boundMouseMove);
+  this._saveIndex = null;
+  this._hijackFrames(true);
+  if (this._dragDoneCallback) {
+    var dropX, dropY;
+    if (event.pageX || event.pageY) {
+      dropX = event.pageX;
+      dropY = event.pageY;
+    } else {
+      dropX = event.clientX + window.document.body.scrollLeft - window.document.body.clientLeft;
+      dropY = event.clientY + window.document.body.scrollTop - window.document.body.clientTop;
+    }
+    this._dragDoneCallback(true, {layout: 'absolutelayout', x: dropX, y: dropY});
+    this._dragDoneCallback = null;
+  }
+}
diff --git a/UNGProject/gadgets/layout/browser.js b/UNGProject/gadgets/layout/browser.js
new file mode 100644
index 0000000000000000000000000000000000000000..ec7cc78f11b50a7fca4dc85fae6ca22c999d0399
--- /dev/null
+++ b/UNGProject/gadgets/layout/browser.js
@@ -0,0 +1,226 @@
+if (typeof Node == 'undefined') {
+    Node = {};
+    Node.ELEMENT_NODE = 1;
+    Node.TEXT_NODE    = 3;
+}
+
+function gel(id) 
+{
+    return(document.getElementById(id));
+}
+
+Browser = {};
+Browser.isIE      = (navigator.userAgent.indexOf('MSIE')  != -1);
+Browser.isFirefox = (navigator.userAgent.indexOf('Firefox') != -1);
+Browser.isSafari  = (navigator.userAgent.indexOf('Safari')  != -1);
+Browser.isOpera   = (navigator.userAgent.indexOf('Opera')   != -1);
+
+Browser.addEventListener = function(eventType, onWhom, callback) {
+    if (onWhom.addEventListener) {
+        onWhom.addEventListener(eventType, callback, false);
+    } else {
+        onWhom.attachEvent('on' + eventType, callback);
+    }
+}
+
+Browser.removeEventListener = function(eventType, onWhom, callback) 
+{
+    if (onWhom.removeEventListener) {
+        onWhom.removeEventListener(eventType, callback, false);
+    } else {
+        onWhom.detachEvent('on' + eventType, callback);
+    }
+}
+
+Browser.bind = function(callback, toWom) 
+{
+    var __method = callback;
+    return function() {
+        return __method.apply(toWom, arguments);
+    }
+}
+
+Browser.setAlpha = function(element, alpha) 
+{
+    if (Browser.isIE) {
+        element.style.filter="Alpha(Opacity=" + (parseFloat(alpha) * 100) + ")";
+    } else {
+        element.style.opacity = alpha;
+    }
+}
+
+Browser.cancelEvent = function(e) 
+{
+    if (e.stopPropagation) {
+        e.stopPropagation();
+    }
+    if (e.preventDefault) {
+        e.preventDefault();
+    }
+    e.cancelBubble = true;
+    e.cancel       = true;
+    e.returnValue  = false;
+
+    return(false);
+}
+Browser.fetchPreviousSibling = function(element, tagName)
+{
+    if (! tagName) {
+        tagName = element.tagName;
+    }
+    element = element.previousSibling;
+    while (element && element.tagName != tagName)  {
+        element = element.previousSibling;
+    }
+    return(element);
+}
+
+Browser.fetchNextSibling = function(element, tagName)
+{
+    if (! tagName) {
+        tagName = element.tagName;
+    }
+    element = element.nextSibling;
+    while (element && element.tagName != tagName)  {
+        element = element.nextSibling;
+    }
+    return(element);
+}
+
+Browser.fetchFirst = function(element, tagName)
+{
+    if (element.childNodes) {
+        tagName = tagName.toUpperCase()
+        for (var i = 0; i < element.childNodes.length; i++) {
+            var child = element.childNodes.item(i);
+            if ((child.tagName && child.tagName.toUpperCase() == tagName) || (!tagName && (child.nodeType == Node.ELEMENT_NODE))) {
+                return(child);
+            }
+        }
+    }
+    return(null);
+}
+
+Browser.fetchChildren = function(element, tagName)
+{
+    var result = new Array();
+    tagName = tagName.toUpperCase();
+    result.item = function(index) {
+        if (index >= 0 && index < this.length) {
+            return(this[index]);
+        }
+        throw 'Index out of bounds';
+    }
+    if (element.childNodes) {
+        for (var i = 0; i < element.childNodes.length; i++) {
+            var child = element.childNodes.item(i);
+            if (child.tagName && child.tagName.toUpperCase() == tagName) {
+                result.push(child);
+            }
+        }
+    }
+    return(result);
+}
+
+Browser.elementFromPoint = function(parent, x, y) {
+    if (document.elementFromPoint) {
+        var element = document.elementFromPoint(x, y);
+        if (element) {
+            return(element);
+        }
+    } else {
+        var startPos = dojo.coords(parent);
+    
+        if ((x >= startPos.x && x <= (startPos.x + parent.offsetWidth)) && 
+            (y >= startPos.y && y < (startPos.y + parent.offsetHeight))) {
+            for (var i = 0; i < parent.childNodes.length; i++) {
+                var child = parent.childNodes.item(i);
+                if (child.nodeType == Node.ELEMENT_NODE) {
+                    var result = this.elementFromPoint(child, x, y);
+                    if (result) {
+                        return(result);
+                    }
+                }
+            }
+            return(parent);
+        }
+    }
+    return(false);
+}
+
+Browser.getScrollTop = function(){
+    return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
+}
+
+Browser.getScrollLeft = function(){
+    return window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0;
+}
+
+Browser.sumAncestorProperties = function(node, prop) {
+    if (!node) { 
+        return 0; 
+    } // FIXME: throw an error?
+
+    var retVal = 0;
+    while(node){
+        var val = node[prop];
+        if(val){
+            retVal += val - 0;
+            if(node==document.body){ break; }// opera and khtml #body & #html has the same values, we only need one value
+        }
+        node = node.parentNode;
+    }
+    return retVal;
+}
+
+Browser.getStyle = function(el, prop) {
+  if (document.defaultView && document.defaultView.getComputedStyle) {
+    return document.defaultView.getComputedStyle(el, null)[prop];
+  } else if (el.currentStyle) {
+      var value = el.currentStyle[prop];
+      if (typeof value == 'undefined') {
+          value = el.style[prop];
+      }
+      return(value);
+  } else {
+    return el.style[prop];
+  }
+}
+Browser.pixelValue = function(str) 
+{
+    if (typeof str == 'number') {
+        return(str);
+    }
+    if (!str) {
+        return(0);
+    }    
+    var match = str.match(/(.*)(px|\%)?/);
+    if (match && match.length == 3) 
+        return(parseFloat(match[1]));
+    return(0);
+}
+Browser.createElement = function(tagName, style, parent) {
+    var result = document.createElement(tagName);
+    if (style) {
+        result.className = style;
+    }
+    if (parent) {
+        parent.appendChild(result);
+    }
+    return(result);
+}
+Browser.evalScriptGlobal = function(script) {
+    // dojo.eval doesn't execute script in global scope on IE.  Be aware that
+    // window.execScript doesn't return anything so really best just for
+    // declaring things like functions, etc
+    if (window.execScript) {
+        window.execScript(script);
+        return null;
+    }
+
+    return dojo.eval(script);
+}
+
+function _gel(id) {
+    return(document.getElementById(id));
+}
diff --git a/UNGProject/gadgets/layout/css/default/mashup.css b/UNGProject/gadgets/layout/css/default/mashup.css
new file mode 100644
index 0000000000000000000000000000000000000000..073157a9f518bcaf4de6799762ed2a8957c84506
--- /dev/null
+++ b/UNGProject/gadgets/layout/css/default/mashup.css
@@ -0,0 +1,173 @@
+  /* styles for the banner and toolbar */
+
+  .banner {
+    background-image: url('../../images/OAAright.jpg');
+    background-repeat: repeat-x;
+    margin: 0;
+    height: 47px;
+    width: 100%;
+  }
+  .banner-left {
+    float: left;
+    height: 47px;
+    width: 320px;
+  }
+  .banner-right {
+    float: right;
+    height: 47px;
+    width: 1px;
+  }
+  .nomadToolbarIcon {
+    background-repeat: no-repeat;
+    width: 24px;
+    height: 24px;
+    text-align: center;
+    cursor: pointer;
+  }
+
+  .nomadIconHelp {
+    background-image: url('../../images/help.gif');
+  }
+  .nomadIconView {
+    background-image: url('../../images/view.gif');
+  }
+  .nomadIconImport {
+    background-image: url('../../images/plus-circle.png');
+  }
+  .nomadIconRefresh {
+    background-image: url('../../images/refreshResults.gif');
+  }
+  .nomadIconSearchResults {
+    background-image: url('../../images/plus-circle.png');
+  }
+  .nomadCheckedMenuItemIcon {
+    background-image: url('../../images/checkmark.gif');
+  }
+  .nomadIconNoBinding {
+    background-image: url('../../images/noBind.gif');
+  }
+  .nomadIconSingleBinding {
+    background-image: url('../../images/singleBind.gif');
+  }
+  .nomadIconMultipleBinding {
+    background-image: url('../../images/multipleBind.gif');
+  }
+  .nomadIconPreferences {
+    background-image: url('../../images/gear_small.gif');
+  }
+  .preEdit input {
+    font-style: italic;
+    font-weight: lighter;
+    color: #999;
+  }
+  input.postEdit {
+    font-style: normal;
+    font-weight: normal;
+    color: #000;
+  }
+
+  /* styles for palette*/
+
+  .nomadIconWidget {
+    background-image: url('../../images/component_18x18.gif');
+  }
+  .paletteItemIconRow {
+    display: none;
+  }
+  .dijitMenuItemHover .paletteItemIconRow {
+    display: table-row;
+  }
+  .dijitMenuItemHoverIE .paletteItemIconRow {
+    display: block;
+  }
+  .dijitMenuItemHover .nomadIconInfo {
+    background-image: url('../../images/info.png');
+  }
+  .dijitMenuItemHover .nomadIconRun {
+    background-image: url('../../images/run.gif');
+  }
+  .dijitMenuItemHover .nomadIconBookmark {
+    background-image: url('../../images/folder.gif');
+  }
+
+  .nomadPaletteItem {
+    cursor: default;
+  }
+  .dijitMenu .nomadInnerMenu {
+    border: 0;
+  }
+  .paletteScrollButton {
+    width: 100%;
+    height: 18px;
+  }
+  .nomadIconScrollUp {
+    background-image: url('../../images/uparrow.gif');
+  }
+  .nomadIconScrollDown {
+    background-image: url('../../images/downarrow.gif');
+  }
+  .dijitTitlePane.paletteNorgie {
+    min-width: 200px;
+  }
+
+  .dijitMenu .paletteNorgie .dijitTitlePaneTitle {
+    background-image: none;
+    background-color: #e0d138;
+  }
+
+  .nomadWiringOverlayCurrent {
+    background-color: purple;
+  }
+  .nomadWiringOverlayRecommended {
+    background-color: yellow;
+  }
+  .nomadWiringOverlayPossible {
+   /* background-color: gray;*/
+  }
+  .dijitTooltip .dijitTooltipContainer {
+    width: 200px;
+  }
+  #propertyDialog .gadgetBody {
+    border: none;
+    padding: 0;
+    height: auto;
+  }
+
+  .nomadErrorMsg {
+    color: red;
+    font-style: italic;
+  }
+
+  .tundra .nomadMultiSelect select, .tundra .nomadMultiSelect input {
+    /* use same layout styles for both major components of the multiselect control */
+    /*border: 1px solid #B3B3B3;*/
+    margin: 0em 0.1em;
+  }
+
+  /* dojo 1.1 doesn't necessarily gray text anymore due to '.dijitReset' rule it introduced */
+  input[disabled], textarea[disabled], option[disabled], optgroup[disabled], select[disabled] {
+    color: graytext;
+  }
+
+  /* dojo 1.1 is causing things in buttons to be vertical-align: middle which
+   * is bothering the arrows on our WiringDropDownButtons
+   */
+  .wiringButton .dijitButtonNode * {
+    display: -moz-inline-box;
+    display: inline-block;
+  }
+
+  .wiringButton .dijitA11yDownArrow {
+    margin-left: 0.8em;
+    font-size: 0.75em;
+    color: #848484;
+  }
+
+    /* had to specify directly, IE wasn't inheriting well */
+/*
+  #searchOptions.dijitMenuItemHover {
+    background-color: #f7f7f7;
+    color: #000;
+  }
+*/
+
diff --git a/UNGProject/gadgets/layout/css/whitebox/corner_db_BR16.png b/UNGProject/gadgets/layout/css/whitebox/corner_db_BR16.png
new file mode 100644
index 0000000000000000000000000000000000000000..0c4fef94207a37b6e9d049bd5bdfcbdc03533cdb
Binary files /dev/null and b/UNGProject/gadgets/layout/css/whitebox/corner_db_BR16.png differ
diff --git a/UNGProject/gadgets/layout/css/whitebox/corner_dg_BL16.png b/UNGProject/gadgets/layout/css/whitebox/corner_dg_BL16.png
new file mode 100644
index 0000000000000000000000000000000000000000..1ab860f0f2b9e41f031e1c6a519d9ac7dc6353c9
Binary files /dev/null and b/UNGProject/gadgets/layout/css/whitebox/corner_dg_BL16.png differ
diff --git a/UNGProject/gadgets/layout/css/whitebox/corner_dg_TL.gif b/UNGProject/gadgets/layout/css/whitebox/corner_dg_TL.gif
new file mode 100644
index 0000000000000000000000000000000000000000..37b6c20415fc508f34886ca64b0b97093e54abae
Binary files /dev/null and b/UNGProject/gadgets/layout/css/whitebox/corner_dg_TL.gif differ
diff --git a/UNGProject/gadgets/layout/css/whitebox/corner_dg_TR.gif b/UNGProject/gadgets/layout/css/whitebox/corner_dg_TR.gif
new file mode 100644
index 0000000000000000000000000000000000000000..c7adb47d34adc88876a89fc41269b9facef51c21
Binary files /dev/null and b/UNGProject/gadgets/layout/css/whitebox/corner_dg_TR.gif differ
diff --git a/UNGProject/gadgets/layout/css/whitebox/smallish_widget.png b/UNGProject/gadgets/layout/css/whitebox/smallish_widget.png
new file mode 100644
index 0000000000000000000000000000000000000000..d3c728c052936d75bc137bf8b41bd668819bf0cd
Binary files /dev/null and b/UNGProject/gadgets/layout/css/whitebox/smallish_widget.png differ
diff --git a/UNGProject/gadgets/layout/css/whitebox/whitebox.css b/UNGProject/gadgets/layout/css/whitebox/whitebox.css
new file mode 100644
index 0000000000000000000000000000000000000000..f55cf575ba623716b9be85024e2eb20498c13632
--- /dev/null
+++ b/UNGProject/gadgets/layout/css/whitebox/whitebox.css
@@ -0,0 +1,114 @@
+      html body { 
+            background:#DADADA;       
+            margin:0px;
+       }
+
+      .properties {
+          display:none;
+      }
+
+      .gadgetBody {
+          position:relative;
+          padding:4px;
+          height:100%;
+          overflow:hidden;
+          background:white;
+          border-right: solid 1px #dfdfdf;
+          border-bottom: solid 1px #dfdfdf;
+          border-left: solid 1px #dfdfdf;
+      }
+
+      .gadgetFrame { 
+          width:100%;
+          height:100%;
+          margin:0;
+          padding:0;
+          border:none;
+       }
+
+      .gadgetDragAvatar { 
+          position:absolute;
+          display:none;
+          background:url(smallish_widget.png) center left no-repeat;
+          height:50px;
+          padding-left:54px;
+          overflow:hidden;
+      }
+
+      .gadgetDragAvatar div { 
+          overflow:hidden;
+          background:#DADADA;
+          height:100%;
+          background:#fef49c;
+          border:1px solid #BCA902;
+          padding:2px;
+          font-size:14px;
+       }
+
+      .gadgetDropTarget { 
+          position:absolute;
+          background:darkgray;
+          width:4px;
+       }
+      .gadgetContainer .gadgetBoxHeader {
+          height:4px;
+          background:#DAE6F6; /* url(corner_dg_TR.gif) 100% 0 no-repeat;*/
+       }
+
+      .gadgetContainer .gadgetBoxHeader div {
+          width:4px;
+          height:4px;
+          background:#DAE6F6; /*  url(corner_dg_TL.gif) 0 0 no-repeat;*/
+       }
+
+      .gadgetContainer .gadgetBoxContent {
+          background:#DAE6F6;
+          padding:5px 9px 0px 9px;
+      }
+
+      .gadgetContainer .gadgetBoxFooter {
+          height:16px;
+          background:#DAE6F6; /*  url(corner_db_BR16.png) 100% 0 no-repeat;*/
+          cursor:se-resize;
+       }
+
+      .gadgetContainer .gadgetBoxFooter div  {
+          height:16px;
+          width:16px;
+          background:#DAE6F6; /*  url(corner_dg_BL16.png) 0 0 no-repeat;*/
+       }
+
+      .gadgetHeader {
+          position:relative;
+          height:20px;
+          cursor:move;
+          background:#DADADA;
+      }
+
+       .absDeleteImg { 
+          margin-top:3px;
+          margin-right:4px;
+          cursor:pointer;
+          float:right;
+       }
+
+       .absPropEditImg { 
+          margin-top:2px;
+          margin-right:4px;
+          margin-left:4px;
+          cursor:pointer;
+          float:left;
+       }
+
+       .absSizerImg { 
+          float:right;
+          cursor:se-resize;
+       }
+
+      .gadgetTitle {
+          overflow:hidden;
+          font-size:16px;
+          padding-top:2px;
+          white-space:nowrap;          
+      }
+
diff --git a/UNGProject/gadgets/layout/gadgetsite.js b/UNGProject/gadgets/layout/gadgetsite.js
new file mode 100644
index 0000000000000000000000000000000000000000..6d5d8e16fa82ec9a59547ed86d724af0267b687a
--- /dev/null
+++ b/UNGProject/gadgets/layout/gadgetsite.js
@@ -0,0 +1,205 @@
+dojo.declare("GadgetSite", null, {
+
+        constants : {
+            GADGET_CLASSNAMES: ['gadgetHeader', 'gadgetBody', 'gadgetTitle']
+        },
+
+        constructor: function(container, id, views) {
+            this.gadgetContainer = container;
+            this.widgetId = id;
+            this.views = views;
+            if (container) {
+                this.adopt(container);
+            }
+            if ( ! dijit.byId(id + "_propMenu") ) {
+                // Due to a bug in IE 6/7, we cannot call this method directly.
+                // This constructor is called from inline JavaScript and tries
+                // to manipulate the DOM of the containing element.  On IE 6/7,
+                // this leads to a crash of the JS engine.  In order to avoid
+                // that, we create the menu after the DOM has loaded.
+                dojo.addOnLoad(this, "createEditMenu");
+            }
+        },
+        /**
+         * create the edit menu for the widget attaching it to left click on
+         * the widget edit image in the widget header
+         * 
+         */
+        createEditMenu: function() {
+            dojo.require('dijit.Menu');
+            var targetImgNode = dojo.byId(this.widgetId+"_propMenuTarget");
+            if ( ! targetImgNode ) { // nothing to bind to...
+                return;
+            }
+
+            var widgetId = this.widgetId;
+            pMenu = new dijit.Menu(
+                    { 
+                        targetNodeIds:[this.widgetId+"_propMenuTarget"], 
+                        id: this.widgetId + "_propMenu",
+                        leftClickToOpen: true
+                    });
+            pMenu.addChild(new dijit.MenuItem(
+                    {
+                        label: "Edit widget properties", 
+                        onClick: //dojo.hitch( window,
+                            function(evt) {
+                                mashupMaker.editGadget( widgetId );
+                            }
+                        //)
+                    }));
+            pMenu.addChild(new dijit.MenuItem(
+                    {
+                        label: "Share widget", 
+                        onClick:
+                            function(evt) {
+                                mashupMaker.shareGadget( widgetId );
+                            }
+                    }));
+
+            // menu items for custom widget views go here
+            if ( typeof this.views == "object" ) {
+                var addedSeparator = false;
+                for ( var i = 0; i < this.views.length; i++ ) {
+                    var viewName = this.views[i];
+                    
+                    if ( viewName == 'default' ||
+                         viewName == 'edit' ||
+                         viewName == 'help' ) {
+                        continue;
+                    }
+                    
+                    // Add an extra separator if there are any custom views
+                    if ( ! addedSeparator ) {
+                        pMenu.addChild(new dijit.MenuSeparator());
+                        addedSeparator = true;
+                    }
+                    
+                    // Custom view names are QNames, which may consist of a
+                    // prefix and a local part separated by a ':'.  For the
+                    // menu, we'll only display the local part.
+                    var localPart = viewName.split(":").pop();
+                    pMenu.addChild(new dijit.MenuItem(
+                        {
+                            label: localPart.charAt(0).toUpperCase() + localPart.substr(1), 
+                            onClick: 
+                                function(evt) {
+                                    var menuItem = dijit.getEnclosingWidget(evt.currentTarget);
+                                    mashupMaker.openGadgetView( widgetId, menuItem.fullQName );
+                                },
+                            fullQName: viewName
+                        }));
+                }
+            }
+            
+            pMenu.addChild(new dijit.MenuSeparator());
+            if ( this.views && dojo.indexOf(this.views, 'help') != -1 ) {   // XXX this.views should exist; shouldn't need to check for it
+                pMenu.addChild(new dijit.MenuItem(
+                    {
+                        label: "Help",
+                        onClick: 
+                            function(evt) {
+                                mashupMaker.openGadgetView( widgetId, 'help' );
+                            }
+                    }));
+            } else {
+                pMenu.addChild(new dijit.MenuItem({label: "Help", disabled: true}));
+            }
+            pMenu.startup();            
+        },
+        
+        /**
+         * Return the body html element for this site. The body element actually contains the widget
+         *
+         * @return HTML Element
+         * @type {DOM}
+         */
+        getBody: function() {
+            return(this.gadgetBody);
+        },
+
+        /**
+         * Return the containing html element for this site. 
+         *
+         * @return HTML Element
+         * @type {DOM}
+         */
+        getContainer: function() {
+            return(this.gadgetContainer);
+        },
+
+        /**
+         * Set the title of the gadget within the site.
+         *
+         * @param {String} title The title to be displayed
+         */
+        setTitle : function(title) {
+            this._titleText = title;
+            var titleTarget = this.getTitleElement();
+            if (titleTarget) {
+                titleTarget.innerHTML = title;
+            }
+        },
+
+        /**
+         * Get the title of the gadget within the site.
+         *
+         * @return The title to be displayed
+         * @type {String}
+         */
+        getTitle : function() {
+            var titleTarget = this.getTitleElement();
+            if (! this._titleText && titleTarget) {
+                this._titleText = titleTarget.innerHTML;        
+            }
+            return(this._titleText);
+        },
+        
+        getTitleElement : function() {
+            return(this.gadgetTitle);
+        },
+
+        /**
+         * @param {DOM} containerDOM The DOM element to adopt as the container
+         */
+        adopt: function(containerDOM) {
+            if (containerDOM.tagName != 'TABLE' || containerDOM.className != 'gadgetContainer') {
+                return(false);
+            }
+            this.gadgetContainer = containerDOM;
+            dojo.forEach(this.constants.GADGET_CLASSNAMES,
+                         dojo.hitch(this,
+                                    function(className) {
+                                        var gadgetPart = dojo.query('.' + className, containerDOM);
+                                        if (gadgetPart && gadgetPart.length) {
+                                            this[className] = gadgetPart[0];
+                                        }
+                                    })
+            );
+        },
+
+        getDimensions : function() {
+            var dimensions = {};
+            var style = dojo.getComputedStyle( this.gadgetBody );
+            dimensions.width = parseInt( style.width );
+            dimensions.height = parseInt( style.height );
+            
+            return dimensions;
+        },
+        
+        getPosition : function() {
+            var coords = dojo.coords( this.gadgetContainer );
+            return { x: coords.x, y: coords.y };
+        },
+        
+        resize : function( width, height ) {
+            this.gadgetBody.style.width = width + "px";
+            this.gadgetBody.style.height = height + "px";
+
+	        // XXX 'gadgetHeader' sizing should be done in theme specific file
+            if ( this.gadgetHeader ) {
+                this.gadgetHeader.style.width = dojo.coords( this.gadgetBody ).w + "px";
+            }
+        }
+
+});
diff --git a/UNGProject/gadgets/layout/images/OAAleft.jpg b/UNGProject/gadgets/layout/images/OAAleft.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..a122d019b9e88618595eebe496f760985dda30d4
Binary files /dev/null and b/UNGProject/gadgets/layout/images/OAAleft.jpg differ
diff --git a/UNGProject/gadgets/layout/images/OAAright.jpg b/UNGProject/gadgets/layout/images/OAAright.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..57d5d0722b51bc1603677027ffd58879a1b807db
Binary files /dev/null and b/UNGProject/gadgets/layout/images/OAAright.jpg differ
diff --git a/UNGProject/gadgets/layout/images/checkmark.gif b/UNGProject/gadgets/layout/images/checkmark.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1c14222dded318554be9f767e0750fb9828116d7
Binary files /dev/null and b/UNGProject/gadgets/layout/images/checkmark.gif differ
diff --git a/UNGProject/gadgets/layout/images/component_18x18.gif b/UNGProject/gadgets/layout/images/component_18x18.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4f834ce95e706d6e252980bbf75d5a5535da9a10
Binary files /dev/null and b/UNGProject/gadgets/layout/images/component_18x18.gif differ
diff --git a/UNGProject/gadgets/layout/images/delete.png b/UNGProject/gadgets/layout/images/delete.png
new file mode 100644
index 0000000000000000000000000000000000000000..f953427ffbcf0ab10541446a4b93cff0aa17162b
Binary files /dev/null and b/UNGProject/gadgets/layout/images/delete.png differ
diff --git a/UNGProject/gadgets/layout/images/downarrow.gif b/UNGProject/gadgets/layout/images/downarrow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f3f3f5a2a65810e970839ea6d2ac4bcff0b03a6f
Binary files /dev/null and b/UNGProject/gadgets/layout/images/downarrow.gif differ
diff --git a/UNGProject/gadgets/layout/images/folder.gif b/UNGProject/gadgets/layout/images/folder.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a294a26388b4b6b32164c68667008d42be20804a
Binary files /dev/null and b/UNGProject/gadgets/layout/images/folder.gif differ
diff --git a/UNGProject/gadgets/layout/images/gear_small.gif b/UNGProject/gadgets/layout/images/gear_small.gif
new file mode 100644
index 0000000000000000000000000000000000000000..52b9ef40f0d74f02bb3e7d9ad4d8921503eefab4
Binary files /dev/null and b/UNGProject/gadgets/layout/images/gear_small.gif differ
diff --git a/UNGProject/gadgets/layout/images/help.gif b/UNGProject/gadgets/layout/images/help.gif
new file mode 100644
index 0000000000000000000000000000000000000000..9cf894a94673836c52ee15e6d1b2621fdd996007
Binary files /dev/null and b/UNGProject/gadgets/layout/images/help.gif differ
diff --git a/UNGProject/gadgets/layout/images/importSearchTerms.gif b/UNGProject/gadgets/layout/images/importSearchTerms.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a573ceec61f69d161c9f62d51121c79eee209fc8
Binary files /dev/null and b/UNGProject/gadgets/layout/images/importSearchTerms.gif differ
diff --git a/UNGProject/gadgets/layout/images/info.png b/UNGProject/gadgets/layout/images/info.png
new file mode 100644
index 0000000000000000000000000000000000000000..c1d3fc1b231fc06af2fc8d2c5cc36f617aaa6f8b
Binary files /dev/null and b/UNGProject/gadgets/layout/images/info.png differ
diff --git a/UNGProject/gadgets/layout/images/multipleBind.gif b/UNGProject/gadgets/layout/images/multipleBind.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5c9df64bb9842495e83a1cf62f231e577f7032bc
Binary files /dev/null and b/UNGProject/gadgets/layout/images/multipleBind.gif differ
diff --git a/UNGProject/gadgets/layout/images/noBind.gif b/UNGProject/gadgets/layout/images/noBind.gif
new file mode 100644
index 0000000000000000000000000000000000000000..20d1d1f489d580a75211e5071d840968dca9d85a
Binary files /dev/null and b/UNGProject/gadgets/layout/images/noBind.gif differ
diff --git a/UNGProject/gadgets/layout/images/plus-circle.png b/UNGProject/gadgets/layout/images/plus-circle.png
new file mode 100644
index 0000000000000000000000000000000000000000..34ca37a09d5ae70b8dd84223f7ab21cedcd90b9e
Binary files /dev/null and b/UNGProject/gadgets/layout/images/plus-circle.png differ
diff --git a/UNGProject/gadgets/layout/images/refreshResults.gif b/UNGProject/gadgets/layout/images/refreshResults.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ff18a8cde2c0aaadea73bf78b0bb30e2024dd347
Binary files /dev/null and b/UNGProject/gadgets/layout/images/refreshResults.gif differ
diff --git a/UNGProject/gadgets/layout/images/run.gif b/UNGProject/gadgets/layout/images/run.gif
new file mode 100644
index 0000000000000000000000000000000000000000..2133b4582a8da9cab60d1c0acce1d6c3c4034fa7
Binary files /dev/null and b/UNGProject/gadgets/layout/images/run.gif differ
diff --git a/UNGProject/gadgets/layout/images/searchResults.gif b/UNGProject/gadgets/layout/images/searchResults.gif
new file mode 100644
index 0000000000000000000000000000000000000000..3f056c3c2df3fe153a1a92e7253343a2b12af85e
Binary files /dev/null and b/UNGProject/gadgets/layout/images/searchResults.gif differ
diff --git a/UNGProject/gadgets/layout/images/singleBind.gif b/UNGProject/gadgets/layout/images/singleBind.gif
new file mode 100644
index 0000000000000000000000000000000000000000..839e1fef5bb2afc73f6dbc48b281392a2fb34305
Binary files /dev/null and b/UNGProject/gadgets/layout/images/singleBind.gif differ
diff --git a/UNGProject/gadgets/layout/images/uparrow.gif b/UNGProject/gadgets/layout/images/uparrow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6eb71a3272186556e42c7bcd6b9b2130ff748ca0
Binary files /dev/null and b/UNGProject/gadgets/layout/images/uparrow.gif differ
diff --git a/UNGProject/gadgets/layout/images/view.gif b/UNGProject/gadgets/layout/images/view.gif
new file mode 100644
index 0000000000000000000000000000000000000000..eec487d777807b2b310fdc31f2d8fa27d51b6098
Binary files /dev/null and b/UNGProject/gadgets/layout/images/view.gif differ
diff --git a/UNGProject/gadgets/refimpldojo.js b/UNGProject/gadgets/refimpldojo.js
new file mode 100644
index 0000000000000000000000000000000000000000..42e6f8be560619a3274a2397b12fe940edb39980
--- /dev/null
+++ b/UNGProject/gadgets/refimpldojo.js
@@ -0,0 +1,19167 @@
+/*
+	Copyright (c) 2004-2009, The Dojo Foundation All Rights Reserved.
+	Available via Academic Free License >= 2.1 OR the modified BSD license.
+	see: http://dojotoolkit.org/license for details
+*/
+
+/*
+	This is a compiled version of Dojo, built for deployment and not for
+	development. To get an editable version, please visit:
+
+		http://dojotoolkit.org
+
+	for documentation and information on getting the source.
+*/
+
+if(!dojo._hasResource["dojo.date.stamp"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.date.stamp"] = true;
+dojo.provide("dojo.date.stamp");
+
+// Methods to convert dates to or from a wire (string) format using well-known conventions
+
+dojo.date.stamp.fromISOString = function(/*String*/formattedString, /*Number?*/defaultTime){
+	//	summary:
+	//		Returns a Date object given a string formatted according to a subset of the ISO-8601 standard.
+	//
+	//	description:
+	//		Accepts a string formatted according to a profile of ISO8601 as defined by
+	//		[RFC3339](http://www.ietf.org/rfc/rfc3339.txt), except that partial input is allowed.
+	//		Can also process dates as specified [by the W3C](http://www.w3.org/TR/NOTE-datetime)
+	//		The following combinations are valid:
+	//
+	//			* dates only
+	//			|	* yyyy
+	//			|	* yyyy-MM
+	//			|	* yyyy-MM-dd
+	// 			* times only, with an optional time zone appended
+	//			|	* THH:mm
+	//			|	* THH:mm:ss
+	//			|	* THH:mm:ss.SSS
+	// 			* and "datetimes" which could be any combination of the above
+	//
+	//		timezones may be specified as Z (for UTC) or +/- followed by a time expression HH:mm
+	//		Assumes the local time zone if not specified.  Does not validate.  Improperly formatted
+	//		input may return null.  Arguments which are out of bounds will be handled
+	// 		by the Date constructor (e.g. January 32nd typically gets resolved to February 1st)
+	//		Only years between 100 and 9999 are supported.
+	//
+  	//	formattedString:
+	//		A string such as 2005-06-30T08:05:00-07:00 or 2005-06-30 or T08:05:00
+	//
+	//	defaultTime:
+	//		Used for defaults for fields omitted in the formattedString.
+	//		Uses 1970-01-01T00:00:00.0Z by default.
+
+	if(!dojo.date.stamp._isoRegExp){
+		dojo.date.stamp._isoRegExp =
+//TODO: could be more restrictive and check for 00-59, etc.
+			/^(?:(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(.\d+)?)?((?:[+-](\d{2}):(\d{2}))|Z)?)?$/;
+	}
+
+	var match = dojo.date.stamp._isoRegExp.exec(formattedString);
+	var result = null;
+
+	if(match){
+		match.shift();
+		if(match[1]){match[1]--;} // Javascript Date months are 0-based
+		if(match[6]){match[6] *= 1000;} // Javascript Date expects fractional seconds as milliseconds
+
+		if(defaultTime){
+			// mix in defaultTime.  Relatively expensive, so use || operators for the fast path of defaultTime === 0
+			defaultTime = new Date(defaultTime);
+			dojo.map(["FullYear", "Month", "Date", "Hours", "Minutes", "Seconds", "Milliseconds"], function(prop){
+				return defaultTime["get" + prop]();
+			}).forEach(function(value, index){
+				if(match[index] === undefined){
+					match[index] = value;
+				}
+			});
+		}
+		result = new Date(match[0]||1970, match[1]||0, match[2]||1, match[3]||0, match[4]||0, match[5]||0, match[6]||0);
+//		result.setFullYear(match[0]||1970); // for year < 100
+
+		var offset = 0;
+		var zoneSign = match[7] && match[7].charAt(0);
+		if(zoneSign != 'Z'){
+			offset = ((match[8] || 0) * 60) + (Number(match[9]) || 0);
+			if(zoneSign != '-'){ offset *= -1; }
+		}
+		if(zoneSign){
+			offset -= result.getTimezoneOffset();
+		}
+		if(offset){
+			result.setTime(result.getTime() + offset * 60000);
+		}
+	}
+
+	return result; // Date or null
+}
+
+/*=====
+	dojo.date.stamp.__Options = function(){
+		//	selector: String
+		//		"date" or "time" for partial formatting of the Date object.
+		//		Both date and time will be formatted by default.
+		//	zulu: Boolean
+		//		if true, UTC/GMT is used for a timezone
+		//	milliseconds: Boolean
+		//		if true, output milliseconds
+		this.selector = selector;
+		this.zulu = zulu;
+		this.milliseconds = milliseconds;
+	}
+=====*/
+
+dojo.date.stamp.toISOString = function(/*Date*/dateObject, /*dojo.date.stamp.__Options?*/options){
+	//	summary:
+	//		Format a Date object as a string according a subset of the ISO-8601 standard
+	//
+	//	description:
+	//		When options.selector is omitted, output follows [RFC3339](http://www.ietf.org/rfc/rfc3339.txt)
+	//		The local time zone is included as an offset from GMT, except when selector=='time' (time without a date)
+	//		Does not check bounds.  Only years between 100 and 9999 are supported.
+	//
+	//	dateObject:
+	//		A Date object
+
+	var _ = function(n){ return (n < 10) ? "0" + n : n; };
+	options = options || {};
+	var formattedDate = [];
+	var getter = options.zulu ? "getUTC" : "get";
+	var date = "";
+	if(options.selector != "time"){
+		var year = dateObject[getter+"FullYear"]();
+		date = ["0000".substr((year+"").length)+year, _(dateObject[getter+"Month"]()+1), _(dateObject[getter+"Date"]())].join('-');
+	}
+	formattedDate.push(date);
+	if(options.selector != "date"){
+		var time = [_(dateObject[getter+"Hours"]()), _(dateObject[getter+"Minutes"]()), _(dateObject[getter+"Seconds"]())].join(':');
+		var millis = dateObject[getter+"Milliseconds"]();
+		if(options.milliseconds){
+			time += "."+ (millis < 100 ? "0" : "") + _(millis);
+		}
+		if(options.zulu){
+			time += "Z";
+		}else if(options.selector != "time"){
+			var timezoneOffset = dateObject.getTimezoneOffset();
+			var absOffset = Math.abs(timezoneOffset);
+			time += (timezoneOffset > 0 ? "-" : "+") + 
+				_(Math.floor(absOffset/60)) + ":" + _(absOffset%60);
+		}
+		formattedDate.push(time);
+	}
+	return formattedDate.join('T'); // String
+}
+
+}
+
+if(!dojo._hasResource["dojo.parser"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.parser"] = true;
+dojo.provide("dojo.parser");
+
+
+dojo.parser = new function(){
+	// summary: The Dom/Widget parsing package
+
+	var d = dojo;
+	var dtName = d._scopeName + "Type";
+	var qry = "[" + dtName + "]";
+
+	var _anonCtr = 0, _anon = {};
+	var nameAnonFunc = function(/*Function*/anonFuncPtr, /*Object*/thisObj){
+		// summary:
+		//		Creates a reference to anonFuncPtr in thisObj with a completely
+		//		unique name. The new name is returned as a String. 
+		var nso = thisObj || _anon;
+		if(dojo.isIE){
+			var cn = anonFuncPtr["__dojoNameCache"];
+			if(cn && nso[cn] === anonFuncPtr){
+				return cn;
+			}
+		}
+		var name;
+		do{
+			name = "__" + _anonCtr++;
+		}while(name in nso)
+		nso[name] = anonFuncPtr;
+		return name; // String
+	}
+
+	function val2type(/*Object*/ value){
+		// summary:
+		//		Returns name of type of given value.
+
+		if(d.isString(value)){ return "string"; }
+		if(typeof value == "number"){ return "number"; }
+		if(typeof value == "boolean"){ return "boolean"; }
+		if(d.isFunction(value)){ return "function"; }
+		if(d.isArray(value)){ return "array"; } // typeof [] == "object"
+		if(value instanceof Date) { return "date"; } // assume timestamp
+		if(value instanceof d._Url){ return "url"; }
+		return "object";
+	}
+
+	function str2obj(/*String*/ value, /*String*/ type){
+		// summary:
+		//		Convert given string value to given type
+		switch(type){
+			case "string":
+				return value;
+			case "number":
+				return value.length ? Number(value) : NaN;
+			case "boolean":
+				// for checked/disabled value might be "" or "checked".  interpret as true.
+				return typeof value == "boolean" ? value : !(value.toLowerCase()=="false");
+			case "function":
+				if(d.isFunction(value)){
+					// IE gives us a function, even when we say something like onClick="foo"
+					// (in which case it gives us an invalid function "function(){ foo }"). 
+					//  Therefore, convert to string
+					value=value.toString();
+					value=d.trim(value.substring(value.indexOf('{')+1, value.length-1));
+				}
+				try{
+					if(value.search(/[^\w\.]+/i) != -1){
+						// TODO: "this" here won't work
+						value = nameAnonFunc(new Function(value), this);
+					}
+					return d.getObject(value, false);
+				}catch(e){ return new Function(); }
+			case "array":
+				return value ? value.split(/\s*,\s*/) : [];
+			case "date":
+				switch(value){
+					case "": return new Date("");	// the NaN of dates
+					case "now": return new Date();	// current date
+					default: return d.date.stamp.fromISOString(value);
+				}
+			case "url":
+				return d.baseUrl + value;
+			default:
+				return d.fromJson(value);
+		}
+	}
+
+	var instanceClasses = {
+		// map from fully qualified name (like "dijit.Button") to structure like
+		// { cls: dijit.Button, params: {label: "string", disabled: "boolean"} }
+	};
+	
+	function getClassInfo(/*String*/ className){
+		// className:
+		//		fully qualified name (like "dijit.form.Button")
+		// returns:
+		//		structure like
+		//			{ 
+		//				cls: dijit.Button, 
+		//				params: { label: "string", disabled: "boolean"}
+		//			}
+
+		if(!instanceClasses[className]){
+			// get pointer to widget class
+			var cls = d.getObject(className);
+			if(!d.isFunction(cls)){
+				throw new Error("Could not load class '" + className +
+					"'. Did you spell the name correctly and use a full path, like 'dijit.form.Button'?");
+			}
+			var proto = cls.prototype;
+	
+			// get table of parameter names & types
+			var params = {}, dummyClass = {};
+			for(var name in proto){
+				if(name.charAt(0)=="_"){ continue; } 	// skip internal properties
+				if(name in dummyClass){ continue; }		// skip "constructor" and "toString"
+				var defVal = proto[name];
+				params[name]=val2type(defVal);
+			}
+
+			instanceClasses[className] = { cls: cls, params: params };
+		}
+		return instanceClasses[className];
+	}
+
+	this._functionFromScript = function(script){
+		var preamble = "";
+		var suffix = "";
+		var argsStr = script.getAttribute("args");
+		if(argsStr){
+			d.forEach(argsStr.split(/\s*,\s*/), function(part, idx){
+				preamble += "var "+part+" = arguments["+idx+"]; ";
+			});
+		}
+		var withStr = script.getAttribute("with");
+		if(withStr && withStr.length){
+			d.forEach(withStr.split(/\s*,\s*/), function(part){
+				preamble += "with("+part+"){";
+				suffix += "}";
+			});
+		}
+		return new Function(preamble+script.innerHTML+suffix);
+	}
+
+	this.instantiate = function(/* Array */nodes, /* Object? */mixin){
+		// summary:
+		//		Takes array of nodes, and turns them into class instances and
+		//		potentially calls a layout method to allow them to connect with
+		//		any children		
+		// mixin: Object
+		//		An object that will be mixed in with each node in the array.
+		//		Values in the mixin will override values in the node, if they
+		//		exist.
+		var thelist = [];
+		mixin = mixin||{};
+		d.forEach(nodes, function(node){
+			if(!node){ return; }
+			var type = dtName in mixin?mixin[dtName]:node.getAttribute(dtName);
+			if(!type || !type.length){ return; }
+			var clsInfo = getClassInfo(type),
+				clazz = clsInfo.cls,
+				ps = clazz._noScript || clazz.prototype._noScript;
+
+			// read parameters (ie, attributes).
+			// clsInfo.params lists expected params like {"checked": "boolean", "n": "number"}
+			var params = {},
+				attributes = node.attributes;
+			for(var name in clsInfo.params){
+				var item = name in mixin?{value:mixin[name],specified:true}:attributes.getNamedItem(name);
+				if(!item || (!item.specified && (!dojo.isIE || name.toLowerCase()!="value"))){ continue; }
+				var value = item.value;
+				// Deal with IE quirks for 'class' and 'style'
+				switch(name){
+				case "class":
+					value = "className" in mixin?mixin.className:node.className;
+					break;
+				case "style":
+					value = "style" in mixin?mixin.style:(node.style && node.style.cssText); // FIXME: Opera?
+				}
+				var _type = clsInfo.params[name];
+				if(typeof value == "string"){
+					params[name] = str2obj(value, _type);
+				}else{
+					params[name] = value;
+				}
+			}
+
+			// Process <script type="dojo/*"> script tags
+			// <script type="dojo/method" event="foo"> tags are added to params, and passed to
+			// the widget on instantiation.
+			// <script type="dojo/method"> tags (with no event) are executed after instantiation
+			// <script type="dojo/connect" event="foo"> tags are dojo.connected after instantiation
+			// note: dojo/* script tags cannot exist in self closing widgets, like <input />
+			if(!ps){
+				var connects = [],	// functions to connect after instantiation
+					calls = [];		// functions to call after instantiation
+
+				d.query("> script[type^='dojo/']", node).orphan().forEach(function(script){
+					var event = script.getAttribute("event"),
+						type = script.getAttribute("type"),
+						nf = d.parser._functionFromScript(script);
+					if(event){
+						if(type == "dojo/connect"){
+							connects.push({event: event, func: nf});
+						}else{
+							params[event] = nf;
+						}
+					}else{
+						calls.push(nf);
+					}
+				});
+			}
+
+			var markupFactory = clazz["markupFactory"];
+			if(!markupFactory && clazz["prototype"]){
+				markupFactory = clazz.prototype["markupFactory"];
+			}
+			// create the instance
+			var instance = markupFactory ? markupFactory(params, node, clazz) : new clazz(params, node);
+			thelist.push(instance);
+
+			// map it to the JS namespace if that makes sense
+			var jsname = node.getAttribute("jsId");
+			if(jsname){
+				d.setObject(jsname, instance);
+			}
+
+			// process connections and startup functions
+			if(!ps){
+				d.forEach(connects, function(connect){
+					d.connect(instance, connect.event, null, connect.func);
+				});
+				d.forEach(calls, function(func){
+					func.call(instance);
+				});
+			}
+		});
+
+		// Call startup on each top level instance if it makes sense (as for
+		// widgets).  Parent widgets will recursively call startup on their
+		// (non-top level) children
+		d.forEach(thelist, function(instance){
+			if(	instance  && 
+				instance.startup &&
+				!instance._started && 
+				(!instance.getParent || !instance.getParent())
+			){
+				instance.startup();
+			}
+		});
+		return thelist;
+	};
+
+	this.parse = function(/*DomNode?*/ rootNode){
+		// summary:
+		//		Search specified node (or root node) recursively for class instances,
+		//		and instantiate them Searches for
+		//		dojoType="qualified.class.name"
+		var list = d.query(qry, rootNode);
+		// go build the object instances
+		var instances = this.instantiate(list);
+		return instances;
+	};
+}();
+
+//Register the parser callback. It should be the first callback
+//after the a11y test.
+
+(function(){
+	var parseRunner = function(){ 
+		if(dojo.config["parseOnLoad"] == true){
+			dojo.parser.parse(); 
+		}
+	};
+
+	// FIXME: need to clobber cross-dependency!!
+	if(dojo.exists("dijit.wai.onload") && (dijit.wai.onload === dojo._loaders[0])){
+		dojo._loaders.splice(1, 0, parseRunner);
+	}else{
+		dojo._loaders.unshift(parseRunner);
+	}
+})();
+
+}
+
+if(!dojo._hasResource["dojo.data.util.filter"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.data.util.filter"] = true;
+dojo.provide("dojo.data.util.filter");
+
+dojo.data.util.filter.patternToRegExp = function(/*String*/pattern, /*boolean?*/ ignoreCase){
+	//	summary:  
+	//		Helper function to convert a simple pattern to a regular expression for matching.
+	//	description:
+	//		Returns a regular expression object that conforms to the defined conversion rules.
+	//		For example:  
+	//			ca*   -> /^ca.*$/
+	//			*ca*  -> /^.*ca.*$/
+	//			*c\*a*  -> /^.*c\*a.*$/
+	//			*c\*a?*  -> /^.*c\*a..*$/
+	//			and so on.
+	//
+	//	pattern: string
+	//		A simple matching pattern to convert that follows basic rules:
+	//			* Means match anything, so ca* means match anything starting with ca
+	//			? Means match single character.  So, b?b will match to bob and bab, and so on.
+	//      	\ is an escape character.  So for example, \* means do not treat * as a match, but literal character *.
+	//				To use a \ as a character in the string, it must be escaped.  So in the pattern it should be 
+	//				represented by \\ to be treated as an ordinary \ character instead of an escape.
+	//
+	//	ignoreCase:
+	//		An optional flag to indicate if the pattern matching should be treated as case-sensitive or not when comparing
+	//		By default, it is assumed case sensitive.
+
+	var rxp = "^";
+	var c = null;
+	for(var i = 0; i < pattern.length; i++){
+		c = pattern.charAt(i);
+		switch (c) {
+			case '\\':
+				rxp += c;
+				i++;
+				rxp += pattern.charAt(i);
+				break;
+			case '*':
+				rxp += ".*"; break;
+			case '?':
+				rxp += "."; break;
+			case '$':
+			case '^':
+			case '/':
+			case '+':
+			case '.':
+			case '|':
+			case '(':
+			case ')':
+			case '{':
+			case '}':
+			case '[':
+			case ']':
+				rxp += "\\"; //fallthrough
+			default:
+				rxp += c;
+		}
+	}
+	rxp += "$";
+	if(ignoreCase){
+		return new RegExp(rxp,"mi"); //RegExp
+	}else{
+		return new RegExp(rxp,"m"); //RegExp
+	}
+	
+};
+
+}
+
+if(!dojo._hasResource["dojo.data.util.sorter"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.data.util.sorter"] = true;
+dojo.provide("dojo.data.util.sorter");
+
+dojo.data.util.sorter.basicComparator = function(	/*anything*/ a, 
+													/*anything*/ b){
+	//	summary:  
+	//		Basic comparision function that compares if an item is greater or less than another item
+	//	description:  
+	//		returns 1 if a > b, -1 if a < b, 0 if equal.
+	//		'null' values (null, undefined) are treated as larger values so that they're pushed to the end of the list.
+	//		And compared to each other, null is equivalent to undefined.
+	
+	//null is a problematic compare, so if null, we set to undefined.
+	//Makes the check logic simple, compact, and consistent
+	//And (null == undefined) === true, so the check later against null
+	//works for undefined and is less bytes.
+	var r = -1;
+	if(a === null){
+		a = undefined;
+	}
+	if(b === null){
+		b = undefined;
+	}
+	if(a == b){
+		r = 0; 
+	}else if(a > b || a == null){
+		r = 1; 
+	}
+	return r; //int {-1,0,1}
+};
+
+dojo.data.util.sorter.createSortFunction = function(	/* attributes array */sortSpec,
+														/*dojo.data.core.Read*/ store){
+	//	summary:  
+	//		Helper function to generate the sorting function based off the list of sort attributes.
+	//	description:  
+	//		The sort function creation will look for a property on the store called 'comparatorMap'.  If it exists
+	//		it will look in the mapping for comparisons function for the attributes.  If one is found, it will
+	//		use it instead of the basic comparator, which is typically used for strings, ints, booleans, and dates.
+	//		Returns the sorting function for this particular list of attributes and sorting directions.
+	//
+	//	sortSpec: array
+	//		A JS object that array that defines out what attribute names to sort on and whether it should be descenting or asending.
+	//		The objects should be formatted as follows:
+	//		{
+	//			attribute: "attributeName-string" || attribute,
+	//			descending: true|false;   // Default is false.
+	//		}
+	//	store: object
+	//		The datastore object to look up item values from.
+	//
+	var sortFunctions=[];   
+
+	function createSortFunction(attr, dir){
+		return function(itemA, itemB){
+			var a = store.getValue(itemA, attr);
+			var b = store.getValue(itemB, attr);
+			//See if we have a override for an attribute comparison.
+			var comparator = null;
+			if(store.comparatorMap){
+				if(typeof attr !== "string"){
+					 attr = store.getIdentity(attr);
+				}
+				comparator = store.comparatorMap[attr]||dojo.data.util.sorter.basicComparator;
+			}
+			comparator = comparator||dojo.data.util.sorter.basicComparator; 
+			return dir * comparator(a,b); //int
+		};
+	}
+	var sortAttribute;
+	for(var i = 0; i < sortSpec.length; i++){
+		sortAttribute = sortSpec[i];
+		if(sortAttribute.attribute){
+			var direction = (sortAttribute.descending) ? -1 : 1;
+			sortFunctions.push(createSortFunction(sortAttribute.attribute, direction));
+		}
+	}
+
+	return function(rowA, rowB){
+		var i=0;
+		while(i < sortFunctions.length){
+			var ret = sortFunctions[i++](rowA, rowB);
+			if(ret !== 0){
+				return ret;//int
+			}
+		}
+		return 0; //int  
+	};  //  Function
+};
+
+}
+
+if(!dojo._hasResource["dojo.data.util.simpleFetch"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.data.util.simpleFetch"] = true;
+dojo.provide("dojo.data.util.simpleFetch");
+
+
+dojo.data.util.simpleFetch.fetch = function(/* Object? */ request){
+	//	summary:
+	//		The simpleFetch mixin is designed to serve as a set of function(s) that can
+	//		be mixed into other datastore implementations to accelerate their development.  
+	//		The simpleFetch mixin should work well for any datastore that can respond to a _fetchItems() 
+	//		call by returning an array of all the found items that matched the query.  The simpleFetch mixin
+	//		is not designed to work for datastores that respond to a fetch() call by incrementally
+	//		loading items, or sequentially loading partial batches of the result
+	//		set.  For datastores that mixin simpleFetch, simpleFetch 
+	//		implements a fetch method that automatically handles eight of the fetch()
+	//		arguments -- onBegin, onItem, onComplete, onError, start, count, sort and scope
+	//		The class mixing in simpleFetch should not implement fetch(),
+	//		but should instead implement a _fetchItems() method.  The _fetchItems() 
+	//		method takes three arguments, the keywordArgs object that was passed 
+	//		to fetch(), a callback function to be called when the result array is
+	//		available, and an error callback to be called if something goes wrong.
+	//		The _fetchItems() method should ignore any keywordArgs parameters for
+	//		start, count, onBegin, onItem, onComplete, onError, sort, and scope.  
+	//		The _fetchItems() method needs to correctly handle any other keywordArgs
+	//		parameters, including the query parameter and any optional parameters 
+	//		(such as includeChildren).  The _fetchItems() method should create an array of 
+	//		result items and pass it to the fetchHandler along with the original request object 
+	//		-- or, the _fetchItems() method may, if it wants to, create an new request object 
+	//		with other specifics about the request that are specific to the datastore and pass 
+	//		that as the request object to the handler.
+	//
+	//		For more information on this specific function, see dojo.data.api.Read.fetch()
+	request = request || {};
+	if(!request.store){
+		request.store = this;
+	}
+	var self = this;
+
+	var _errorHandler = function(errorData, requestObject){
+		if(requestObject.onError){
+			var scope = requestObject.scope || dojo.global;
+			requestObject.onError.call(scope, errorData, requestObject);
+		}
+	};
+
+	var _fetchHandler = function(items, requestObject){
+		var oldAbortFunction = requestObject.abort || null;
+		var aborted = false;
+
+		var startIndex = requestObject.start?requestObject.start:0;
+		var endIndex   = (requestObject.count && (requestObject.count !== Infinity))?(startIndex + requestObject.count):items.length;
+
+		requestObject.abort = function(){
+			aborted = true;
+			if(oldAbortFunction){
+				oldAbortFunction.call(requestObject);
+			}
+		};
+
+		var scope = requestObject.scope || dojo.global;
+		if(!requestObject.store){
+			requestObject.store = self;
+		}
+		if(requestObject.onBegin){
+			requestObject.onBegin.call(scope, items.length, requestObject);
+		}
+		if(requestObject.sort){
+			items.sort(dojo.data.util.sorter.createSortFunction(requestObject.sort, self));
+		}
+		if(requestObject.onItem){
+			for(var i = startIndex; (i < items.length) && (i < endIndex); ++i){
+				var item = items[i];
+				if(!aborted){
+					requestObject.onItem.call(scope, item, requestObject);
+				}
+			}
+		}
+		if(requestObject.onComplete && !aborted){
+			var subset = null;
+			if (!requestObject.onItem) {
+				subset = items.slice(startIndex, endIndex);
+			}
+			requestObject.onComplete.call(scope, subset, requestObject);   
+		}
+	};
+	this._fetchItems(request, _fetchHandler, _errorHandler);
+	return request;	// Object
+};
+
+}
+
+if(!dojo._hasResource["dojo.data.ItemFileReadStore"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.data.ItemFileReadStore"] = true;
+dojo.provide("dojo.data.ItemFileReadStore");
+
+
+
+
+
+dojo.declare("dojo.data.ItemFileReadStore", null,{
+	//	summary:
+	//		The ItemFileReadStore implements the dojo.data.api.Read API and reads
+	//		data from JSON files that have contents in this format --
+	//		{ items: [
+	//			{ name:'Kermit', color:'green', age:12, friends:['Gonzo', {_reference:{name:'Fozzie Bear'}}]},
+	//			{ name:'Fozzie Bear', wears:['hat', 'tie']},
+	//			{ name:'Miss Piggy', pets:'Foo-Foo'}
+	//		]}
+	//		Note that it can also contain an 'identifer' property that specified which attribute on the items 
+	//		in the array of items that acts as the unique identifier for that item.
+	//
+	constructor: function(/* Object */ keywordParameters){
+		//	summary: constructor
+		//	keywordParameters: {url: String}
+		//	keywordParameters: {data: jsonObject}
+		//	keywordParameters: {typeMap: object)
+		//		The structure of the typeMap object is as follows:
+		//		{
+		//			type0: function || object,
+		//			type1: function || object,
+		//			...
+		//			typeN: function || object
+		//		}
+		//		Where if it is a function, it is assumed to be an object constructor that takes the 
+		//		value of _value as the initialization parameters.  If it is an object, then it is assumed
+		//		to be an object of general form:
+		//		{
+		//			type: function, //constructor.
+		//			deserialize:	function(value) //The function that parses the value and constructs the object defined by type appropriately.
+		//		}
+	
+		this._arrayOfAllItems = [];
+		this._arrayOfTopLevelItems = [];
+		this._loadFinished = false;
+		this._jsonFileUrl = keywordParameters.url;
+		this._jsonData = keywordParameters.data;
+		this._datatypeMap = keywordParameters.typeMap || {};
+		if(!this._datatypeMap['Date']){
+			//If no default mapping for dates, then set this as default.
+			//We use the dojo.date.stamp here because the ISO format is the 'dojo way'
+			//of generically representing dates.
+			this._datatypeMap['Date'] = {
+											type: Date,
+											deserialize: function(value){
+												return dojo.date.stamp.fromISOString(value);
+											}
+										};
+		}
+		this._features = {'dojo.data.api.Read':true, 'dojo.data.api.Identity':true};
+		this._itemsByIdentity = null;
+		this._storeRefPropName = "_S";  // Default name for the store reference to attach to every item.
+		this._itemNumPropName = "_0"; // Default Item Id for isItem to attach to every item.
+		this._rootItemPropName = "_RI"; // Default Item Id for isItem to attach to every item.
+		this._reverseRefMap = "_RRM"; // Default attribute for constructing a reverse reference map for use with reference integrity
+		this._loadInProgress = false;	//Got to track the initial load to prevent duelling loads of the dataset.
+		this._queuedFetches = [];
+		if(keywordParameters.urlPreventCache !== undefined){
+			this.urlPreventCache = keywordParameters.urlPreventCache?true:false;
+		}
+		if(keywordParameters.clearOnClose){
+			this.clearOnClose = true;
+		}
+	},
+	
+	url: "",	// use "" rather than undefined for the benefit of the parser (#3539)
+
+	data: null,	// define this so that the parser can populate it
+
+	typeMap: null, //Define so parser can populate.
+	
+	//Parameter to allow users to specify if a close call should force a reload or not.
+	//By default, it retains the old behavior of not clearing if close is called.  But
+	//if set true, the store will be reset to default state.  Note that by doing this,
+	//all item handles will become invalid and a new fetch must be issued.
+	clearOnClose: false,
+
+	//Parameter to allow specifying if preventCache should be passed to the xhrGet call or not when loading data from a url.  
+	//Note this does not mean the store calls the server on each fetch, only that the data load has preventCache set as an option.
+	//Added for tracker: #6072
+	urlPreventCache: false,  
+
+	_assertIsItem: function(/* item */ item){
+		//	summary:
+		//		This function tests whether the item passed in is indeed an item in the store.
+		//	item: 
+		//		The item to test for being contained by the store.
+		if(!this.isItem(item)){ 
+			throw new Error("dojo.data.ItemFileReadStore: Invalid item argument.");
+		}
+	},
+
+	_assertIsAttribute: function(/* attribute-name-string */ attribute){
+		//	summary:
+		//		This function tests whether the item passed in is indeed a valid 'attribute' like type for the store.
+		//	attribute: 
+		//		The attribute to test for being contained by the store.
+		if(typeof attribute !== "string"){ 
+			throw new Error("dojo.data.ItemFileReadStore: Invalid attribute argument.");
+		}
+	},
+
+	getValue: function(	/* item */ item, 
+						/* attribute-name-string */ attribute, 
+						/* value? */ defaultValue){
+		//	summary: 
+		//		See dojo.data.api.Read.getValue()
+		var values = this.getValues(item, attribute);
+		return (values.length > 0)?values[0]:defaultValue; // mixed
+	},
+
+	getValues: function(/* item */ item, 
+						/* attribute-name-string */ attribute){
+		//	summary: 
+		//		See dojo.data.api.Read.getValues()
+
+		this._assertIsItem(item);
+		this._assertIsAttribute(attribute);
+		return item[attribute] || []; // Array
+	},
+
+	getAttributes: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Read.getAttributes()
+		this._assertIsItem(item);
+		var attributes = [];
+		for(var key in item){
+			// Save off only the real item attributes, not the special id marks for O(1) isItem.
+			if((key !== this._storeRefPropName) && (key !== this._itemNumPropName) && (key !== this._rootItemPropName) && (key !== this._reverseRefMap)){
+				attributes.push(key);
+			}
+		}
+		return attributes; // Array
+	},
+
+	hasAttribute: function(	/* item */ item,
+							/* attribute-name-string */ attribute) {
+		//	summary: 
+		//		See dojo.data.api.Read.hasAttribute()
+		return this.getValues(item, attribute).length > 0;
+	},
+
+	containsValue: function(/* item */ item, 
+							/* attribute-name-string */ attribute, 
+							/* anything */ value){
+		//	summary: 
+		//		See dojo.data.api.Read.containsValue()
+		var regexp = undefined;
+		if(typeof value === "string"){
+			regexp = dojo.data.util.filter.patternToRegExp(value, false);
+		}
+		return this._containsValue(item, attribute, value, regexp); //boolean.
+	},
+
+	_containsValue: function(	/* item */ item, 
+								/* attribute-name-string */ attribute, 
+								/* anything */ value,
+								/* RegExp?*/ regexp){
+		//	summary: 
+		//		Internal function for looking at the values contained by the item.
+		//	description: 
+		//		Internal function for looking at the values contained by the item.  This 
+		//		function allows for denoting if the comparison should be case sensitive for
+		//		strings or not (for handling filtering cases where string case should not matter)
+		//	
+		//	item:
+		//		The data item to examine for attribute values.
+		//	attribute:
+		//		The attribute to inspect.
+		//	value:	
+		//		The value to match.
+		//	regexp:
+		//		Optional regular expression generated off value if value was of string type to handle wildcarding.
+		//		If present and attribute values are string, then it can be used for comparison instead of 'value'
+		return dojo.some(this.getValues(item, attribute), function(possibleValue){
+			if(possibleValue !== null && !dojo.isObject(possibleValue) && regexp){
+				if(possibleValue.toString().match(regexp)){
+					return true; // Boolean
+				}
+			}else if(value === possibleValue){
+				return true; // Boolean
+			}
+		});
+	},
+
+	isItem: function(/* anything */ something){
+		//	summary: 
+		//		See dojo.data.api.Read.isItem()
+		if(something && something[this._storeRefPropName] === this){
+			if(this._arrayOfAllItems[something[this._itemNumPropName]] === something){
+				return true;
+			}
+		}
+		return false; // Boolean
+	},
+
+	isItemLoaded: function(/* anything */ something){
+		//	summary: 
+		//		See dojo.data.api.Read.isItemLoaded()
+		return this.isItem(something); //boolean
+	},
+
+	loadItem: function(/* object */ keywordArgs){
+		//	summary: 
+		//		See dojo.data.api.Read.loadItem()
+		this._assertIsItem(keywordArgs.item);
+	},
+
+	getFeatures: function(){
+		//	summary: 
+		//		See dojo.data.api.Read.getFeatures()
+		return this._features; //Object
+	},
+
+	getLabel: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Read.getLabel()
+		if(this._labelAttr && this.isItem(item)){
+			return this.getValue(item,this._labelAttr); //String
+		}
+		return undefined; //undefined
+	},
+
+	getLabelAttributes: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Read.getLabelAttributes()
+		if(this._labelAttr){
+			return [this._labelAttr]; //array
+		}
+		return null; //null
+	},
+
+	_fetchItems: function(	/* Object */ keywordArgs, 
+							/* Function */ findCallback, 
+							/* Function */ errorCallback){
+		//	summary: 
+		//		See dojo.data.util.simpleFetch.fetch()
+		var self = this;
+		var filter = function(requestArgs, arrayOfItems){
+			var items = [];
+			var i, key;
+			if(requestArgs.query){
+				var value;
+				var ignoreCase = requestArgs.queryOptions ? requestArgs.queryOptions.ignoreCase : false; 
+
+				//See if there are any string values that can be regexp parsed first to avoid multiple regexp gens on the
+				//same value for each item examined.  Much more efficient.
+				var regexpList = {};
+				for(key in requestArgs.query){
+					value = requestArgs.query[key];
+					if(typeof value === "string"){
+						regexpList[key] = dojo.data.util.filter.patternToRegExp(value, ignoreCase);
+					}
+				}
+
+				for(i = 0; i < arrayOfItems.length; ++i){
+					var match = true;
+					var candidateItem = arrayOfItems[i];
+					if(candidateItem === null){
+						match = false;
+					}else{
+						for(key in requestArgs.query) {
+							value = requestArgs.query[key];
+							if (!self._containsValue(candidateItem, key, value, regexpList[key])){
+								match = false;
+							}
+						}
+					}
+					if(match){
+						items.push(candidateItem);
+					}
+				}
+				findCallback(items, requestArgs);
+			}else{
+				// We want a copy to pass back in case the parent wishes to sort the array. 
+				// We shouldn't allow resort of the internal list, so that multiple callers 
+				// can get lists and sort without affecting each other.  We also need to
+				// filter out any null values that have been left as a result of deleteItem()
+				// calls in ItemFileWriteStore.
+				for(i = 0; i < arrayOfItems.length; ++i){
+					var item = arrayOfItems[i];
+					if(item !== null){
+						items.push(item);
+					}
+				}
+				findCallback(items, requestArgs);
+			}
+		};
+
+		if(this._loadFinished){
+			filter(keywordArgs, this._getItemsArray(keywordArgs.queryOptions));
+		}else{
+
+			if(this._jsonFileUrl){
+				//If fetches come in before the loading has finished, but while
+				//a load is in progress, we have to defer the fetching to be 
+				//invoked in the callback.
+				if(this._loadInProgress){
+					this._queuedFetches.push({args: keywordArgs, filter: filter});
+				}else{
+					this._loadInProgress = true;
+					var getArgs = {
+							url: self._jsonFileUrl, 
+							handleAs: "json-comment-optional",
+							preventCache: this.urlPreventCache
+						};
+					var getHandler = dojo.xhrGet(getArgs);
+					getHandler.addCallback(function(data){
+						try{
+							self._getItemsFromLoadedData(data);
+							self._loadFinished = true;
+							self._loadInProgress = false;
+							
+							filter(keywordArgs, self._getItemsArray(keywordArgs.queryOptions));
+							self._handleQueuedFetches();
+						}catch(e){
+							self._loadFinished = true;
+							self._loadInProgress = false;
+							errorCallback(e, keywordArgs);
+						}
+					});
+					getHandler.addErrback(function(error){
+						self._loadInProgress = false;
+						errorCallback(error, keywordArgs);
+					});
+
+					//Wire up the cancel to abort of the request
+					//This call cancel on the deferred if it hasn't been called
+					//yet and then will chain to the simple abort of the
+					//simpleFetch keywordArgs
+					var oldAbort = null;
+					if(keywordArgs.abort){
+						oldAbort = keywordArgs.abort;
+					}
+					keywordArgs.abort = function(){
+						var df = getHandler;
+						if (df && df.fired === -1){
+							df.cancel();
+							df = null;
+						}
+						if(oldAbort){
+							oldAbort.call(keywordArgs);
+						}
+					};
+				}
+			}else if(this._jsonData){
+				try{
+					this._loadFinished = true;
+					this._getItemsFromLoadedData(this._jsonData);
+					this._jsonData = null;
+					filter(keywordArgs, this._getItemsArray(keywordArgs.queryOptions));
+				}catch(e){
+					errorCallback(e, keywordArgs);
+				}
+			}else{
+				errorCallback(new Error("dojo.data.ItemFileReadStore: No JSON source data was provided as either URL or a nested Javascript object."), keywordArgs);
+			}
+		}
+	},
+
+	_handleQueuedFetches: function(){
+		//	summary: 
+		//		Internal function to execute delayed request in the store.
+		//Execute any deferred fetches now.
+		if (this._queuedFetches.length > 0) {
+			for(var i = 0; i < this._queuedFetches.length; i++){
+				var fData = this._queuedFetches[i];
+				var delayedQuery = fData.args;
+				var delayedFilter = fData.filter;
+				if(delayedFilter){
+					delayedFilter(delayedQuery, this._getItemsArray(delayedQuery.queryOptions)); 
+				}else{
+					this.fetchItemByIdentity(delayedQuery);
+				}
+			}
+			this._queuedFetches = [];
+		}
+	},
+
+	_getItemsArray: function(/*object?*/queryOptions){
+		//	summary: 
+		//		Internal function to determine which list of items to search over.
+		//	queryOptions: The query options parameter, if any.
+		if(queryOptions && queryOptions.deep) {
+			return this._arrayOfAllItems; 
+		}
+		return this._arrayOfTopLevelItems;
+	},
+
+	close: function(/*dojo.data.api.Request || keywordArgs || null */ request){
+		 //	summary: 
+		 //		See dojo.data.api.Read.close()
+		 if(this.clearOnClose && (this._jsonFileUrl !== "")){
+			 //Reset all internalsback to default state.  This will force a reload
+			 //on next fetch, but only if the data came from a url.  Passed in data
+			 //means it should not clear the data.
+			 this._arrayOfAllItems = [];
+			 this._arrayOfTopLevelItems = [];
+			 this._loadFinished = false;
+			 this._itemsByIdentity = null;
+			 this._loadInProgress = false;
+			 this._queuedFetches = [];
+		 }
+	},
+
+	_getItemsFromLoadedData: function(/* Object */ dataObject){
+		//	summary:
+		//		Function to parse the loaded data into item format and build the internal items array.
+		//	description:
+		//		Function to parse the loaded data into item format and build the internal items array.
+		//
+		//	dataObject:
+		//		The JS data object containing the raw data to convery into item format.
+		//
+		// 	returns: array
+		//		Array of items in store item format.
+		
+		// First, we define a couple little utility functions...
+		var addingArrays = false;
+		
+		function valueIsAnItem(/* anything */ aValue){
+			// summary:
+			//		Given any sort of value that could be in the raw json data,
+			//		return true if we should interpret the value as being an
+			//		item itself, rather than a literal value or a reference.
+			// example:
+			// 	|	false == valueIsAnItem("Kermit");
+			// 	|	false == valueIsAnItem(42);
+			// 	|	false == valueIsAnItem(new Date());
+			// 	|	false == valueIsAnItem({_type:'Date', _value:'May 14, 1802'});
+			// 	|	false == valueIsAnItem({_reference:'Kermit'});
+			// 	|	true == valueIsAnItem({name:'Kermit', color:'green'});
+			// 	|	true == valueIsAnItem({iggy:'pop'});
+			// 	|	true == valueIsAnItem({foo:42});
+			var isItem = (
+				(aValue !== null) &&
+				(typeof aValue === "object") &&
+				(!dojo.isArray(aValue) || addingArrays) &&
+				(!dojo.isFunction(aValue)) &&
+				(aValue.constructor == Object || dojo.isArray(aValue)) &&
+				(typeof aValue._reference === "undefined") && 
+				(typeof aValue._type === "undefined") && 
+				(typeof aValue._value === "undefined")
+			);
+			return isItem;
+		}
+		
+		var self = this;
+		function addItemAndSubItemsToArrayOfAllItems(/* Item */ anItem){
+			self._arrayOfAllItems.push(anItem);
+			for(var attribute in anItem){
+				var valueForAttribute = anItem[attribute];
+				if(valueForAttribute){
+					if(dojo.isArray(valueForAttribute)){
+						var valueArray = valueForAttribute;
+						for(var k = 0; k < valueArray.length; ++k){
+							var singleValue = valueArray[k];
+							if(valueIsAnItem(singleValue)){
+								addItemAndSubItemsToArrayOfAllItems(singleValue);
+							}
+						}
+					}else{
+						if(valueIsAnItem(valueForAttribute)){
+							addItemAndSubItemsToArrayOfAllItems(valueForAttribute);
+						}
+					}
+				}
+			}
+		}
+
+		this._labelAttr = dataObject.label;
+
+		// We need to do some transformations to convert the data structure
+		// that we read from the file into a format that will be convenient
+		// to work with in memory.
+
+		// Step 1: Walk through the object hierarchy and build a list of all items
+		var i;
+		var item;
+		this._arrayOfAllItems = [];
+		this._arrayOfTopLevelItems = dataObject.items;
+
+		for(i = 0; i < this._arrayOfTopLevelItems.length; ++i){
+			item = this._arrayOfTopLevelItems[i];
+			if(dojo.isArray(item)){
+				addingArrays = true;
+			}
+			addItemAndSubItemsToArrayOfAllItems(item);
+			item[this._rootItemPropName]=true;
+		}
+
+		// Step 2: Walk through all the attribute values of all the items, 
+		// and replace single values with arrays.  For example, we change this:
+		//		{ name:'Miss Piggy', pets:'Foo-Foo'}
+		// into this:
+		//		{ name:['Miss Piggy'], pets:['Foo-Foo']}
+		// 
+		// We also store the attribute names so we can validate our store  
+		// reference and item id special properties for the O(1) isItem
+		var allAttributeNames = {};
+		var key;
+
+		for(i = 0; i < this._arrayOfAllItems.length; ++i){
+			item = this._arrayOfAllItems[i];
+			for(key in item){
+				if (key !== this._rootItemPropName)
+				{
+					var value = item[key];
+					if(value !== null){
+						if(!dojo.isArray(value)){
+							item[key] = [value];
+						}
+					}else{
+						item[key] = [null];
+					}
+				}
+				allAttributeNames[key]=key;
+			}
+		}
+
+		// Step 3: Build unique property names to use for the _storeRefPropName and _itemNumPropName
+		// This should go really fast, it will generally never even run the loop.
+		while(allAttributeNames[this._storeRefPropName]){
+			this._storeRefPropName += "_";
+		}
+		while(allAttributeNames[this._itemNumPropName]){
+			this._itemNumPropName += "_";
+		}
+		while(allAttributeNames[this._reverseRefMap]){
+			this._reverseRefMap += "_";
+		}
+
+		// Step 4: Some data files specify an optional 'identifier', which is 
+		// the name of an attribute that holds the identity of each item. 
+		// If this data file specified an identifier attribute, then build a 
+		// hash table of items keyed by the identity of the items.
+		var arrayOfValues;
+
+		var identifier = dataObject.identifier;
+		if(identifier){
+			this._itemsByIdentity = {};
+			this._features['dojo.data.api.Identity'] = identifier;
+			for(i = 0; i < this._arrayOfAllItems.length; ++i){
+				item = this._arrayOfAllItems[i];
+				arrayOfValues = item[identifier];
+				var identity = arrayOfValues[0];
+				if(!this._itemsByIdentity[identity]){
+					this._itemsByIdentity[identity] = item;
+				}else{
+					if(this._jsonFileUrl){
+						throw new Error("dojo.data.ItemFileReadStore:  The json data as specified by: [" + this._jsonFileUrl + "] is malformed.  Items within the list have identifier: [" + identifier + "].  Value collided: [" + identity + "]");
+					}else if(this._jsonData){
+						throw new Error("dojo.data.ItemFileReadStore:  The json data provided by the creation arguments is malformed.  Items within the list have identifier: [" + identifier + "].  Value collided: [" + identity + "]");
+					}
+				}
+			}
+		}else{
+			this._features['dojo.data.api.Identity'] = Number;
+		}
+
+		// Step 5: Walk through all the items, and set each item's properties 
+		// for _storeRefPropName and _itemNumPropName, so that store.isItem() will return true.
+		for(i = 0; i < this._arrayOfAllItems.length; ++i){
+			item = this._arrayOfAllItems[i];
+			item[this._storeRefPropName] = this;
+			item[this._itemNumPropName] = i;
+		}
+
+		// Step 6: We walk through all the attribute values of all the items,
+		// looking for type/value literals and item-references.
+		//
+		// We replace item-references with pointers to items.  For example, we change:
+		//		{ name:['Kermit'], friends:[{_reference:{name:'Miss Piggy'}}] }
+		// into this:
+		//		{ name:['Kermit'], friends:[miss_piggy] } 
+		// (where miss_piggy is the object representing the 'Miss Piggy' item).
+		//
+		// We replace type/value pairs with typed-literals.  For example, we change:
+		//		{ name:['Nelson Mandela'], born:[{_type:'Date', _value:'July 18, 1918'}] }
+		// into this:
+		//		{ name:['Kermit'], born:(new Date('July 18, 1918')) } 
+		//
+		// We also generate the associate map for all items for the O(1) isItem function.
+		for(i = 0; i < this._arrayOfAllItems.length; ++i){
+			item = this._arrayOfAllItems[i]; // example: { name:['Kermit'], friends:[{_reference:{name:'Miss Piggy'}}] }
+			for(key in item){
+				arrayOfValues = item[key]; // example: [{_reference:{name:'Miss Piggy'}}]
+				for(var j = 0; j < arrayOfValues.length; ++j) {
+					value = arrayOfValues[j]; // example: {_reference:{name:'Miss Piggy'}}
+					if(value !== null && typeof value == "object"){
+						if(value._type && value._value){
+							var type = value._type; // examples: 'Date', 'Color', or 'ComplexNumber'
+							var mappingObj = this._datatypeMap[type]; // examples: Date, dojo.Color, foo.math.ComplexNumber, {type: dojo.Color, deserialize(value){ return new dojo.Color(value)}}
+							if(!mappingObj){ 
+								throw new Error("dojo.data.ItemFileReadStore: in the typeMap constructor arg, no object class was specified for the datatype '" + type + "'");
+							}else if(dojo.isFunction(mappingObj)){
+								arrayOfValues[j] = new mappingObj(value._value);
+							}else if(dojo.isFunction(mappingObj.deserialize)){
+								arrayOfValues[j] = mappingObj.deserialize(value._value);
+							}else{
+								throw new Error("dojo.data.ItemFileReadStore: Value provided in typeMap was neither a constructor, nor a an object with a deserialize function");
+							}
+						}
+						if(value._reference){
+							var referenceDescription = value._reference; // example: {name:'Miss Piggy'}
+							if(!dojo.isObject(referenceDescription)){
+								// example: 'Miss Piggy'
+								// from an item like: { name:['Kermit'], friends:[{_reference:'Miss Piggy'}]}
+								arrayOfValues[j] = this._itemsByIdentity[referenceDescription];
+							}else{
+								// example: {name:'Miss Piggy'}
+								// from an item like: { name:['Kermit'], friends:[{_reference:{name:'Miss Piggy'}}] }
+								for(var k = 0; k < this._arrayOfAllItems.length; ++k){
+									var candidateItem = this._arrayOfAllItems[k];
+									var found = true;
+									for(var refKey in referenceDescription){
+										if(candidateItem[refKey] != referenceDescription[refKey]){ 
+											found = false; 
+										}
+									}
+									if(found){ 
+										arrayOfValues[j] = candidateItem; 
+									}
+								}
+							}
+							if(this.referenceIntegrity){
+								var refItem = arrayOfValues[j];
+								if(this.isItem(refItem)){
+									this._addReferenceToMap(refItem, item, key);
+								}
+							}
+						}else if(this.isItem(value)){
+							//It's a child item (not one referenced through _reference).  
+							//We need to treat this as a referenced item, so it can be cleaned up
+							//in a write store easily.
+							if(this.referenceIntegrity){
+								this._addReferenceToMap(value, item, key);
+							}
+						}
+					}
+				}
+			}
+		}
+	},
+
+	_addReferenceToMap: function(/*item*/ refItem, /*item*/ parentItem, /*string*/ attribute){
+		 //	summary:
+		 //		Method to add an reference map entry for an item and attribute.
+		 //	description:
+		 //		Method to add an reference map entry for an item and attribute. 		 //
+		 //	refItem:
+		 //		The item that is referenced.
+		 //	parentItem:
+		 //		The item that holds the new reference to refItem.
+		 //	attribute:
+		 //		The attribute on parentItem that contains the new reference.
+		 
+		 //Stub function, does nothing.  Real processing is in ItemFileWriteStore.
+	},
+
+	getIdentity: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Identity.getIdentity()
+		var identifier = this._features['dojo.data.api.Identity'];
+		if(identifier === Number){
+			return item[this._itemNumPropName]; // Number
+		}else{
+			var arrayOfValues = item[identifier];
+			if(arrayOfValues){
+				return arrayOfValues[0]; // Object || String
+			}
+		}
+		return null; // null
+	},
+
+	fetchItemByIdentity: function(/* Object */ keywordArgs){
+		//	summary: 
+		//		See dojo.data.api.Identity.fetchItemByIdentity()
+
+		// Hasn't loaded yet, we have to trigger the load.
+		var item;
+		var scope;
+		if(!this._loadFinished){
+			var self = this;
+			if(this._jsonFileUrl){
+
+				if(this._loadInProgress){
+					this._queuedFetches.push({args: keywordArgs});
+				}else{
+					this._loadInProgress = true;
+					var getArgs = {
+							url: self._jsonFileUrl, 
+							handleAs: "json-comment-optional",
+							preventCache: this.urlPreventCache
+					};
+					var getHandler = dojo.xhrGet(getArgs);
+					getHandler.addCallback(function(data){
+						var scope =  keywordArgs.scope?keywordArgs.scope:dojo.global;
+						try{
+							self._getItemsFromLoadedData(data);
+							self._loadFinished = true;
+							self._loadInProgress = false;
+							item = self._getItemByIdentity(keywordArgs.identity);
+							if(keywordArgs.onItem){
+								keywordArgs.onItem.call(scope, item);
+							}
+							self._handleQueuedFetches();
+						}catch(error){
+							self._loadInProgress = false;
+							if(keywordArgs.onError){
+								keywordArgs.onError.call(scope, error);
+							}
+						}
+					});
+					getHandler.addErrback(function(error){
+						self._loadInProgress = false;
+						if(keywordArgs.onError){
+							var scope =  keywordArgs.scope?keywordArgs.scope:dojo.global;
+							keywordArgs.onError.call(scope, error);
+						}
+					});
+				}
+
+			}else if(this._jsonData){
+				// Passed in data, no need to xhr.
+				self._getItemsFromLoadedData(self._jsonData);
+				self._jsonData = null;
+				self._loadFinished = true;
+				item = self._getItemByIdentity(keywordArgs.identity);
+				if(keywordArgs.onItem){
+					scope =  keywordArgs.scope?keywordArgs.scope:dojo.global;
+					keywordArgs.onItem.call(scope, item);
+				}
+			} 
+		}else{
+			// Already loaded.  We can just look it up and call back.
+			item = this._getItemByIdentity(keywordArgs.identity);
+			if(keywordArgs.onItem){
+				scope =  keywordArgs.scope?keywordArgs.scope:dojo.global;
+				keywordArgs.onItem.call(scope, item);
+			}
+		}
+	},
+
+	_getItemByIdentity: function(/* Object */ identity){
+		//	summary:
+		//		Internal function to look an item up by its identity map.
+		var item = null;
+		if(this._itemsByIdentity){
+			item = this._itemsByIdentity[identity];
+		}else{
+			item = this._arrayOfAllItems[identity];
+		}
+		if(item === undefined){
+			item = null;
+		}
+		return item; // Object
+	},
+
+	getIdentityAttributes: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Identity.getIdentifierAttributes()
+		 
+		var identifier = this._features['dojo.data.api.Identity'];
+		if(identifier === Number){
+			// If (identifier === Number) it means getIdentity() just returns
+			// an integer item-number for each item.  The dojo.data.api.Identity
+			// spec says we need to return null if the identity is not composed 
+			// of attributes 
+			return null; // null
+		}else{
+			return [identifier]; // Array
+		}
+	},
+	
+	_forceLoad: function(){
+		//	summary: 
+		//		Internal function to force a load of the store if it hasn't occurred yet.  This is required
+		//		for specific functions to work properly.  
+		var self = this;
+		if(this._jsonFileUrl){
+				var getArgs = {
+					url: self._jsonFileUrl, 
+					handleAs: "json-comment-optional",
+					preventCache: this.urlPreventCache,
+					sync: true
+				};
+			var getHandler = dojo.xhrGet(getArgs);
+			getHandler.addCallback(function(data){
+				try{
+					//Check to be sure there wasn't another load going on concurrently 
+					//So we don't clobber data that comes in on it.  If there is a load going on
+					//then do not save this data.  It will potentially clobber current data.
+					//We mainly wanted to sync/wait here.
+					//TODO:  Revisit the loading scheme of this store to improve multi-initial
+					//request handling.
+					if(self._loadInProgress !== true && !self._loadFinished){
+						self._getItemsFromLoadedData(data);
+						self._loadFinished = true;
+					}else if(self._loadInProgress){
+						//Okay, we hit an error state we can't recover from.  A forced load occurred
+						//while an async load was occurring.  Since we cannot block at this point, the best
+						//that can be managed is to throw an error.
+						throw new Error("dojo.data.ItemFileReadStore:  Unable to perform a synchronous load, an async load is in progress."); 
+					}
+				}catch(e){
+					
+					throw e;
+				}
+			});
+			getHandler.addErrback(function(error){
+				throw error;
+			});
+		}else if(this._jsonData){
+			self._getItemsFromLoadedData(self._jsonData);
+			self._jsonData = null;
+			self._loadFinished = true;
+		} 
+	}
+});
+//Mix in the simple fetch implementation to this class.
+dojo.extend(dojo.data.ItemFileReadStore,dojo.data.util.simpleFetch);
+
+}
+
+if(!dojo._hasResource["dojo.data.ItemFileWriteStore"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.data.ItemFileWriteStore"] = true;
+dojo.provide("dojo.data.ItemFileWriteStore");
+
+
+dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, {
+	constructor: function(/* object */ keywordParameters){
+		//	keywordParameters: {typeMap: object)
+		//		The structure of the typeMap object is as follows:
+		//		{
+		//			type0: function || object,
+		//			type1: function || object,
+		//			...
+		//			typeN: function || object
+		//		}
+		//		Where if it is a function, it is assumed to be an object constructor that takes the 
+		//		value of _value as the initialization parameters.  It is serialized assuming object.toString()
+		//		serialization.  If it is an object, then it is assumed
+		//		to be an object of general form:
+		//		{
+		//			type: function, //constructor.
+		//			deserialize:	function(value) //The function that parses the value and constructs the object defined by type appropriately.
+		//			serialize:	function(object) //The function that converts the object back into the proper file format form.
+		//		}
+
+		// ItemFileWriteStore extends ItemFileReadStore to implement these additional dojo.data APIs
+		this._features['dojo.data.api.Write'] = true;
+		this._features['dojo.data.api.Notification'] = true;
+		
+		// For keeping track of changes so that we can implement isDirty and revert
+		this._pending = {
+			_newItems:{}, 
+			_modifiedItems:{}, 
+			_deletedItems:{}
+		};
+
+		if(!this._datatypeMap['Date'].serialize){
+			this._datatypeMap['Date'].serialize = function(obj){
+				return dojo.date.stamp.toISOString(obj, {zulu:true});
+			};
+		}
+		//Disable only if explicitly set to false.
+		if(keywordParameters && (keywordParameters.referenceIntegrity === false)){
+			this.referenceIntegrity = false;
+		}
+
+		// this._saveInProgress is set to true, briefly, from when save() is first called to when it completes
+		this._saveInProgress = false;
+	},
+
+	referenceIntegrity: true,  //Flag that defaultly enabled reference integrity tracking.  This way it can also be disabled pogrammatially or declaratively.
+
+	_assert: function(/* boolean */ condition){
+		if(!condition) {
+			throw new Error("assertion failed in ItemFileWriteStore");
+		}
+	},
+
+	_getIdentifierAttribute: function(){
+		var identifierAttribute = this.getFeatures()['dojo.data.api.Identity'];
+		// this._assert((identifierAttribute === Number) || (dojo.isString(identifierAttribute)));
+		return identifierAttribute;
+	},
+	
+	
+/* dojo.data.api.Write */
+
+	newItem: function(/* Object? */ keywordArgs, /* Object? */ parentInfo){
+		// summary: See dojo.data.api.Write.newItem()
+
+		this._assert(!this._saveInProgress);
+
+		if (!this._loadFinished){
+			// We need to do this here so that we'll be able to find out what
+			// identifierAttribute was specified in the data file.
+			this._forceLoad();
+		}
+
+		if(typeof keywordArgs != "object" && typeof keywordArgs != "undefined"){
+			throw new Error("newItem() was passed something other than an object");
+		}
+		var newIdentity = null;
+		var identifierAttribute = this._getIdentifierAttribute();
+		if(identifierAttribute === Number){
+			newIdentity = this._arrayOfAllItems.length;
+		}else{
+			newIdentity = keywordArgs[identifierAttribute];
+			if (typeof newIdentity === "undefined"){
+				throw new Error("newItem() was not passed an identity for the new item");
+			}
+			if (dojo.isArray(newIdentity)){
+				throw new Error("newItem() was not passed an single-valued identity");
+			}
+		}
+		
+		// make sure this identity is not already in use by another item, if identifiers were 
+		// defined in the file.  Otherwise it would be the item count, 
+		// which should always be unique in this case.
+		if(this._itemsByIdentity){
+			this._assert(typeof this._itemsByIdentity[newIdentity] === "undefined");
+		}
+		this._assert(typeof this._pending._newItems[newIdentity] === "undefined");
+		this._assert(typeof this._pending._deletedItems[newIdentity] === "undefined");
+		
+		var newItem = {};
+		newItem[this._storeRefPropName] = this;		
+		newItem[this._itemNumPropName] = this._arrayOfAllItems.length;
+		if(this._itemsByIdentity){
+			this._itemsByIdentity[newIdentity] = newItem;
+			//We have to set the identifier now, otherwise we can't look it
+			//up at calls to setValueorValues in parentInfo handling.
+			newItem[identifierAttribute] = [newIdentity];
+		}
+		this._arrayOfAllItems.push(newItem);
+
+		//We need to construct some data for the onNew call too...
+		var pInfo = null;
+		
+		// Now we need to check to see where we want to assign this thingm if any.
+		if(parentInfo && parentInfo.parent && parentInfo.attribute){
+			pInfo = {
+				item: parentInfo.parent,
+				attribute: parentInfo.attribute,
+				oldValue: undefined
+			};
+
+			//See if it is multi-valued or not and handle appropriately
+			//Generally, all attributes are multi-valued for this store
+			//So, we only need to append if there are already values present.
+			var values = this.getValues(parentInfo.parent, parentInfo.attribute);
+			if(values && values.length > 0){
+				var tempValues = values.slice(0, values.length);
+				if(values.length === 1){
+					pInfo.oldValue = values[0];
+				}else{
+					pInfo.oldValue = values.slice(0, values.length);
+				}
+				tempValues.push(newItem);
+				this._setValueOrValues(parentInfo.parent, parentInfo.attribute, tempValues, false);
+				pInfo.newValue = this.getValues(parentInfo.parent, parentInfo.attribute);
+			}else{
+				this._setValueOrValues(parentInfo.parent, parentInfo.attribute, newItem, false);
+				pInfo.newValue = newItem;
+			}
+		}else{
+			//Toplevel item, add to both top list as well as all list.
+			newItem[this._rootItemPropName]=true;
+			this._arrayOfTopLevelItems.push(newItem);
+		}
+		
+		this._pending._newItems[newIdentity] = newItem;
+		
+		//Clone over the properties to the new item
+		for(var key in keywordArgs){
+			if(key === this._storeRefPropName || key === this._itemNumPropName){
+				// Bummer, the user is trying to do something like
+				// newItem({_S:"foo"}).  Unfortunately, our superclass,
+				// ItemFileReadStore, is already using _S in each of our items
+				// to hold private info.  To avoid a naming collision, we 
+				// need to move all our private info to some other property 
+				// of all the items/objects.  So, we need to iterate over all
+				// the items and do something like: 
+				//    item.__S = item._S;
+				//    item._S = undefined;
+				// But first we have to make sure the new "__S" variable is 
+				// not in use, which means we have to iterate over all the 
+				// items checking for that.
+				throw new Error("encountered bug in ItemFileWriteStore.newItem");
+			}
+			var value = keywordArgs[key];
+			if(!dojo.isArray(value)){
+				value = [value];
+			}
+			newItem[key] = value;
+			if(this.referenceIntegrity){
+				for(var i = 0; i < value.length; i++){
+					var val = value[i];
+					if(this.isItem(val)){
+						this._addReferenceToMap(val, newItem, key);
+					}
+				}
+			}
+		}
+		this.onNew(newItem, pInfo); // dojo.data.api.Notification call
+		return newItem; // item
+	},
+	
+	_removeArrayElement: function(/* Array */ array, /* anything */ element){
+		var index = dojo.indexOf(array, element);
+		if (index != -1){
+			array.splice(index, 1);
+			return true;
+		}
+		return false;
+	},
+	
+	deleteItem: function(/* item */ item){
+		// summary: See dojo.data.api.Write.deleteItem()
+		this._assert(!this._saveInProgress);
+		this._assertIsItem(item);
+
+		// Remove this item from the _arrayOfAllItems, but leave a null value in place
+		// of the item, so as not to change the length of the array, so that in newItem() 
+		// we can still safely do: newIdentity = this._arrayOfAllItems.length;
+		var indexInArrayOfAllItems = item[this._itemNumPropName];
+		var identity = this.getIdentity(item);
+
+		//If we have reference integrity on, we need to do reference cleanup for the deleted item
+		if(this.referenceIntegrity){
+			//First scan all the attributes of this items for references and clean them up in the map 
+			//As this item is going away, no need to track its references anymore.
+
+			//Get the attributes list before we generate the backup so it 
+			//doesn't pollute the attributes list.
+			var attributes = this.getAttributes(item);
+
+			//Backup the map, we'll have to restore it potentially, in a revert.
+			if(item[this._reverseRefMap]){
+				item["backup_" + this._reverseRefMap] = dojo.clone(item[this._reverseRefMap]);
+			}
+			
+			//TODO:  This causes a reversion problem.  This list won't be restored on revert since it is
+			//attached to the 'value'. item, not ours.  Need to back tese up somehow too.
+			//Maybe build a map of the backup of the entries and attach it to the deleted item to be restored
+			//later.  Or just record them and call _addReferenceToMap on them in revert.
+			dojo.forEach(attributes, function(attribute){
+				dojo.forEach(this.getValues(item, attribute), function(value){
+					if(this.isItem(value)){
+						//We have to back up all the references we had to others so they can be restored on a revert.
+						if(!item["backupRefs_" + this._reverseRefMap]){
+							item["backupRefs_" + this._reverseRefMap] = [];
+						}
+						item["backupRefs_" + this._reverseRefMap].push({id: this.getIdentity(value), attr: attribute});
+						this._removeReferenceFromMap(value, item, attribute);
+					}
+				}, this);
+			}, this);
+
+			//Next, see if we have references to this item, if we do, we have to clean them up too.
+			var references = item[this._reverseRefMap];
+			if(references){
+				//Look through all the items noted as references to clean them up.
+				for(var itemId in references){
+					var containingItem = null;
+					if(this._itemsByIdentity){
+						containingItem = this._itemsByIdentity[itemId];
+					}else{
+						containingItem = this._arrayOfAllItems[itemId];
+					}
+					//We have a reference to a containing item, now we have to process the
+					//attributes and clear all references to the item being deleted.
+					if(containingItem){
+						for(var attribute in references[itemId]){
+							var oldValues = this.getValues(containingItem, attribute) || [];
+							var newValues = dojo.filter(oldValues, function(possibleItem){
+							   return !(this.isItem(possibleItem) && this.getIdentity(possibleItem) == identity);
+							}, this);
+							//Remove the note of the reference to the item and set the values on the modified attribute.
+							this._removeReferenceFromMap(item, containingItem, attribute); 
+							if(newValues.length < oldValues.length){
+								this._setValueOrValues(containingItem, attribute, newValues, true);
+							}
+						}
+					}
+				}
+			}
+		}
+
+		this._arrayOfAllItems[indexInArrayOfAllItems] = null;
+
+		item[this._storeRefPropName] = null;
+		if(this._itemsByIdentity){
+			delete this._itemsByIdentity[identity];
+		}
+		this._pending._deletedItems[identity] = item;
+		
+		//Remove from the toplevel items, if necessary...
+		if(item[this._rootItemPropName]){
+			this._removeArrayElement(this._arrayOfTopLevelItems, item);
+		}
+		this.onDelete(item); // dojo.data.api.Notification call
+		return true;
+	},
+
+	setValue: function(/* item */ item, /* attribute-name-string */ attribute, /* almost anything */ value){
+		// summary: See dojo.data.api.Write.set()
+		return this._setValueOrValues(item, attribute, value, true); // boolean
+	},
+	
+	setValues: function(/* item */ item, /* attribute-name-string */ attribute, /* array */ values){
+		// summary: See dojo.data.api.Write.setValues()
+		return this._setValueOrValues(item, attribute, values, true); // boolean
+	},
+	
+	unsetAttribute: function(/* item */ item, /* attribute-name-string */ attribute){
+		// summary: See dojo.data.api.Write.unsetAttribute()
+		return this._setValueOrValues(item, attribute, [], true);
+	},
+	
+	_setValueOrValues: function(/* item */ item, /* attribute-name-string */ attribute, /* anything */ newValueOrValues, /*boolean?*/ callOnSet){
+		this._assert(!this._saveInProgress);
+		
+		// Check for valid arguments
+		this._assertIsItem(item);
+		this._assert(dojo.isString(attribute));
+		this._assert(typeof newValueOrValues !== "undefined");
+
+		// Make sure the user isn't trying to change the item's identity
+		var identifierAttribute = this._getIdentifierAttribute();
+		if(attribute == identifierAttribute){
+			throw new Error("ItemFileWriteStore does not have support for changing the value of an item's identifier.");
+		}
+
+		// To implement the Notification API, we need to make a note of what
+		// the old attribute value was, so that we can pass that info when
+		// we call the onSet method.
+		var oldValueOrValues = this._getValueOrValues(item, attribute);
+
+		var identity = this.getIdentity(item);
+		if(!this._pending._modifiedItems[identity]){
+			// Before we actually change the item, we make a copy of it to 
+			// record the original state, so that we'll be able to revert if 
+			// the revert method gets called.  If the item has already been
+			// modified then there's no need to do this now, since we already
+			// have a record of the original state.						
+			var copyOfItemState = {};
+			for(var key in item){
+				if((key === this._storeRefPropName) || (key === this._itemNumPropName) || (key === this._rootItemPropName)){
+					copyOfItemState[key] = item[key];
+				}else if(key === this._reverseRefMap){
+					copyOfItemState[key] = dojo.clone(item[key]);
+				}else{
+					copyOfItemState[key] = item[key].slice(0, item[key].length);
+				}
+			}
+			// Now mark the item as dirty, and save the copy of the original state
+			this._pending._modifiedItems[identity] = copyOfItemState;
+		}
+		
+		// Okay, now we can actually change this attribute on the item
+		var success = false;
+		
+		if(dojo.isArray(newValueOrValues) && newValueOrValues.length === 0){
+			
+			// If we were passed an empty array as the value, that counts
+			// as "unsetting" the attribute, so we need to remove this 
+			// attribute from the item.
+			success = delete item[attribute];
+			newValueOrValues = undefined; // used in the onSet Notification call below
+
+			if(this.referenceIntegrity && oldValueOrValues){
+				var oldValues = oldValueOrValues;
+				if (!dojo.isArray(oldValues)){
+					oldValues = [oldValues];
+				}
+				for(var i = 0; i < oldValues.length; i++){
+					var value = oldValues[i];
+					if(this.isItem(value)){
+						this._removeReferenceFromMap(value, item, attribute);
+					}
+				}
+			}
+		}else{
+			var newValueArray;
+			if(dojo.isArray(newValueOrValues)){
+				var newValues = newValueOrValues;
+				// Unfortunately, it's not safe to just do this:
+				//    newValueArray = newValues;
+				// Instead, we need to copy the array, which slice() does very nicely.
+				// This is so that our internal data structure won't  
+				// get corrupted if the user mucks with the values array *after*
+				// calling setValues().
+				newValueArray = newValueOrValues.slice(0, newValueOrValues.length);
+			}else{
+				newValueArray = [newValueOrValues];
+			}
+
+			//We need to handle reference integrity if this is on. 
+			//In the case of set, we need to see if references were added or removed
+			//and update the reference tracking map accordingly.
+			if(this.referenceIntegrity){
+				if(oldValueOrValues){
+					var oldValues = oldValueOrValues;
+					if(!dojo.isArray(oldValues)){
+						oldValues = [oldValues];
+					}
+					//Use an associative map to determine what was added/removed from the list.
+					//Should be O(n) performant.  First look at all the old values and make a list of them
+					//Then for any item not in the old list, we add it.  If it was already present, we remove it.
+					//Then we pass over the map and any references left it it need to be removed (IE, no match in
+					//the new values list).
+					var map = {};
+					dojo.forEach(oldValues, function(possibleItem){
+						if(this.isItem(possibleItem)){
+							var id = this.getIdentity(possibleItem);
+							map[id.toString()] = true;
+						}
+					}, this);
+					dojo.forEach(newValueArray, function(possibleItem){
+						if(this.isItem(possibleItem)){
+							var id = this.getIdentity(possibleItem);
+							if(map[id.toString()]){
+								delete map[id.toString()];
+							}else{
+								this._addReferenceToMap(possibleItem, item, attribute); 
+							}
+						}
+					}, this);
+					for(var rId in map){
+						var removedItem;
+						if(this._itemsByIdentity){
+							removedItem = this._itemsByIdentity[rId];
+						}else{
+							removedItem = this._arrayOfAllItems[rId];
+						}
+						this._removeReferenceFromMap(removedItem, item, attribute);
+					}
+				}else{
+					//Everything is new (no old values) so we have to just
+					//insert all the references, if any.
+					for(var i = 0; i < newValueArray.length; i++){
+						var value = newValueArray[i];
+						if(this.isItem(value)){
+							this._addReferenceToMap(value, item, attribute);
+						}
+					}
+				}
+			}
+			item[attribute] = newValueArray;
+			success = true;
+		}
+
+		// Now we make the dojo.data.api.Notification call
+		if(callOnSet){
+			this.onSet(item, attribute, oldValueOrValues, newValueOrValues); 
+		}
+		return success; // boolean
+	},
+
+	_addReferenceToMap: function(/*item*/ refItem, /*item*/ parentItem, /*string*/ attribute){
+		//	summary:
+		//		Method to add an reference map entry for an item and attribute.
+		//	description:
+		//		Method to add an reference map entry for an item and attribute. 		 //
+		//	refItem:
+		//		The item that is referenced.
+		//	parentItem:
+		//		The item that holds the new reference to refItem.
+		//	attribute:
+		//		The attribute on parentItem that contains the new reference.
+		 
+		var parentId = this.getIdentity(parentItem);
+		var references = refItem[this._reverseRefMap];
+
+		if(!references){
+			references = refItem[this._reverseRefMap] = {};
+		}
+		var itemRef = references[parentId];
+		if(!itemRef){
+			itemRef = references[parentId] = {};
+		}
+		itemRef[attribute] = true;
+	},
+
+	_removeReferenceFromMap: function(/* item */ refItem, /* item */ parentItem, /*strin*/ attribute){
+		//	summary:
+		//		Method to remove an reference map entry for an item and attribute.
+		//	description:
+		//		Method to remove an reference map entry for an item and attribute.  This will
+		//		also perform cleanup on the map such that if there are no more references at all to 
+		//		the item, its reference object and entry are removed.
+		//
+		//	refItem:
+		//		The item that is referenced.
+		//	parentItem:
+		//		The item holding a reference to refItem.
+		//	attribute:
+		//		The attribute on parentItem that contains the reference.
+		var identity = this.getIdentity(parentItem);
+		var references = refItem[this._reverseRefMap];
+		var itemId;
+		if(references){
+			for(itemId in references){
+				if(itemId == identity){
+					delete references[itemId][attribute];
+					if(this._isEmpty(references[itemId])){
+						delete references[itemId];
+					}
+				}
+			}
+			if(this._isEmpty(references)){
+				delete refItem[this._reverseRefMap];
+			}
+		}
+	},
+
+	_dumpReferenceMap: function(){
+		//	summary:
+		//		Function to dump the reverse reference map of all items in the store for debug purposes.
+		//	description:
+		//		Function to dump the reverse reference map of all items in the store for debug purposes.
+		var i;
+		for(i = 0; i < this._arrayOfAllItems.length; i++){
+			var item = this._arrayOfAllItems[i];
+			if(item && item[this._reverseRefMap]){
+				
+			}
+		}
+	},
+						   
+	_getValueOrValues: function(/* item */ item, /* attribute-name-string */ attribute){
+		var valueOrValues = undefined;
+		if(this.hasAttribute(item, attribute)){
+			var valueArray = this.getValues(item, attribute);
+			if(valueArray.length == 1){
+				valueOrValues = valueArray[0];
+			}else{
+				valueOrValues = valueArray;
+			}
+		}
+		return valueOrValues;
+	},
+	
+	_flatten: function(/* anything */ value){
+		if(this.isItem(value)){
+			var item = value;
+			// Given an item, return an serializable object that provides a 
+			// reference to the item.
+			// For example, given kermit:
+			//    var kermit = store.newItem({id:2, name:"Kermit"});
+			// we want to return
+			//    {_reference:2}
+			var identity = this.getIdentity(item);
+			var referenceObject = {_reference: identity};
+			return referenceObject;
+		}else{
+			if(typeof value === "object"){
+				for(var type in this._datatypeMap){
+					var typeMap = this._datatypeMap[type];
+					if (dojo.isObject(typeMap) && !dojo.isFunction(typeMap)){
+						if(value instanceof typeMap.type){
+							if(!typeMap.serialize){
+								throw new Error("ItemFileWriteStore:  No serializer defined for type mapping: [" + type + "]");
+							}
+							return {_type: type, _value: typeMap.serialize(value)};
+						}
+					} else if(value instanceof typeMap){
+						//SImple mapping, therefore, return as a toString serialization.
+						return {_type: type, _value: value.toString()};
+					}
+				}
+			}
+			return value;
+		}
+	},
+	
+	_getNewFileContentString: function(){
+		// summary: 
+		//		Generate a string that can be saved to a file.
+		//		The result should look similar to:
+		//		http://trac.dojotoolkit.org/browser/dojo/trunk/tests/data/countries.json
+		var serializableStructure = {};
+		
+		var identifierAttribute = this._getIdentifierAttribute();
+		if(identifierAttribute !== Number){
+			serializableStructure.identifier = identifierAttribute;
+		}
+		if(this._labelAttr){
+			serializableStructure.label = this._labelAttr;
+		}
+		serializableStructure.items = [];
+		for(var i = 0; i < this._arrayOfAllItems.length; ++i){
+			var item = this._arrayOfAllItems[i];
+			if(item !== null){
+				var serializableItem = {};
+				for(var key in item){
+					if(key !== this._storeRefPropName && key !== this._itemNumPropName && key !== this._reverseRefMap && key !== this._rootItemPropName){
+						var attribute = key;
+						var valueArray = this.getValues(item, attribute);
+						if(valueArray.length == 1){
+							serializableItem[attribute] = this._flatten(valueArray[0]);
+						}else{
+							var serializableArray = [];
+							for(var j = 0; j < valueArray.length; ++j){
+								serializableArray.push(this._flatten(valueArray[j]));
+								serializableItem[attribute] = serializableArray;
+							}
+						}
+					}
+				}
+				serializableStructure.items.push(serializableItem);
+			}
+		}
+		var prettyPrint = true;
+		return dojo.toJson(serializableStructure, prettyPrint);
+	},
+
+	_isEmpty: function(something){
+		//	summary: 
+		//		Function to determine if an array or object has no properties or values.
+		//	something:
+		//		The array or object to examine.
+		var empty = true;
+		if(dojo.isObject(something)){
+			var i;
+			for(i in something){
+				empty = false;
+				break;
+			}
+		}else if(dojo.isArray(something)){
+			if(something.length > 0){
+				empty = false;
+			}
+		}
+		return empty; //boolean
+	},
+	
+	save: function(/* object */ keywordArgs){
+		// summary: See dojo.data.api.Write.save()
+		this._assert(!this._saveInProgress);
+		
+		// this._saveInProgress is set to true, briefly, from when save is first called to when it completes
+		this._saveInProgress = true;
+		
+		var self = this;
+		var saveCompleteCallback = function(){
+			self._pending = {
+				_newItems:{}, 
+				_modifiedItems:{},
+				_deletedItems:{}
+			};
+
+			self._saveInProgress = false; // must come after this._pending is cleared, but before any callbacks
+			if(keywordArgs && keywordArgs.onComplete){
+				var scope = keywordArgs.scope || dojo.global;
+				keywordArgs.onComplete.call(scope);
+			}
+		};
+		var saveFailedCallback = function(err){
+			self._saveInProgress = false;
+			if(keywordArgs && keywordArgs.onError){
+				var scope = keywordArgs.scope || dojo.global;
+				keywordArgs.onError.call(scope, err);
+			}
+		};
+		
+		if(this._saveEverything){
+			var newFileContentString = this._getNewFileContentString();
+			this._saveEverything(saveCompleteCallback, saveFailedCallback, newFileContentString);
+		}
+		if(this._saveCustom){
+			this._saveCustom(saveCompleteCallback, saveFailedCallback);
+		}
+		if(!this._saveEverything && !this._saveCustom){
+			// Looks like there is no user-defined save-handler function.
+			// That's fine, it just means the datastore is acting as a "mock-write"
+			// store -- changes get saved in memory but don't get saved to disk.
+			saveCompleteCallback();
+		}
+	},
+	
+	revert: function(){
+		// summary: See dojo.data.api.Write.revert()
+		this._assert(!this._saveInProgress);
+
+		var identity;
+		for(identity in this._pending._modifiedItems){
+			// find the original item and the modified item that replaced it
+			var originalItem = this._pending._modifiedItems[identity];
+			var modifiedItem = null;
+			if(this._itemsByIdentity){
+				modifiedItem = this._itemsByIdentity[identity];
+			}else{
+				modifiedItem = this._arrayOfAllItems[identity];
+			}
+			
+			// make the original item into a full-fledged item again
+			originalItem[this._storeRefPropName] = this;
+			modifiedItem[this._storeRefPropName] = null;
+
+			// replace the modified item with the original one
+			var arrayIndex = modifiedItem[this._itemNumPropName];
+			this._arrayOfAllItems[arrayIndex] = originalItem;
+			
+			if(modifiedItem[this._rootItemPropName]){
+				var i;
+				for (i = 0; i < this._arrayOfTopLevelItems.length; i++) {
+					var possibleMatch = this._arrayOfTopLevelItems[i];
+					if (this.getIdentity(possibleMatch) == identity){
+						this._arrayOfTopLevelItems[i] = originalItem;
+						break;
+					}
+				}
+			}
+			if(this._itemsByIdentity){
+				this._itemsByIdentity[identity] = originalItem;
+			}			
+		}
+		var deletedItem;
+		for(identity in this._pending._deletedItems){
+			deletedItem = this._pending._deletedItems[identity];
+			deletedItem[this._storeRefPropName] = this;
+			var index = deletedItem[this._itemNumPropName];
+
+			//Restore the reverse refererence map, if any.
+			if(deletedItem["backup_" + this._reverseRefMap]){
+				deletedItem[this._reverseRefMap] = deletedItem["backup_" + this._reverseRefMap];
+				delete deletedItem["backup_" + this._reverseRefMap];
+			}
+			this._arrayOfAllItems[index] = deletedItem;
+			if (this._itemsByIdentity) {
+				this._itemsByIdentity[identity] = deletedItem;
+			}
+			if(deletedItem[this._rootItemPropName]){
+				this._arrayOfTopLevelItems.push(deletedItem);
+			}	  
+		}
+		//We have to pass through it again and restore the reference maps after all the
+		//undeletes have occurred.
+		for(identity in this._pending._deletedItems){
+			deletedItem = this._pending._deletedItems[identity];
+			if(deletedItem["backupRefs_" + this._reverseRefMap]){
+				dojo.forEach(deletedItem["backupRefs_" + this._reverseRefMap], function(reference){
+					var refItem;
+					if(this._itemsByIdentity){
+						refItem = this._itemsByIdentity[reference.id];
+					}else{
+						refItem = this._arrayOfAllItems[reference.id];
+					}
+					this._addReferenceToMap(refItem, deletedItem, reference.attr);
+				}, this);
+				delete deletedItem["backupRefs_" + this._reverseRefMap]; 
+			}
+		}
+
+		for(identity in this._pending._newItems){
+			var newItem = this._pending._newItems[identity];
+			newItem[this._storeRefPropName] = null;
+			// null out the new item, but don't change the array index so
+			// so we can keep using _arrayOfAllItems.length.
+			this._arrayOfAllItems[newItem[this._itemNumPropName]] = null;
+			if(newItem[this._rootItemPropName]){
+				this._removeArrayElement(this._arrayOfTopLevelItems, newItem);
+			}
+			if(this._itemsByIdentity){
+				delete this._itemsByIdentity[identity];
+			}
+		}
+
+		this._pending = {
+			_newItems:{}, 
+			_modifiedItems:{}, 
+			_deletedItems:{}
+		};
+		return true; // boolean
+	},
+	
+	isDirty: function(/* item? */ item){
+		// summary: See dojo.data.api.Write.isDirty()
+		if(item){
+			// return true if the item is dirty
+			var identity = this.getIdentity(item);
+			return new Boolean(this._pending._newItems[identity] || 
+				this._pending._modifiedItems[identity] ||
+				this._pending._deletedItems[identity]).valueOf(); // boolean
+		}else{
+			// return true if the store is dirty -- which means return true
+			// if there are any new items, dirty items, or modified items
+			if(!this._isEmpty(this._pending._newItems) || 
+			   !this._isEmpty(this._pending._modifiedItems) ||
+			   !this._isEmpty(this._pending._deletedItems)){
+				return true;
+			}
+			return false; // boolean
+		}
+	},
+
+/* dojo.data.api.Notification */
+
+	onSet: function(/* item */ item, 
+					/*attribute-name-string*/ attribute, 
+					/*object | array*/ oldValue,
+					/*object | array*/ newValue){
+		// summary: See dojo.data.api.Notification.onSet()
+		
+		// No need to do anything. This method is here just so that the 
+		// client code can connect observers to it.
+	},
+
+	onNew: function(/* item */ newItem, /*object?*/ parentInfo){
+		// summary: See dojo.data.api.Notification.onNew()
+		
+		// No need to do anything. This method is here just so that the 
+		// client code can connect observers to it. 
+	},
+
+	onDelete: function(/* item */ deletedItem){
+		// summary: See dojo.data.api.Notification.onDelete()
+		
+		// No need to do anything. This method is here just so that the 
+		// client code can connect observers to it. 
+	},
+
+	close: function(/* object? */ request) {
+		 // summary:
+		 //		Over-ride of base close function of ItemFileReadStore to add in check for store state.
+		 // description:
+		 //		Over-ride of base close function of ItemFileReadStore to add in check for store state.
+		 //		If the store is still dirty (unsaved changes), then an error will be thrown instead of
+		 //		clearing the internal state for reload from the url.
+
+		 //Clear if not dirty ... or throw an error
+		 if(this.clearOnClose){
+			 if(!this.isDirty()){
+				 this.inherited(arguments);
+			 }else if(this._jsonFileUrl !== ""){
+				 //Only throw an error if the store was dirty and we were loading from a url (cannot reload from url until state is saved).
+				 throw new Error("dojo.data.ItemFileWriteStore: There are unsaved changes present in the store.  Please save or revert the changes before invoking close.");
+			 }
+		 }
+	}
+});
+
+}
+
+if(!dojo._hasResource["dojo.date"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.date"] = true;
+dojo.provide("dojo.date");
+
+/*=====
+dojo.date = {
+	// summary: Date manipulation utilities
+}
+=====*/
+
+dojo.date.getDaysInMonth = function(/*Date*/dateObject){
+	//	summary:
+	//		Returns the number of days in the month used by dateObject
+	var month = dateObject.getMonth();
+	var days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
+	if(month == 1 && dojo.date.isLeapYear(dateObject)){ return 29; } // Number
+	return days[month]; // Number
+}
+
+dojo.date.isLeapYear = function(/*Date*/dateObject){
+	//	summary:
+	//		Determines if the year of the dateObject is a leap year
+	//	description:
+	//		Leap years are years with an additional day YYYY-02-29, where the
+	//		year number is a multiple of four with the following exception: If
+	//		a year is a multiple of 100, then it is only a leap year if it is
+	//		also a multiple of 400. For example, 1900 was not a leap year, but
+	//		2000 is one.
+
+	var year = dateObject.getFullYear();
+	return !(year%400) || (!(year%4) && !!(year%100)); // Boolean
+}
+
+// FIXME: This is not localized
+dojo.date.getTimezoneName = function(/*Date*/dateObject){
+	//	summary:
+	//		Get the user's time zone as provided by the browser
+	// dateObject:
+	//		Needed because the timezone may vary with time (daylight savings)
+	//	description:
+	//		Try to get time zone info from toString or toLocaleString method of
+	//		the Date object -- UTC offset is not a time zone.  See
+	//		http://www.twinsun.com/tz/tz-link.htm Note: results may be
+	//		inconsistent across browsers.
+
+	var str = dateObject.toString(); // Start looking in toString
+	var tz = ''; // The result -- return empty string if nothing found
+	var match;
+
+	// First look for something in parentheses -- fast lookup, no regex
+	var pos = str.indexOf('(');
+	if(pos > -1){
+		tz = str.substring(++pos, str.indexOf(')'));
+	}else{
+		// If at first you don't succeed ...
+		// If IE knows about the TZ, it appears before the year
+		// Capital letters or slash before a 4-digit year 
+		// at the end of string
+		var pat = /([A-Z\/]+) \d{4}$/;
+		if((match = str.match(pat))){
+			tz = match[1];
+		}else{
+		// Some browsers (e.g. Safari) glue the TZ on the end
+		// of toLocaleString instead of putting it in toString
+			str = dateObject.toLocaleString();
+			// Capital letters or slash -- end of string, 
+			// after space
+			pat = / ([A-Z\/]+)$/;
+			if((match = str.match(pat))){
+				tz = match[1];
+			}
+		}
+	}
+
+	// Make sure it doesn't somehow end up return AM or PM
+	return (tz == 'AM' || tz == 'PM') ? '' : tz; // String
+}
+
+// Utility methods to do arithmetic calculations with Dates
+
+dojo.date.compare = function(/*Date*/date1, /*Date?*/date2, /*String?*/portion){
+	//	summary:
+	//		Compare two date objects by date, time, or both.
+	//	description:
+	//  	Returns 0 if equal, positive if a > b, else negative.
+	//	date1:
+	//		Date object
+	//	date2:
+	//		Date object.  If not specified, the current Date is used.
+	//	portion:
+	//		A string indicating the "date" or "time" portion of a Date object.
+	//		Compares both "date" and "time" by default.  One of the following:
+	//		"date", "time", "datetime"
+
+	// Extra step required in copy for IE - see #3112
+	date1 = new Date(Number(date1));
+	date2 = new Date(Number(date2 || new Date()));
+
+	if(portion !== "undefined"){
+		if(portion == "date"){
+			// Ignore times and compare dates.
+			date1.setHours(0, 0, 0, 0);
+			date2.setHours(0, 0, 0, 0);
+		}else if(portion == "time"){
+			// Ignore dates and compare times.
+			date1.setFullYear(0, 0, 0);
+			date2.setFullYear(0, 0, 0);
+		}
+	}
+	
+	if(date1 > date2){ return 1; } // int
+	if(date1 < date2){ return -1; } // int
+	return 0; // int
+};
+
+dojo.date.add = function(/*Date*/date, /*String*/interval, /*int*/amount){
+	//	summary:
+	//		Add to a Date in intervals of different size, from milliseconds to years
+	//	date: Date
+	//		Date object to start with
+	//	interval:
+	//		A string representing the interval.  One of the following:
+	//			"year", "month", "day", "hour", "minute", "second",
+	//			"millisecond", "quarter", "week", "weekday"
+	//	amount:
+	//		How much to add to the date.
+
+	var sum = new Date(Number(date)); // convert to Number before copying to accomodate IE (#3112)
+	var fixOvershoot = false;
+	var property = "Date";
+
+	switch(interval){
+		case "day":
+			break;
+		case "weekday":
+			//i18n FIXME: assumes Saturday/Sunday weekend, but this is not always true.  see dojo.cldr.supplemental
+
+			// Divide the increment time span into weekspans plus leftover days
+			// e.g., 8 days is one 5-day weekspan / and two leftover days
+			// Can't have zero leftover days, so numbers divisible by 5 get
+			// a days value of 5, and the remaining days make up the number of weeks
+			var days, weeks;
+			var mod = amount % 5;
+			if(!mod){
+				days = (amount > 0) ? 5 : -5;
+				weeks = (amount > 0) ? ((amount-5)/5) : ((amount+5)/5);
+			}else{
+				days = mod;
+				weeks = parseInt(amount/5);
+			}
+			// Get weekday value for orig date param
+			var strt = date.getDay();
+			// Orig date is Sat / positive incrementer
+			// Jump over Sun
+			var adj = 0;
+			if(strt == 6 && amount > 0){
+				adj = 1;
+			}else if(strt == 0 && amount < 0){
+			// Orig date is Sun / negative incrementer
+			// Jump back over Sat
+				adj = -1;
+			}
+			// Get weekday val for the new date
+			var trgt = strt + days;
+			// New date is on Sat or Sun
+			if(trgt == 0 || trgt == 6){
+				adj = (amount > 0) ? 2 : -2;
+			}
+			// Increment by number of weeks plus leftover days plus
+			// weekend adjustments
+			amount = (7 * weeks) + days + adj;
+			break;
+		case "year":
+			property = "FullYear";
+			// Keep increment/decrement from 2/29 out of March
+			fixOvershoot = true;
+			break;
+		case "week":
+			amount *= 7;
+			break;
+		case "quarter":
+			// Naive quarter is just three months
+			amount *= 3;
+			// fallthrough...
+		case "month":
+			// Reset to last day of month if you overshoot
+			fixOvershoot = true;
+			property = "Month";
+			break;
+		case "hour":
+		case "minute":
+		case "second":
+		case "millisecond":
+			property = "UTC"+interval.charAt(0).toUpperCase() + interval.substring(1) + "s";
+	}
+
+	if(property){
+		sum["set"+property](sum["get"+property]()+amount);
+	}
+
+	if(fixOvershoot && (sum.getDate() < date.getDate())){
+		sum.setDate(0);
+	}
+
+	return sum; // Date
+};
+
+dojo.date.difference = function(/*Date*/date1, /*Date?*/date2, /*String?*/interval){
+	//	summary:
+	//		Get the difference in a specific unit of time (e.g., number of
+	//		months, weeks, days, etc.) between two dates, rounded to the
+	//		nearest integer.
+	//	date1:
+	//		Date object
+	//	date2:
+	//		Date object.  If not specified, the current Date is used.
+	//	interval:
+	//		A string representing the interval.  One of the following:
+	//			"year", "month", "day", "hour", "minute", "second",
+	//			"millisecond", "quarter", "week", "weekday"
+	//		Defaults to "day".
+
+	date2 = date2 || new Date();
+	interval = interval || "day";
+	var yearDiff = date2.getFullYear() - date1.getFullYear();
+	var delta = 1; // Integer return value
+
+	switch(interval){
+		case "quarter":
+			var m1 = date1.getMonth();
+			var m2 = date2.getMonth();
+			// Figure out which quarter the months are in
+			var q1 = Math.floor(m1/3) + 1;
+			var q2 = Math.floor(m2/3) + 1;
+			// Add quarters for any year difference between the dates
+			q2 += (yearDiff * 4);
+			delta = q2 - q1;
+			break;
+		case "weekday":
+			var days = Math.round(dojo.date.difference(date1, date2, "day"));
+			var weeks = parseInt(dojo.date.difference(date1, date2, "week"));
+			var mod = days % 7;
+
+			// Even number of weeks
+			if(mod == 0){
+				days = weeks*5;
+			}else{
+				// Weeks plus spare change (< 7 days)
+				var adj = 0;
+				var aDay = date1.getDay();
+				var bDay = date2.getDay();
+
+				weeks = parseInt(days/7);
+				mod = days % 7;
+				// Mark the date advanced by the number of
+				// round weeks (may be zero)
+				var dtMark = new Date(date1);
+				dtMark.setDate(dtMark.getDate()+(weeks*7));
+				var dayMark = dtMark.getDay();
+
+				// Spare change days -- 6 or less
+				if(days > 0){
+					switch(true){
+						// Range starts on Sat
+						case aDay == 6:
+							adj = -1;
+							break;
+						// Range starts on Sun
+						case aDay == 0:
+							adj = 0;
+							break;
+						// Range ends on Sat
+						case bDay == 6:
+							adj = -1;
+							break;
+						// Range ends on Sun
+						case bDay == 0:
+							adj = -2;
+							break;
+						// Range contains weekend
+						case (dayMark + mod) > 5:
+							adj = -2;
+					}
+				}else if(days < 0){
+					switch(true){
+						// Range starts on Sat
+						case aDay == 6:
+							adj = 0;
+							break;
+						// Range starts on Sun
+						case aDay == 0:
+							adj = 1;
+							break;
+						// Range ends on Sat
+						case bDay == 6:
+							adj = 2;
+							break;
+						// Range ends on Sun
+						case bDay == 0:
+							adj = 1;
+							break;
+						// Range contains weekend
+						case (dayMark + mod) < 0:
+							adj = 2;
+					}
+				}
+				days += adj;
+				days -= (weeks*2);
+			}
+			delta = days;
+			break;
+		case "year":
+			delta = yearDiff;
+			break;
+		case "month":
+			delta = (date2.getMonth() - date1.getMonth()) + (yearDiff * 12);
+			break;
+		case "week":
+			// Truncate instead of rounding
+			// Don't use Math.floor -- value may be negative
+			delta = parseInt(dojo.date.difference(date1, date2, "day")/7);
+			break;
+		case "day":
+			delta /= 24;
+			// fallthrough
+		case "hour":
+			delta /= 60;
+			// fallthrough
+		case "minute":
+			delta /= 60;
+			// fallthrough
+		case "second":
+			delta /= 1000;
+			// fallthrough
+		case "millisecond":
+			delta *= date2.getTime() - date1.getTime();
+	}
+
+	// Round for fractional values and DST leaps
+	return Math.round(delta); // Number (integer)
+};
+
+}
+
+if(!dojo._hasResource["dojo.i18n"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.i18n"] = true;
+dojo.provide("dojo.i18n");
+
+/*=====
+dojo.i18n = {
+	// summary: Utility classes to enable loading of resources for internationalization (i18n)
+};
+=====*/
+
+dojo.i18n.getLocalization = function(/*String*/packageName, /*String*/bundleName, /*String?*/locale){
+	//	summary:
+	//		Returns an Object containing the localization for a given resource
+	//		bundle in a package, matching the specified locale.
+	//	description:
+	//		Returns a hash containing name/value pairs in its prototypesuch
+	//		that values can be easily overridden.  Throws an exception if the
+	//		bundle is not found.  Bundle must have already been loaded by
+	//		`dojo.requireLocalization()` or by a build optimization step.  NOTE:
+	//		try not to call this method as part of an object property
+	//		definition (`var foo = { bar: dojo.i18n.getLocalization() }`).  In
+	//		some loading situations, the bundle may not be available in time
+	//		for the object definition.  Instead, call this method inside a
+	//		function that is run after all modules load or the page loads (like
+	//		in `dojo.addOnLoad()`), or in a widget lifecycle method.
+	//	packageName:
+	//		package which is associated with this resource
+	//	bundleName:
+	//		the base filename of the resource bundle (without the ".js" suffix)
+	//	locale:
+	//		the variant to load (optional).  By default, the locale defined by
+	//		the host environment: dojo.locale
+
+	locale = dojo.i18n.normalizeLocale(locale);
+
+	// look for nearest locale match
+	var elements = locale.split('-');
+	var module = [packageName,"nls",bundleName].join('.');
+	var bundle = dojo._loadedModules[module];
+	if(bundle){
+		var localization;
+		for(var i = elements.length; i > 0; i--){
+			var loc = elements.slice(0, i).join('_');
+			if(bundle[loc]){
+				localization = bundle[loc];
+				break;
+			}
+		}
+		if(!localization){
+			localization = bundle.ROOT;
+		}
+
+		// make a singleton prototype so that the caller won't accidentally change the values globally
+		if(localization){
+			var clazz = function(){};
+			clazz.prototype = localization;
+			return new clazz(); // Object
+		}
+	}
+
+	throw new Error("Bundle not found: " + bundleName + " in " + packageName+" , locale=" + locale);
+};
+
+dojo.i18n.normalizeLocale = function(/*String?*/locale){
+	//	summary:
+	//		Returns canonical form of locale, as used by Dojo.
+	//
+	//  description:
+	//		All variants are case-insensitive and are separated by '-' as specified in [RFC 3066](http://www.ietf.org/rfc/rfc3066.txt).
+	//		If no locale is specified, the dojo.locale is returned.  dojo.locale is defined by
+	//		the user agent's locale unless overridden by djConfig.
+
+	var result = locale ? locale.toLowerCase() : dojo.locale;
+	if(result == "root"){
+		result = "ROOT";
+	}
+	return result; // String
+};
+
+dojo.i18n._requireLocalization = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale, /*String?*/availableFlatLocales){
+	//	summary:
+	//		See dojo.requireLocalization()
+	//	description:
+	// 		Called by the bootstrap, but factored out so that it is only
+	// 		included in the build when needed.
+
+	var targetLocale = dojo.i18n.normalizeLocale(locale);
+ 	var bundlePackage = [moduleName, "nls", bundleName].join(".");
+	// NOTE: 
+	//		When loading these resources, the packaging does not match what is
+	//		on disk.  This is an implementation detail, as this is just a
+	//		private data structure to hold the loaded resources.  e.g.
+	//		`tests/hello/nls/en-us/salutations.js` is loaded as the object
+	//		`tests.hello.nls.salutations.en_us={...}` The structure on disk is
+	//		intended to be most convenient for developers and translators, but
+	//		in memory it is more logical and efficient to store in a different
+	//		order.  Locales cannot use dashes, since the resulting path will
+	//		not evaluate as valid JS, so we translate them to underscores.
+	
+	//Find the best-match locale to load if we have available flat locales.
+	var bestLocale = "";
+	if(availableFlatLocales){
+		var flatLocales = availableFlatLocales.split(",");
+		for(var i = 0; i < flatLocales.length; i++){
+			//Locale must match from start of string.
+			//Using ["indexOf"] so customBase builds do not see
+			//this as a dojo._base.array dependency.
+			if(targetLocale["indexOf"](flatLocales[i]) == 0){
+				if(flatLocales[i].length > bestLocale.length){
+					bestLocale = flatLocales[i];
+				}
+			}
+		}
+		if(!bestLocale){
+			bestLocale = "ROOT";
+		}		
+	}
+
+	//See if the desired locale is already loaded.
+	var tempLocale = availableFlatLocales ? bestLocale : targetLocale;
+	var bundle = dojo._loadedModules[bundlePackage];
+	var localizedBundle = null;
+	if(bundle){
+		if(dojo.config.localizationComplete && bundle._built){return;}
+		var jsLoc = tempLocale.replace(/-/g, '_');
+		var translationPackage = bundlePackage+"."+jsLoc;
+		localizedBundle = dojo._loadedModules[translationPackage];
+	}
+
+	if(!localizedBundle){
+		bundle = dojo["provide"](bundlePackage);
+		var syms = dojo._getModuleSymbols(moduleName);
+		var modpath = syms.concat("nls").join("/");
+		var parent;
+
+		dojo.i18n._searchLocalePath(tempLocale, availableFlatLocales, function(loc){
+			var jsLoc = loc.replace(/-/g, '_');
+			var translationPackage = bundlePackage + "." + jsLoc;
+			var loaded = false;
+			if(!dojo._loadedModules[translationPackage]){
+				// Mark loaded whether it's found or not, so that further load attempts will not be made
+				dojo["provide"](translationPackage);
+				var module = [modpath];
+				if(loc != "ROOT"){module.push(loc);}
+				module.push(bundleName);
+				var filespec = module.join("/") + '.js';
+				loaded = dojo._loadPath(filespec, null, function(hash){
+					// Use singleton with prototype to point to parent bundle, then mix-in result from loadPath
+					var clazz = function(){};
+					clazz.prototype = parent;
+					bundle[jsLoc] = new clazz();
+					for(var j in hash){ bundle[jsLoc][j] = hash[j]; }
+				});
+			}else{
+				loaded = true;
+			}
+			if(loaded && bundle[jsLoc]){
+				parent = bundle[jsLoc];
+			}else{
+				bundle[jsLoc] = parent;
+			}
+			
+			if(availableFlatLocales){
+				//Stop the locale path searching if we know the availableFlatLocales, since
+				//the first call to this function will load the only bundle that is needed.
+				return true;
+			}
+		});
+	}
+
+	//Save the best locale bundle as the target locale bundle when we know the
+	//the available bundles.
+	if(availableFlatLocales && targetLocale != bestLocale){
+		bundle[targetLocale.replace(/-/g, '_')] = bundle[bestLocale.replace(/-/g, '_')];
+	}
+};
+
+(function(){
+	// If other locales are used, dojo.requireLocalization should load them as
+	// well, by default. 
+	// 
+	// Override dojo.requireLocalization to do load the default bundle, then
+	// iterate through the extraLocale list and load those translations as
+	// well, unless a particular locale was requested.
+
+	var extra = dojo.config.extraLocale;
+	if(extra){
+		if(!extra instanceof Array){
+			extra = [extra];
+		}
+
+		var req = dojo.i18n._requireLocalization;
+		dojo.i18n._requireLocalization = function(m, b, locale, availableFlatLocales){
+			req(m,b,locale, availableFlatLocales);
+			if(locale){return;}
+			for(var i=0; i<extra.length; i++){
+				req(m,b,extra[i], availableFlatLocales);
+			}
+		};
+	}
+})();
+
+dojo.i18n._searchLocalePath = function(/*String*/locale, /*Boolean*/down, /*Function*/searchFunc){
+	//	summary:
+	//		A helper method to assist in searching for locale-based resources.
+	//		Will iterate through the variants of a particular locale, either up
+	//		or down, executing a callback function.  For example, "en-us" and
+	//		true will try "en-us" followed by "en" and finally "ROOT".
+
+	locale = dojo.i18n.normalizeLocale(locale);
+
+	var elements = locale.split('-');
+	var searchlist = [];
+	for(var i = elements.length; i > 0; i--){
+		searchlist.push(elements.slice(0, i).join('-'));
+	}
+	searchlist.push(false);
+	if(down){searchlist.reverse();}
+
+	for(var j = searchlist.length - 1; j >= 0; j--){
+		var loc = searchlist[j] || "ROOT";
+		var stop = searchFunc(loc);
+		if(stop){ break; }
+	}
+};
+
+dojo.i18n._preloadLocalizations = function(/*String*/bundlePrefix, /*Array*/localesGenerated){
+	//	summary:
+	//		Load built, flattened resource bundles, if available for all
+	//		locales used in the page. Only called by built layer files.
+
+	function preload(locale){
+		locale = dojo.i18n.normalizeLocale(locale);
+		dojo.i18n._searchLocalePath(locale, true, function(loc){
+			for(var i=0; i<localesGenerated.length;i++){
+				if(localesGenerated[i] == loc){
+					dojo["require"](bundlePrefix+"_"+loc);
+					return true; // Boolean
+				}
+			}
+			return false; // Boolean
+		});
+	}
+	preload();
+	var extra = dojo.config.extraLocale||[];
+	for(var i=0; i<extra.length; i++){
+		preload(extra[i]);
+	}
+};
+
+}
+
+if(!dojo._hasResource["dojo.cldr.supplemental"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.cldr.supplemental"] = true;
+dojo.provide("dojo.cldr.supplemental");
+
+
+
+dojo.cldr.supplemental.getFirstDayOfWeek = function(/*String?*/locale){
+// summary: Returns a zero-based index for first day of the week
+// description:
+//		Returns a zero-based index for first day of the week, as used by the local (Gregorian) calendar.
+//		e.g. Sunday (returns 0), or Monday (returns 1)
+
+	// from http://www.unicode.org/cldr/data/common/supplemental/supplementalData.xml:supplementalData/weekData/firstDay
+	var firstDay = {/*default is 1=Monday*/
+		mv:5,
+		ae:6,af:6,bh:6,dj:6,dz:6,eg:6,er:6,et:6,iq:6,ir:6,jo:6,ke:6,kw:6,lb:6,ly:6,ma:6,om:6,qa:6,sa:6,
+		sd:6,so:6,tn:6,ye:6,
+		as:0,au:0,az:0,bw:0,ca:0,cn:0,fo:0,ge:0,gl:0,gu:0,hk:0,ie:0,il:0,is:0,jm:0,jp:0,kg:0,kr:0,la:0,
+		mh:0,mo:0,mp:0,mt:0,nz:0,ph:0,pk:0,sg:0,th:0,tt:0,tw:0,um:0,us:0,uz:0,vi:0,za:0,zw:0,
+		et:0,mw:0,ng:0,tj:0,
+// variant. do not use?		gb:0,
+		sy:4
+	};
+
+	var country = dojo.cldr.supplemental._region(locale);
+	var dow = firstDay[country];
+	return (dow === undefined) ? 1 : dow; /*Number*/
+};
+
+dojo.cldr.supplemental._region = function(/*String?*/locale){
+	locale = dojo.i18n.normalizeLocale(locale);
+	var tags = locale.split('-');
+	var region = tags[1];
+	if(!region){
+		// IE often gives language only (#2269)
+		// Arbitrary mappings of language-only locales to a country:
+		region = {de:"de", en:"us", es:"es", fi:"fi", fr:"fr", he:"il", hu:"hu", it:"it",
+			ja:"jp", ko:"kr", nl:"nl", pt:"br", sv:"se", zh:"cn"}[tags[0]];
+	}else if(region.length == 4){
+		// The ISO 3166 country code is usually in the second position, unless a
+		// 4-letter script is given. See http://www.ietf.org/rfc/rfc4646.txt
+		region = tags[2];
+	}
+	return region;
+}
+
+dojo.cldr.supplemental.getWeekend = function(/*String?*/locale){
+// summary: Returns a hash containing the start and end days of the weekend
+// description:
+//		Returns a hash containing the start and end days of the weekend according to local custom using locale,
+//		or by default in the user's locale.
+//		e.g. {start:6, end:0}
+
+	// from http://www.unicode.org/cldr/data/common/supplemental/supplementalData.xml:supplementalData/weekData/weekend{Start,End}
+	var weekendStart = {/*default is 6=Saturday*/
+		eg:5,il:5,sy:5,
+		'in':0,
+		ae:4,bh:4,dz:4,iq:4,jo:4,kw:4,lb:4,ly:4,ma:4,om:4,qa:4,sa:4,sd:4,tn:4,ye:4		
+	};
+
+	var weekendEnd = {/*default is 0=Sunday*/
+		ae:5,bh:5,dz:5,iq:5,jo:5,kw:5,lb:5,ly:5,ma:5,om:5,qa:5,sa:5,sd:5,tn:5,ye:5,af:5,ir:5,
+		eg:6,il:6,sy:6
+	};
+
+	var country = dojo.cldr.supplemental._region(locale);
+	var start = weekendStart[country];
+	var end = weekendEnd[country];
+	if(start === undefined){start=6;}
+	if(end === undefined){end=0;}
+	return {start:start, end:end}; /*Object {start,end}*/
+};
+
+}
+
+if(!dojo._hasResource["dojo.regexp"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.regexp"] = true;
+dojo.provide("dojo.regexp");
+
+/*=====
+dojo.regexp = {
+	// summary: Regular expressions and Builder resources
+};
+=====*/
+
+dojo.regexp.escapeString = function(/*String*/str, /*String?*/except){
+	//	summary:
+	//		Adds escape sequences for special characters in regular expressions
+	// except:
+	//		a String with special characters to be left unescaped
+
+	return str.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, function(ch){
+		if(except && except.indexOf(ch) != -1){
+			return ch;
+		}
+		return "\\" + ch;
+	}); // String
+}
+
+dojo.regexp.buildGroupRE = function(/*Object|Array*/arr, /*Function*/re, /*Boolean?*/nonCapture){
+	//	summary:
+	//		Builds a regular expression that groups subexpressions
+	//	description:
+	//		A utility function used by some of the RE generators. The
+	//		subexpressions are constructed by the function, re, in the second
+	//		parameter.  re builds one subexpression for each elem in the array
+	//		a, in the first parameter. Returns a string for a regular
+	//		expression that groups all the subexpressions.
+	// arr:
+	//		A single value or an array of values.
+	// re:
+	//		A function. Takes one parameter and converts it to a regular
+	//		expression. 
+	// nonCapture:
+	//		If true, uses non-capturing match, otherwise matches are retained
+	//		by regular expression. Defaults to false
+
+	// case 1: a is a single value.
+	if(!(arr instanceof Array)){
+		return re(arr); // String
+	}
+
+	// case 2: a is an array
+	var b = [];
+	for(var i = 0; i < arr.length; i++){
+		// convert each elem to a RE
+		b.push(re(arr[i]));
+	}
+
+	 // join the REs as alternatives in a RE group.
+	return dojo.regexp.group(b.join("|"), nonCapture); // String
+}
+
+dojo.regexp.group = function(/*String*/expression, /*Boolean?*/nonCapture){
+	// summary:
+	//		adds group match to expression
+	// nonCapture:
+	//		If true, uses non-capturing match, otherwise matches are retained
+	//		by regular expression. 
+	return "(" + (nonCapture ? "?:":"") + expression + ")"; // String
+}
+
+}
+
+if(!dojo._hasResource["dojo.string"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.string"] = true;
+dojo.provide("dojo.string");
+
+/*=====
+dojo.string = { 
+	// summary: String utilities for Dojo
+};
+=====*/
+
+dojo.string.rep = function(/*String*/str, /*Integer*/num){
+	//	summary:
+	//		Efficiently replicate a string `n` times.
+	//	str:
+	//		the string to replicate
+	//	num:
+	//		number of times to replicate the string
+	
+	if(num <= 0 || !str){ return ""; }
+	
+	var buf = [];
+	for(;;){
+		if(num & 1){
+			buf.push(str);
+		}
+		if(!(num >>= 1)){ break; }
+		str += str;
+	}
+	return buf.join("");	// String
+};
+
+dojo.string.pad = function(/*String*/text, /*Integer*/size, /*String?*/ch, /*Boolean?*/end){
+	//	summary:
+	//		Pad a string to guarantee that it is at least `size` length by
+	//		filling with the character `ch` at either the start or end of the
+	//		string. Pads at the start, by default.
+	//	text:
+	//		the string to pad
+	//	size:
+	//		length to provide padding
+	//	ch:
+	//		character to pad, defaults to '0'
+	//	end:
+	//		adds padding at the end if true, otherwise pads at start
+	//	example:
+	//	|	// Fill the string to length 10 with "+" characters on the right.  Yields "Dojo++++++".
+	//	|	dojo.string.pad("Dojo", 10, "+", true);
+
+	if(!ch){
+		ch = '0';
+	}
+	var out = String(text),
+		pad = dojo.string.rep(ch, Math.ceil((size - out.length) / ch.length));
+	return end ? out + pad : pad + out;	// String
+};
+
+dojo.string.substitute = function(	/*String*/		template, 
+									/*Object|Array*/map, 
+									/*Function?*/	transform, 
+									/*Object?*/		thisObject){
+	//	summary:
+	//		Performs parameterized substitutions on a string. Throws an
+	//		exception if any parameter is unmatched.
+	//	template: 
+	//		a string with expressions in the form `${key}` to be replaced or
+	//		`${key:format}` which specifies a format function. keys are case-sensitive. 
+	//	map:
+	//		hash to search for substitutions
+	//	transform: 
+	//		a function to process all parameters before substitution takes
+	//		place, e.g. dojo.string.encodeXML
+	//	thisObject: 
+	//		where to look for optional format function; default to the global
+	//		namespace
+	//	example:
+	//	|	// returns "File 'foo.html' is not found in directory '/temp'."
+	//	|	dojo.string.substitute(
+	//	|		"File '${0}' is not found in directory '${1}'.",
+	//	|		["foo.html","/temp"]
+	//	|	);
+	//	|
+	//	|	// also returns "File 'foo.html' is not found in directory '/temp'."
+	//	|	dojo.string.substitute(
+	//	|		"File '${name}' is not found in directory '${info.dir}'.",
+	//	|		{ name: "foo.html", info: { dir: "/temp" } }
+	//	|	);
+	//	example:
+	//		use a transform function to modify the values:
+	//	|	// returns "file 'foo.html' is not found in directory '/temp'."
+	//	|	dojo.string.substitute(
+	//	|		"${0} is not found in ${1}.",
+	//	|		["foo.html","/temp"],
+	//	|		function(str){
+	//	|			// try to figure out the type
+	//	|			var prefix = (str.charAt(0) == "/") ? "directory": "file";
+	//	|			return prefix + " '" + str + "'";
+	//	|		}
+	//	|	);
+	//	example:
+	//		use a formatter
+	//	|	// returns "thinger -- howdy"
+	//	|	dojo.string.substitute(
+	//	|		"${0:postfix}", ["thinger"], null, {
+	//	|			postfix: function(value, key){
+	//	|				return value + " -- howdy";
+	//	|			}
+	//	|		}
+	//	|	);
+
+	thisObject = thisObject||dojo.global;
+	transform = (!transform) ? 
+					function(v){ return v; } : 
+					dojo.hitch(thisObject, transform);
+
+	return template.replace(/\$\{([^\s\:\}]+)(?:\:([^\s\:\}]+))?\}/g, function(match, key, format){
+		var value = dojo.getObject(key, false, map);
+		if(format){
+			value = dojo.getObject(format, false, thisObject).call(thisObject, value, key);
+		}
+		return transform(value, key).toString();
+	}); // string
+};
+
+/*=====
+dojo.string.trim = function(str){
+	//	summary:
+	//		Trims whitespace from both sides of the string
+	//	str: String
+	//		String to be trimmed
+	//	returns: String
+	//		Returns the trimmed string
+	//	description:
+	//		This version of trim() was taken from [Steven Levithan's blog](http://blog.stevenlevithan.com/archives/faster-trim-javascript).
+	//		The short yet performant version of this function is dojo.trim(),
+	//		which is part of Dojo base.  Uses String.prototype.trim instead, if available.
+	return "";	// String
+}
+=====*/
+
+dojo.string.trim = String.prototype.trim ?
+	dojo.trim : // aliasing to the native function
+	function(str){
+		str = str.replace(/^\s+/, '');
+		for(var i = str.length - 1; i >= 0; i--){
+			if(/\S/.test(str.charAt(i))){
+				str = str.substring(0, i + 1);
+				break;
+			}
+		}
+		return str;
+	};
+
+}
+
+if(!dojo._hasResource["dojo.date.locale"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.date.locale"] = true;
+dojo.provide("dojo.date.locale");
+
+// Localization methods for Date.   Honor local customs using locale-dependent dojo.cldr data.
+
+
+
+
+
+
+
+// Load the bundles containing localization information for
+// names and formats
+
+
+//NOTE: Everything in this module assumes Gregorian calendars.
+// Other calendars will be implemented in separate modules.
+
+(function(){
+	// Format a pattern without literals
+	function formatPattern(dateObject, bundle, fullYear, pattern){
+		return pattern.replace(/([a-z])\1*/ig, function(match){
+			var s, pad;
+			var c = match.charAt(0);
+			var l = match.length;
+			var widthList = ["abbr", "wide", "narrow"];
+			switch(c){
+				case 'G':
+					s = bundle[(l < 4) ? "eraAbbr" : "eraNames"][dateObject.getFullYear() < 0 ? 0 : 1];
+					break;
+				case 'y':
+					s = dateObject.getFullYear();
+					switch(l){
+						case 1:
+							break;
+						case 2:
+							if(!fullYear){
+								s = String(s); s = s.substr(s.length - 2);
+								break;
+							}
+							// fallthrough
+						default:
+							pad = true;
+					}
+					break;
+				case 'Q':
+				case 'q':
+					s = Math.ceil((dateObject.getMonth()+1)/3);
+//					switch(l){
+//						case 1: case 2:
+							pad = true;
+//							break;
+//						case 3: case 4: // unimplemented
+//					}
+					break;
+				case 'M':
+					var m = dateObject.getMonth();
+					if(l<3){
+						s = m+1; pad = true;
+					}else{
+						var propM = ["months", "format", widthList[l-3]].join("-");
+						s = bundle[propM][m];
+					}
+					break;
+				case 'w':
+					var firstDay = 0;
+					s = dojo.date.locale._getWeekOfYear(dateObject, firstDay); pad = true;
+					break;
+				case 'd':
+					s = dateObject.getDate(); pad = true;
+					break;
+				case 'D':
+					s = dojo.date.locale._getDayOfYear(dateObject); pad = true;
+					break;
+				case 'E':
+					var d = dateObject.getDay();
+					if(l<3){
+						s = d+1; pad = true;
+					}else{
+						var propD = ["days", "format", widthList[l-3]].join("-");
+						s = bundle[propD][d];
+					}
+					break;
+				case 'a':
+					var timePeriod = (dateObject.getHours() < 12) ? 'am' : 'pm';
+					s = bundle[timePeriod];
+					break;
+				case 'h':
+				case 'H':
+				case 'K':
+				case 'k':
+					var h = dateObject.getHours();
+					// strange choices in the date format make it impossible to write this succinctly
+					switch (c){
+						case 'h': // 1-12
+							s = (h % 12) || 12;
+							break;
+						case 'H': // 0-23
+							s = h;
+							break;
+						case 'K': // 0-11
+							s = (h % 12);
+							break;
+						case 'k': // 1-24
+							s = h || 24;
+							break;
+					}
+					pad = true;
+					break;
+				case 'm':
+					s = dateObject.getMinutes(); pad = true;
+					break;
+				case 's':
+					s = dateObject.getSeconds(); pad = true;
+					break;
+				case 'S':
+					s = Math.round(dateObject.getMilliseconds() * Math.pow(10, l-3)); pad = true;
+					break;
+				case 'v': // FIXME: don't know what this is. seems to be same as z?
+				case 'z':
+					// We only have one timezone to offer; the one from the browser
+					s = dojo.date.getTimezoneName(dateObject);
+					if(s){break;}
+					l=4;
+					// fallthrough... use GMT if tz not available
+				case 'Z':
+					var offset = dateObject.getTimezoneOffset();
+					var tz = [
+						(offset<=0 ? "+" : "-"),
+						dojo.string.pad(Math.floor(Math.abs(offset)/60), 2),
+						dojo.string.pad(Math.abs(offset)% 60, 2)
+					];
+					if(l==4){
+						tz.splice(0, 0, "GMT");
+						tz.splice(3, 0, ":");
+					}
+					s = tz.join("");
+					break;
+//				case 'Y': case 'u': case 'W': case 'F': case 'g': case 'A': case 'e':
+//					
+				default:
+					throw new Error("dojo.date.locale.format: invalid pattern char: "+pattern);
+			}
+			if(pad){ s = dojo.string.pad(s, l); }
+			return s;
+		});
+	}
+
+/*=====
+	dojo.date.locale.__FormatOptions = function(){
+	//	selector: String
+	//		choice of 'time','date' (default: date and time)
+	//	formatLength: String
+	//		choice of long, short, medium or full (plus any custom additions).  Defaults to 'short'
+	//	datePattern:String
+	//		override pattern with this string
+	//	timePattern:String
+	//		override pattern with this string
+	//	am: String
+	//		override strings for am in times
+	//	pm: String
+	//		override strings for pm in times
+	//	locale: String
+	//		override the locale used to determine formatting rules
+	//	fullYear: Boolean
+	//		(format only) use 4 digit years whenever 2 digit years are called for
+	//	strict: Boolean
+	//		(parse only) strict parsing, off by default
+		this.selector = selector;
+		this.formatLength = formatLength;
+		this.datePattern = datePattern;
+		this.timePattern = timePattern;
+		this.am = am;
+		this.pm = pm;
+		this.locale = locale;
+		this.fullYear = fullYear;
+		this.strict = strict;
+	}
+=====*/
+
+dojo.date.locale.format = function(/*Date*/dateObject, /*dojo.date.locale.__FormatOptions?*/options){
+	// summary:
+	//		Format a Date object as a String, using locale-specific settings.
+	//
+	// description:
+	//		Create a string from a Date object using a known localized pattern.
+	//		By default, this method formats both date and time from dateObject.
+	//		Formatting patterns are chosen appropriate to the locale.  Different
+	//		formatting lengths may be chosen, with "full" used by default.
+	//		Custom patterns may be used or registered with translations using
+	//		the dojo.date.locale.addCustomFormats method.
+	//		Formatting patterns are implemented using [the syntax described at
+	//		unicode.org](http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns)
+	//
+	// dateObject:
+	//		the date and/or time to be formatted.  If a time only is formatted,
+	//		the values in the year, month, and day fields are irrelevant.  The
+	//		opposite is true when formatting only dates.
+
+	options = options || {};
+
+	var locale = dojo.i18n.normalizeLocale(options.locale);
+	var formatLength = options.formatLength || 'short';
+	var bundle = dojo.date.locale._getGregorianBundle(locale);
+	var str = [];
+	var sauce = dojo.hitch(this, formatPattern, dateObject, bundle, options.fullYear);
+	if(options.selector == "year"){
+		// Special case as this is not yet driven by CLDR data
+		var year = dateObject.getFullYear();
+		if(locale.match(/^zh|^ja/)){
+			year += "\u5E74";
+		}
+		return year;
+	}
+	if(options.selector != "time"){
+		var datePattern = options.datePattern || bundle["dateFormat-"+formatLength];
+		if(datePattern){str.push(_processPattern(datePattern, sauce));}
+	}
+	if(options.selector != "date"){
+		var timePattern = options.timePattern || bundle["timeFormat-"+formatLength];
+		if(timePattern){str.push(_processPattern(timePattern, sauce));}
+	}
+	var result = str.join(" "); //TODO: use locale-specific pattern to assemble date + time
+	return result; // String
+};
+
+dojo.date.locale.regexp = function(/*dojo.date.locale.__FormatOptions?*/options){
+	// summary:
+	//		Builds the regular needed to parse a localized date
+
+	return dojo.date.locale._parseInfo(options).regexp; // String
+};
+
+dojo.date.locale._parseInfo = function(/*dojo.date.locale.__FormatOptions?*/options){
+	options = options || {};
+	var locale = dojo.i18n.normalizeLocale(options.locale);
+	var bundle = dojo.date.locale._getGregorianBundle(locale);
+	var formatLength = options.formatLength || 'short';
+	var datePattern = options.datePattern || bundle["dateFormat-" + formatLength];
+	var timePattern = options.timePattern || bundle["timeFormat-" + formatLength];
+	var pattern;
+	if(options.selector == 'date'){
+		pattern = datePattern;
+	}else if(options.selector == 'time'){
+		pattern = timePattern;
+	}else{
+		pattern = datePattern + ' ' + timePattern; //TODO: use locale-specific pattern to assemble date + time
+	}
+
+	var tokens = [];
+	var re = _processPattern(pattern, dojo.hitch(this, _buildDateTimeRE, tokens, bundle, options));
+	return {regexp: re, tokens: tokens, bundle: bundle};
+};
+
+dojo.date.locale.parse = function(/*String*/value, /*dojo.date.locale.__FormatOptions?*/options){
+	// summary:
+	//		Convert a properly formatted string to a primitive Date object,
+	//		using locale-specific settings.
+	//
+	// description:
+	//		Create a Date object from a string using a known localized pattern.
+	//		By default, this method parses looking for both date and time in the string.
+	//		Formatting patterns are chosen appropriate to the locale.  Different
+	//		formatting lengths may be chosen, with "full" used by default.
+	//		Custom patterns may be used or registered with translations using
+	//		the dojo.date.locale.addCustomFormats method.
+	//	
+	//		Formatting patterns are implemented using [the syntax described at
+	//		unicode.org](http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns)
+	//		When two digit years are used, a century is chosen according to a sliding 
+	//		window of 80 years before and 20 years after present year, for both `yy` and `yyyy` patterns.
+	//		year < 100CE requires strict mode.
+	//
+	// value:
+	//		A string representation of a date
+
+	var info = dojo.date.locale._parseInfo(options);
+	var tokens = info.tokens, bundle = info.bundle;
+	var re = new RegExp("^" + info.regexp + "$", info.strict ? "" : "i");
+	var match = re.exec(value);
+	if(!match){ return null; } // null
+
+	var widthList = ['abbr', 'wide', 'narrow'];
+	var result = [1970,0,1,0,0,0,0]; // will get converted to a Date at the end
+	var amPm = "";
+	var valid = dojo.every(match, function(v, i){
+		if(!i){return true;}
+		var token=tokens[i-1];
+		var l=token.length;
+		switch(token.charAt(0)){
+			case 'y':
+				if(l != 2 && options.strict){
+					//interpret year literally, so '5' would be 5 A.D.
+					result[0] = v;
+				}else{
+					if(v<100){
+						v = Number(v);
+						//choose century to apply, according to a sliding window
+						//of 80 years before and 20 years after present year
+						var year = '' + new Date().getFullYear();
+						var century = year.substring(0, 2) * 100;
+						var cutoff = Math.min(Number(year.substring(2, 4)) + 20, 99);
+						var num = (v < cutoff) ? century + v : century - 100 + v;
+						result[0] = num;
+					}else{
+						//we expected 2 digits and got more...
+						if(options.strict){
+							return false;
+						}
+						//interpret literally, so '150' would be 150 A.D.
+						//also tolerate '1950', if 'yyyy' input passed to 'yy' format
+						result[0] = v;
+					}
+				}
+				break;
+			case 'M':
+				if(l>2){
+					var months = bundle['months-format-' + widthList[l-3]].concat();
+					if(!options.strict){
+						//Tolerate abbreviating period in month part
+						//Case-insensitive comparison
+						v = v.replace(".","").toLowerCase();
+						months = dojo.map(months, function(s){ return s.replace(".","").toLowerCase(); } );
+					}
+					v = dojo.indexOf(months, v);
+					if(v == -1){
+//						
+						return false;
+					}
+				}else{
+					v--;
+				}
+				result[1] = v;
+				break;
+			case 'E':
+			case 'e':
+				var days = bundle['days-format-' + widthList[l-3]].concat();
+				if(!options.strict){
+					//Case-insensitive comparison
+					v = v.toLowerCase();
+					days = dojo.map(days, function(d){return d.toLowerCase();});
+				}
+				v = dojo.indexOf(days, v);
+				if(v == -1){
+//					
+					return false;
+				}
+
+				//TODO: not sure what to actually do with this input,
+				//in terms of setting something on the Date obj...?
+				//without more context, can't affect the actual date
+				//TODO: just validate?
+				break;
+			case 'D':
+				result[1] = 0;
+				// fallthrough...
+			case 'd':
+				result[2] = v;
+				break;
+			case 'a': //am/pm
+				var am = options.am || bundle.am;
+				var pm = options.pm || bundle.pm;
+				if(!options.strict){
+					var period = /\./g;
+					v = v.replace(period,'').toLowerCase();
+					am = am.replace(period,'').toLowerCase();
+					pm = pm.replace(period,'').toLowerCase();
+				}
+				if(options.strict && v != am && v != pm){
+//					
+					return false;
+				}
+
+				// we might not have seen the hours field yet, so store the state and apply hour change later
+				amPm = (v == pm) ? 'p' : (v == am) ? 'a' : '';
+				break;
+			case 'K': //hour (1-24)
+				if(v == 24){ v = 0; }
+				// fallthrough...
+			case 'h': //hour (1-12)
+			case 'H': //hour (0-23)
+			case 'k': //hour (0-11)
+				//TODO: strict bounds checking, padding
+				if(v > 23){
+//					
+					return false;
+				}
+
+				//in the 12-hour case, adjusting for am/pm requires the 'a' part
+				//which could come before or after the hour, so we will adjust later
+				result[3] = v;
+				break;
+			case 'm': //minutes
+				result[4] = v;
+				break;
+			case 's': //seconds
+				result[5] = v;
+				break;
+			case 'S': //milliseconds
+				result[6] = v;
+//				break;
+//			case 'w':
+//TODO				var firstDay = 0;
+//			default:
+//TODO: throw?
+//				
+		}
+		return true;
+	});
+
+	var hours = +result[3];
+	if(amPm === 'p' && hours < 12){
+		result[3] = hours + 12; //e.g., 3pm -> 15
+	}else if(amPm === 'a' && hours == 12){
+		result[3] = 0; //12am -> 0
+	}
+
+	//TODO: implement a getWeekday() method in order to test 
+	//validity of input strings containing 'EEE' or 'EEEE'...
+
+	var dateObject = new Date(result[0], result[1], result[2], result[3], result[4], result[5], result[6]); // Date
+	if(options.strict){
+		dateObject.setFullYear(result[0]);
+	}
+
+	// Check for overflow.  The Date() constructor normalizes things like April 32nd...
+	//TODO: why isn't this done for times as well?
+	var allTokens = tokens.join(""),
+		dateToken = allTokens.indexOf('d') != -1,
+		monthToken = allTokens.indexOf('M') != -1;
+
+	if(!valid ||
+		(monthToken && dateObject.getMonth() > result[1]) ||
+		(dateToken && dateObject.getDate() > result[2])){
+		return null;
+	}
+
+	// Check for underflow, due to DST shifts.  See #9366
+	// This assumes a 1 hour dst shift correction at midnight
+	// We could compare the timezone offset after the shift and add the difference instead.
+	if((monthToken && dateObject.getMonth() < result[1]) ||
+		(dateToken && dateObject.getDate() < result[2])){
+		dateObject = dojo.date.add(dateObject, "hour", 1);
+	}
+
+	return dateObject; // Date
+};
+
+function _processPattern(pattern, applyPattern, applyLiteral, applyAll){
+	//summary: Process a pattern with literals in it
+
+	// Break up on single quotes, treat every other one as a literal, except '' which becomes '
+	var identity = function(x){return x;};
+	applyPattern = applyPattern || identity;
+	applyLiteral = applyLiteral || identity;
+	applyAll = applyAll || identity;
+
+	//split on single quotes (which escape literals in date format strings) 
+	//but preserve escaped single quotes (e.g., o''clock)
+	var chunks = pattern.match(/(''|[^'])+/g); 
+	var literal = pattern.charAt(0) == "'";
+
+	dojo.forEach(chunks, function(chunk, i){
+		if(!chunk){
+			chunks[i]='';
+		}else{
+			chunks[i]=(literal ? applyLiteral : applyPattern)(chunk);
+			literal = !literal;
+		}
+	});
+	return applyAll(chunks.join(''));
+}
+
+function _buildDateTimeRE(tokens, bundle, options, pattern){
+	pattern = dojo.regexp.escapeString(pattern);
+	if(!options.strict){ pattern = pattern.replace(" a", " ?a"); } // kludge to tolerate no space before am/pm
+	return pattern.replace(/([a-z])\1*/ig, function(match){
+		// Build a simple regexp.  Avoid captures, which would ruin the tokens list
+		var s;
+		var c = match.charAt(0);
+		var l = match.length;
+		var p2 = '', p3 = '';
+		if(options.strict){
+			if(l > 1){ p2 = '0' + '{'+(l-1)+'}'; }
+			if(l > 2){ p3 = '0' + '{'+(l-2)+'}'; }
+		}else{
+			p2 = '0?'; p3 = '0{0,2}';
+		}
+		switch(c){
+			case 'y':
+				s = '\\d{2,4}';
+				break;
+			case 'M':
+				s = (l>2) ? '\\S+?' : p2+'[1-9]|1[0-2]';
+				break;
+			case 'D':
+				s = p2+'[1-9]|'+p3+'[1-9][0-9]|[12][0-9][0-9]|3[0-5][0-9]|36[0-6]';
+				break;
+			case 'd':
+				s = '[12]\\d|'+p2+'[1-9]|3[01]';
+				break;
+			case 'w':
+				s = p2+'[1-9]|[1-4][0-9]|5[0-3]';
+				break;
+		    case 'E':
+				s = '\\S+';
+				break;
+			case 'h': //hour (1-12)
+				s = p2+'[1-9]|1[0-2]';
+				break;
+			case 'k': //hour (0-11)
+				s = p2+'\\d|1[01]';
+				break;
+			case 'H': //hour (0-23)
+				s = p2+'\\d|1\\d|2[0-3]';
+				break;
+			case 'K': //hour (1-24)
+				s = p2+'[1-9]|1\\d|2[0-4]';
+				break;
+			case 'm':
+			case 's':
+				s = '[0-5]\\d';
+				break;
+			case 'S':
+				s = '\\d{'+l+'}';
+				break;
+			case 'a':
+				var am = options.am || bundle.am || 'AM';
+				var pm = options.pm || bundle.pm || 'PM';
+				if(options.strict){
+					s = am + '|' + pm;
+				}else{
+					s = am + '|' + pm;
+					if(am != am.toLowerCase()){ s += '|' + am.toLowerCase(); }
+					if(pm != pm.toLowerCase()){ s += '|' + pm.toLowerCase(); }
+					if(s.indexOf('.') != -1){ s += '|' + s.replace(/\./g, ""); }
+				}
+				s = s.replace(/\./g, "\\.");
+				break;
+			default:
+			// case 'v':
+			// case 'z':
+			// case 'Z':
+				s = ".*";
+//				
+		}
+
+		if(tokens){ tokens.push(match); }
+
+		return "(" + s + ")"; // add capture
+	}).replace(/[\xa0 ]/g, "[\\s\\xa0]"); // normalize whitespace.  Need explicit handling of \xa0 for IE.
+}
+})();
+
+(function(){
+var _customFormats = [];
+dojo.date.locale.addCustomFormats = function(/*String*/packageName, /*String*/bundleName){
+	// summary:
+	//		Add a reference to a bundle containing localized custom formats to be
+	//		used by date/time formatting and parsing routines.
+	//
+	// description:
+	//		The user may add custom localized formats where the bundle has properties following the
+	//		same naming convention used by dojo.cldr: `dateFormat-xxxx` / `timeFormat-xxxx`
+	//		The pattern string should match the format used by the CLDR.
+	//		See dojo.date.locale.format() for details.
+	//		The resources must be loaded by dojo.requireLocalization() prior to use
+
+	_customFormats.push({pkg:packageName,name:bundleName});
+};
+
+dojo.date.locale._getGregorianBundle = function(/*String*/locale){
+	var gregorian = {};
+	dojo.forEach(_customFormats, function(desc){
+		var bundle = dojo.i18n.getLocalization(desc.pkg, desc.name, locale);
+		gregorian = dojo.mixin(gregorian, bundle);
+	}, this);
+	return gregorian; /*Object*/
+};
+})();
+
+dojo.date.locale.addCustomFormats("dojo.cldr","gregorian");
+
+dojo.date.locale.getNames = function(/*String*/item, /*String*/type, /*String?*/context, /*String?*/locale){
+	// summary:
+	//		Used to get localized strings from dojo.cldr for day or month names.
+	//
+	// item:
+	//	'months' || 'days'
+	// type:
+	//	'wide' || 'narrow' || 'abbr' (e.g. "Monday", "Mon", or "M" respectively, in English)
+	// context:
+	//	'standAlone' || 'format' (default)
+	// locale:
+	//	override locale used to find the names
+
+	var label;
+	var lookup = dojo.date.locale._getGregorianBundle(locale);
+	var props = [item, context, type];
+	if(context == 'standAlone'){
+		var key = props.join('-');
+		label = lookup[key];
+		// Fall back to 'format' flavor of name
+		if(label[0] == 1){ label = undefined; } // kludge, in the absense of real aliasing support in dojo.cldr
+	}
+	props[1] = 'format';
+
+	// return by copy so changes won't be made accidentally to the in-memory model
+	return (label || lookup[props.join('-')]).concat(); /*Array*/
+};
+
+dojo.date.locale.isWeekend = function(/*Date?*/dateObject, /*String?*/locale){
+	// summary:
+	//	Determines if the date falls on a weekend, according to local custom.
+
+	var weekend = dojo.cldr.supplemental.getWeekend(locale);
+	var day = (dateObject || new Date()).getDay();
+	if(weekend.end < weekend.start){
+		weekend.end += 7;
+		if(day < weekend.start){ day += 7; }
+	}
+	return day >= weekend.start && day <= weekend.end; // Boolean
+};
+
+// These are used only by format and strftime.  Do they need to be public?  Which module should they go in?
+
+dojo.date.locale._getDayOfYear = function(/*Date*/dateObject){
+	// summary: gets the day of the year as represented by dateObject
+	return dojo.date.difference(new Date(dateObject.getFullYear(), 0, 1, dateObject.getHours()), dateObject) + 1; // Number
+};
+
+dojo.date.locale._getWeekOfYear = function(/*Date*/dateObject, /*Number*/firstDayOfWeek){
+	if(arguments.length == 1){ firstDayOfWeek = 0; } // Sunday
+
+	var firstDayOfYear = new Date(dateObject.getFullYear(), 0, 1).getDay();
+	var adj = (firstDayOfYear - firstDayOfWeek + 7) % 7;
+	var week = Math.floor((dojo.date.locale._getDayOfYear(dateObject) + adj - 1) / 7);
+
+	// if year starts on the specified day, start counting weeks at 1
+	if(firstDayOfYear == firstDayOfWeek){ week++; }
+
+	return week; // Number
+};
+
+}
+
+if(!dojo._hasResource["dijit._base.focus"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._base.focus"] = true;
+dojo.provide("dijit._base.focus");
+
+// summary:
+//		These functions are used to query or set the focus and selection.
+//
+//		Also, they trace when widgets become actived/deactivated,
+//		so that the widget can fire _onFocus/_onBlur events.
+//		"Active" here means something similar to "focused", but
+//		"focus" isn't quite the right word because we keep track of
+//		a whole stack of "active" widgets.  Example:  Combobutton --> Menu -->
+//		MenuItem.   The onBlur event for Combobutton doesn't fire due to focusing
+//		on the Menu or a MenuItem, since they are considered part of the
+//		Combobutton widget.  It only happens when focus is shifted
+//		somewhere completely different.
+
+dojo.mixin(dijit,
+{
+	// _curFocus: DomNode
+	//		Currently focused item on screen
+	_curFocus: null,
+
+	// _prevFocus: DomNode
+	//		Previously focused item on screen
+	_prevFocus: null,
+
+	isCollapsed: function(){
+		// summary:
+		//		Returns true if there is no text selected
+		var _document = dojo.doc;
+		if(_document.selection){ // IE
+			var s=_document.selection;
+			if(s.type=='Text'){
+				return !s.createRange().htmlText.length; // Boolean
+			}else{ //Control range
+				return !s.createRange().length; // Boolean
+			}
+		}else{
+			var _window = dojo.global;
+			var selection = _window.getSelection();
+			
+			if(dojo.isString(selection)){ // Safari
+				// TODO: this is dead code; safari is taking the else branch.  remove after 1.3.
+				return !selection; // Boolean
+			}else{ // Mozilla/W3
+				return !selection || selection.isCollapsed || !selection.toString(); // Boolean
+			}
+		}
+	},
+
+	getBookmark: function(){
+		// summary:
+		//		Retrieves a bookmark that can be used with moveToBookmark to return to the same range
+		var bookmark, selection = dojo.doc.selection;
+		if(selection){ // IE
+			var range = selection.createRange();
+			if(selection.type.toUpperCase()=='CONTROL'){
+				if(range.length){
+					bookmark=[];
+					var i=0,len=range.length;
+					while(i<len){
+						bookmark.push(range.item(i++));
+					}
+				}else{
+					bookmark=null;
+				}
+			}else{
+				bookmark = range.getBookmark();
+			}
+		}else{
+			if(window.getSelection){
+				selection = dojo.global.getSelection();
+				if(selection){
+					range = selection.getRangeAt(0);
+					bookmark = range.cloneRange();
+				}
+			}else{
+				console.warn("No idea how to store the current selection for this browser!");
+			}
+		}
+		return bookmark; // Array
+	},
+
+	moveToBookmark: function(/*Object*/bookmark){
+		// summary:
+		//		Moves current selection to a bookmark
+		// bookmark:
+		//		This should be a returned object from dojo.html.selection.getBookmark()
+		var _document = dojo.doc;
+		if(_document.selection){ // IE
+			var range;
+			if(dojo.isArray(bookmark)){
+				range = _document.body.createControlRange();
+				//range.addElement does not have call/apply method, so can not call it directly
+				//range is not available in "range.addElement(item)", so can't use that either
+				dojo.forEach(bookmark, function(n){
+					range.addElement(n);
+				});
+			}else{
+				range = _document.selection.createRange();
+				range.moveToBookmark(bookmark);
+			}
+			range.select();
+		}else{ //Moz/W3C
+			var selection = dojo.global.getSelection && dojo.global.getSelection();
+			if(selection && selection.removeAllRanges){
+				selection.removeAllRanges();
+				selection.addRange(bookmark);
+			}else{
+				console.warn("No idea how to restore selection for this browser!");
+			}
+		}
+	},
+
+	getFocus: function(/*Widget?*/menu, /*Window?*/openedForWindow){
+		// summary:
+		//		Returns the current focus and selection.
+		//		Called when a popup appears (either a top level menu or a dialog),
+		//		or when a toolbar/menubar receives focus
+		//
+		// menu:
+		//		The menu that's being opened
+		//
+		// openedForWindow:
+		//		iframe in which menu was opened
+		//
+		// returns:
+		//		A handle to restore focus/selection
+
+		return {
+			// Node to return focus to
+			node: menu && dojo.isDescendant(dijit._curFocus, menu.domNode) ? dijit._prevFocus : dijit._curFocus,
+
+			// Previously selected text
+			bookmark:
+				!dojo.withGlobal(openedForWindow||dojo.global, dijit.isCollapsed) ?
+				dojo.withGlobal(openedForWindow||dojo.global, dijit.getBookmark) :
+				null,
+
+			openedForWindow: openedForWindow
+		}; // Object
+	},
+
+	focus: function(/*Object || DomNode */ handle){
+		// summary:
+		//		Sets the focused node and the selection according to argument.
+		//		To set focus to an iframe's content, pass in the iframe itself.
+		// handle:
+		//		object returned by get(), or a DomNode
+
+		if(!handle){ return; }
+
+		var node = "node" in handle ? handle.node : handle,		// because handle is either DomNode or a composite object
+			bookmark = handle.bookmark,
+			openedForWindow = handle.openedForWindow;
+
+		// Set the focus
+		// Note that for iframe's we need to use the <iframe> to follow the parentNode chain,
+		// but we need to set focus to iframe.contentWindow
+		if(node){
+			var focusNode = (node.tagName.toLowerCase()=="iframe") ? node.contentWindow : node;
+			if(focusNode && focusNode.focus){
+				try{
+					// Gecko throws sometimes if setting focus is impossible,
+					// node not displayed or something like that
+					focusNode.focus();
+				}catch(e){/*quiet*/}
+			}			
+			dijit._onFocusNode(node);
+		}
+
+		// set the selection
+		// do not need to restore if current selection is not empty
+		// (use keyboard to select a menu item)
+		if(bookmark && dojo.withGlobal(openedForWindow||dojo.global, dijit.isCollapsed)){
+			if(openedForWindow){
+				openedForWindow.focus();
+			}
+			try{
+				dojo.withGlobal(openedForWindow||dojo.global, dijit.moveToBookmark, null, [bookmark]);
+			}catch(e){
+				/*squelch IE internal error, see http://trac.dojotoolkit.org/ticket/1984 */
+			}
+		}
+	},
+
+	// _activeStack: Array
+	//		List of currently active widgets (focused widget and it's ancestors)
+	_activeStack: [],
+
+	registerIframe: function(/*DomNode*/ iframe){
+		// summary:
+		//		Registers listeners on the specified iframe so that any click
+		//		or focus event on that iframe (or anything in it) is reported
+		//		as a focus/click event on the <iframe> itself.
+		// description:
+		//		Currently only used by editor.
+		dijit.registerWin(iframe.contentWindow, iframe);
+	},
+		
+
+	registerWin: function(/*Window?*/targetWindow, /*DomNode?*/ effectiveNode){
+		// summary:
+		//		Registers listeners on the specified window (either the main
+		//		window or an iframe's window) to detect when the user has clicked somewhere
+		//		or focused somewhere.
+		// description:
+		//		Users should call registerIframe() instead of this method.
+		// targetWindow:
+		//		If specified this is the window associated with the iframe,
+		//		i.e. iframe.contentWindow.
+		// effectiveNode:
+		//		If specified, report any focus events inside targetWindow as
+		//		an event on effectiveNode, rather than on evt.target.
+
+		// TODO: make this function private in 2.0; Editor/users should call registerIframe(),
+		// or if Editor stops using <iframe> altogether than we can probably just drop
+		// the whole public API.
+
+		dojo.connect(targetWindow.document, "onmousedown", function(evt){
+			dijit._justMouseDowned = true;
+			setTimeout(function(){ dijit._justMouseDowned = false; }, 0);
+			dijit._onTouchNode(effectiveNode||evt.target||evt.srcElement);
+		});
+		//dojo.connect(targetWindow, "onscroll", ???);
+
+		// Listen for blur and focus events on targetWindow's document.
+		// IIRC, I'm using attachEvent() rather than dojo.connect() because focus/blur events don't bubble
+		// through dojo.connect(), and also maybe to catch the focus events early, before onfocus handlers
+		// fire.
+		var doc = targetWindow.document;
+		if(doc){
+			if(dojo.isIE){
+				doc.attachEvent('onactivate', function(evt){
+					if(evt.srcElement.tagName.toLowerCase() != "#document"){
+						dijit._onFocusNode(effectiveNode||evt.srcElement);
+					}
+				});
+				doc.attachEvent('ondeactivate', function(evt){
+					dijit._onBlurNode(effectiveNode||evt.srcElement);
+				});
+			}else{
+				doc.addEventListener('focus', function(evt){
+					dijit._onFocusNode(effectiveNode||evt.target);
+				}, true);
+				doc.addEventListener('blur', function(evt){
+					dijit._onBlurNode(effectiveNode||evt.target);
+				}, true);
+			}
+		}
+		doc = null;	// prevent memory leak (apparent circular reference via closure)
+	},
+
+	_onBlurNode: function(/*DomNode*/ node){
+		// summary:
+		// 		Called when focus leaves a node.
+		//		Usually ignored, _unless_ it *isn't* follwed by touching another node,
+		//		which indicates that we tabbed off the last field on the page,
+		//		in which case every widget is marked inactive
+		dijit._prevFocus = dijit._curFocus;
+		dijit._curFocus = null;
+
+		if(dijit._justMouseDowned){
+			// the mouse down caused a new widget to be marked as active; this blur event
+			// is coming late, so ignore it.
+			return;
+		}
+
+		// if the blur event isn't followed by a focus event then mark all widgets as inactive.
+		if(dijit._clearActiveWidgetsTimer){
+			clearTimeout(dijit._clearActiveWidgetsTimer);
+		}
+		dijit._clearActiveWidgetsTimer = setTimeout(function(){
+			delete dijit._clearActiveWidgetsTimer;
+			dijit._setStack([]);
+			dijit._prevFocus = null;
+		}, 100);
+	},
+
+	_onTouchNode: function(/*DomNode*/ node){
+		// summary:
+		//		Callback when node is focused or mouse-downed
+
+		// ignore the recent blurNode event
+		if(dijit._clearActiveWidgetsTimer){
+			clearTimeout(dijit._clearActiveWidgetsTimer);
+			delete dijit._clearActiveWidgetsTimer;
+		}
+
+		// compute stack of active widgets (ex: ComboButton --> Menu --> MenuItem)
+		var newStack=[];
+		try{
+			while(node){
+				if(node.dijitPopupParent){
+					node=dijit.byId(node.dijitPopupParent).domNode;
+				}else if(node.tagName && node.tagName.toLowerCase()=="body"){
+					// is this the root of the document or just the root of an iframe?
+					if(node===dojo.body()){
+						// node is the root of the main document
+						break;
+					}
+					// otherwise, find the iframe this node refers to (can't access it via parentNode,
+					// need to do this trick instead). window.frameElement is supported in IE/FF/Webkit
+					node=dijit.getDocumentWindow(node.ownerDocument).frameElement;
+				}else{
+					var id = node.getAttribute && node.getAttribute("widgetId");
+					if(id){
+						newStack.unshift(id);
+					}
+					node=node.parentNode;
+				}
+			}
+		}catch(e){ /* squelch */ }
+
+		dijit._setStack(newStack);
+	},
+
+	_onFocusNode: function(/*DomNode*/ node){
+		// summary:
+		//		Callback when node is focused
+
+		if(!node){
+			return;
+		}
+
+		if(node.nodeType == 9){
+			// Ignore focus events on the document itself.  This is here so that
+			// (for example) clicking the up/down arrows of a spinner
+			// (which don't get focus) won't cause that widget to blur. (FF issue)
+			return;
+		}
+
+		dijit._onTouchNode(node);
+
+		if(node==dijit._curFocus){ return; }
+		if(dijit._curFocus){
+			dijit._prevFocus = dijit._curFocus;
+		}
+		dijit._curFocus = node;
+		dojo.publish("focusNode", [node]);
+	},
+
+	_setStack: function(newStack){
+		// summary:
+		//		The stack of active widgets has changed.  Send out appropriate events and records new stack.
+
+		var oldStack = dijit._activeStack;
+		dijit._activeStack = newStack;
+
+		// compare old stack to new stack to see how many elements they have in common
+		for(var nCommon=0; nCommon<Math.min(oldStack.length, newStack.length); nCommon++){
+			if(oldStack[nCommon] != newStack[nCommon]){
+				break;
+			}
+		}
+
+		// for all elements that have gone out of focus, send blur event
+		for(var i=oldStack.length-1; i>=nCommon; i--){
+			var widget = dijit.byId(oldStack[i]);
+			if(widget){
+				widget._focused = false;
+				widget._hasBeenBlurred = true;
+				if(widget._onBlur){
+					widget._onBlur();
+				}
+				if (widget._setStateClass){
+					widget._setStateClass();
+				}
+				dojo.publish("widgetBlur", [widget]);
+			}
+		}
+
+		// for all element that have come into focus, send focus event
+		for(i=nCommon; i<newStack.length; i++){
+			widget = dijit.byId(newStack[i]);
+			if(widget){
+				widget._focused = true;
+				if(widget._onFocus){
+					widget._onFocus();
+				}
+				if (widget._setStateClass){
+					widget._setStateClass();
+				}
+				dojo.publish("widgetFocus", [widget]);
+			}
+		}
+	}
+});
+
+// register top window and all the iframes it contains
+dojo.addOnLoad(function(){dijit.registerWin(window); });
+
+}
+
+if(!dojo._hasResource["dijit._base.manager"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._base.manager"] = true;
+dojo.provide("dijit._base.manager");
+
+dojo.declare("dijit.WidgetSet", null, {
+	// summary:
+	//		A set of widgets indexed by id. A default instance of this class is 
+	//		available as `dijit.registry`
+	//
+	// example:
+	//		Create a small list of widgets:
+	//		|	var ws = new dijit.WidgetSet();
+	//		|	ws.add(dijit.byId("one"));
+	//		| 	ws.add(dijit.byId("two"));
+	//		|	// destroy both:
+	//		|	ws.forEach(function(w){ w.destroy(); });
+	//
+	// example:
+	//		Using dijit.registry:
+	//		|	dijit.registry.forEach(function(w){ /* do something */ });
+	
+	constructor: function(){
+		this._hash = {};
+	},
+
+	add: function(/*Widget*/ widget){
+		// summary:
+		//		Add a widget to this list. If a duplicate ID is detected, a error is thrown.
+		//
+		// widget: dijit._Widget
+		//		Any dijit._Widget subclass.
+		if(this._hash[widget.id]){
+			throw new Error("Tried to register widget with id==" + widget.id + " but that id is already registered");
+		}
+		this._hash[widget.id]=widget;
+	},
+
+	remove: function(/*String*/ id){
+		// summary:
+		//		Remove a widget from this WidgetSet. Does not destroy the widget; simply
+		//		removes the reference.
+		delete this._hash[id];
+	},
+
+	forEach: function(/*Function*/ func){
+		// summary:
+		//		Call specified function for each widget in this set.
+		//
+		// func:
+		//		A callback function to run for each item. Is passed a the widget.
+		//
+		// example:
+		//		Using the default `dijit.registry` instance:
+		//		|	dijit.registry.forEach(function(widget){
+		//		|			
+		//		|	});
+		for(var id in this._hash){
+			func(this._hash[id]);
+		}
+	},
+
+	filter: function(/*Function*/ filter){
+		// summary:
+		//		Filter down this WidgetSet to a smaller new WidgetSet
+		//		Works the same as `dojo.filter` and `dojo.NodeList.filter`
+		//		
+		// filter:
+		//		Callback function to test truthiness.
+		//
+		// example:
+		//		Arbitrary: select the odd widgets in this list
+		//		|	var i = 0;
+		//		|	dijit.registry.filter(function(w){
+		//		|		return ++i % 2 == 0;
+		//		|	}).forEach(function(w){ /* odd ones */ });
+
+		var res = new dijit.WidgetSet();
+		this.forEach(function(widget){
+			if(filter(widget)){ res.add(widget); }
+		});
+		return res; // dijit.WidgetSet
+	},
+
+	byId: function(/*String*/ id){
+		// summary:
+		//		Find a widget in this list by it's id. 
+		// example:
+		//		Test if an id is in a particular WidgetSet
+		//		| var ws = new dijit.WidgetSet();
+		//		| ws.add(dijit.byId("bar"));
+		//		| var t = ws.byId("bar") // returns a widget
+		//		| var x = ws.byId("foo"); // returns undefined
+		
+		return this._hash[id];	// dijit._Widget
+	},
+
+	byClass: function(/*String*/ cls){
+		// summary:
+		//		Reduce this widgetset to a new WidgetSet of a particular declaredClass
+		// 
+		// example:
+		//		Find all titlePane's in a page:
+		//		|	dijit.registry.byClass("dijit.TitlePane").forEach(function(tp){ tp.close(); });
+		
+		return this.filter(function(widget){ return widget.declaredClass==cls; });	// dijit.WidgetSet
+	}
+	
+});
+
+/*=====
+dijit.registry = {
+	// summary: A list of widgets on a page.
+	// description: Is an instance of `dijit.WidgetSet`
+};
+=====*/
+dijit.registry = new dijit.WidgetSet();
+
+dijit._widgetTypeCtr = {};
+
+dijit.getUniqueId = function(/*String*/widgetType){
+	// summary: Generates a unique id for a given widgetType
+
+	var id;
+	do{
+		id = widgetType + "_" +
+			(widgetType in dijit._widgetTypeCtr ?
+				++dijit._widgetTypeCtr[widgetType] : dijit._widgetTypeCtr[widgetType] = 0);
+	}while(dijit.byId(id));
+	return id; // String
+};
+
+dijit.findWidgets = function(/*DomNode*/ root){
+	// summary:
+	//		Search subtree under root, putting found widgets in outAry.
+	//		Doesn't search for nested widgets (ie, widgets inside other widgets)
+	
+	var outAry = [];
+
+	function getChildrenHelper(root){
+		var list = dojo.isIE ? root.children : root.childNodes, i = 0, node;
+		while(node = list[i++]){
+			if(node.nodeType != 1){ continue; }
+			var widgetId = node.getAttribute("widgetId");
+			if(widgetId){
+				var widget = dijit.byId(widgetId);
+				outAry.push(widget);
+			}else{
+				getChildrenHelper(node);
+			}
+		}
+	}
+
+	getChildrenHelper(root);
+	return outAry;
+};
+
+if(dojo.isIE){
+	// Only run this for IE because we think it's only necessary in that case,
+	// and because it causes problems on FF.  See bug #3531 for details.
+	dojo.addOnWindowUnload(function(){
+		dojo.forEach(dijit.findWidgets(dojo.body()), function(widget){
+			if(widget.destroyRecursive){
+				widget.destroyRecursive();
+			}else if(widget.destroy){
+				widget.destroy();
+			}
+		});
+	});
+}
+
+dijit.byId = function(/*String|Widget*/id){
+	// summary:
+	//		Returns a widget by it's id, or if passed a widget, no-op (like dojo.byId())
+	return (dojo.isString(id)) ? dijit.registry.byId(id) : id; // Widget
+};
+
+dijit.byNode = function(/* DOMNode */ node){
+	// summary:
+	//		Returns the widget corresponding to the given DOMNode
+	return dijit.registry.byId(node.getAttribute("widgetId")); // Widget
+};
+
+dijit.getEnclosingWidget = function(/* DOMNode */ node){
+	// summary:
+	//		Returns the widget whose DOM tree contains the specified DOMNode, or null if
+	//		the node is not contained within the DOM tree of any widget
+	while(node){
+		if(node.getAttribute && node.getAttribute("widgetId")){
+			return dijit.registry.byId(node.getAttribute("widgetId"));
+		}
+		node = node.parentNode;
+	}
+	return null;
+};
+
+// elements that are tab-navigable if they have no tabindex value set
+// (except for "a", which must have an href attribute)
+dijit._tabElements = {
+	area: true,
+	button: true,
+	input: true,
+	object: true,
+	select: true,
+	textarea: true
+};
+
+dijit._isElementShown = function(/*Element*/elem){
+	var style = dojo.style(elem);
+	return (style.visibility != "hidden")
+		&& (style.visibility != "collapsed")
+		&& (style.display != "none")
+		&& (dojo.attr(elem, "type") != "hidden");
+}
+
+dijit.isTabNavigable = function(/*Element*/elem){
+	// summary:
+	//		Tests if an element is tab-navigable
+	if(dojo.hasAttr(elem, "disabled")){ return false; }
+	var hasTabindex = dojo.hasAttr(elem, "tabindex");
+	var tabindex = dojo.attr(elem, "tabindex");
+	if(hasTabindex && tabindex >= 0) {
+		return true; // boolean
+	}
+	var name = elem.nodeName.toLowerCase();
+	if(((name == "a" && dojo.hasAttr(elem, "href"))
+			|| dijit._tabElements[name])
+		&& (!hasTabindex || tabindex >= 0)){
+		return true; // boolean
+	}
+	return false; // boolean
+};
+
+dijit._getTabNavigable = function(/*DOMNode*/root){
+	// summary:
+	//		Finds descendants of the specified root node.
+	//
+	// description:
+	//		Finds the following descendants of the specified root node:
+	//		* the first tab-navigable element in document order
+	//		  without a tabindex or with tabindex="0"
+	//		* the last tab-navigable element in document order
+	//		  without a tabindex or with tabindex="0"
+	//		* the first element in document order with the lowest
+	//		  positive tabindex value
+	//		* the last element in document order with the highest
+	//		  positive tabindex value
+	var first, last, lowest, lowestTabindex, highest, highestTabindex;
+	var walkTree = function(/*DOMNode*/parent){
+		dojo.query("> *", parent).forEach(function(child){
+			var isShown = dijit._isElementShown(child);
+			if(isShown && dijit.isTabNavigable(child)){
+				var tabindex = dojo.attr(child, "tabindex");
+				if(!dojo.hasAttr(child, "tabindex") || tabindex == 0){
+					if(!first){ first = child; }
+					last = child;
+				}else if(tabindex > 0){
+					if(!lowest || tabindex < lowestTabindex){
+						lowestTabindex = tabindex;
+						lowest = child;
+					}
+					if(!highest || tabindex >= highestTabindex){
+						highestTabindex = tabindex;
+						highest = child;
+					}
+				}
+			}
+			if(isShown && child.nodeName.toUpperCase() != 'SELECT'){ walkTree(child) }
+		});
+	};
+	if(dijit._isElementShown(root)){ walkTree(root) }
+	return { first: first, last: last, lowest: lowest, highest: highest };
+}
+dijit.getFirstInTabbingOrder = function(/*String|DOMNode*/root){
+	// summary:
+	//		Finds the descendant of the specified root node
+	//		that is first in the tabbing order
+	var elems = dijit._getTabNavigable(dojo.byId(root));
+	return elems.lowest ? elems.lowest : elems.first; // DomNode
+};
+
+dijit.getLastInTabbingOrder = function(/*String|DOMNode*/root){
+	// summary:
+	//		Finds the descendant of the specified root node
+	//		that is last in the tabbing order
+	var elems = dijit._getTabNavigable(dojo.byId(root));
+	return elems.last ? elems.last : elems.highest; // DomNode
+};
+
+/*=====
+dojo.mixin(dijit, {
+	// defaultDuration: Integer
+	//		The default animation speed (in ms) to use for all Dijit
+	//		transitional animations, unless otherwise specified 
+	//		on a per-instance basis. Defaults to 200, overrided by 
+	//		`djConfig.defaultDuration`
+	defaultDuration: 300
+});
+=====*/
+
+dijit.defaultDuration = dojo.config["defaultDuration"] || 200;
+
+}
+
+if(!dojo._hasResource["dojo.AdapterRegistry"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.AdapterRegistry"] = true;
+dojo.provide("dojo.AdapterRegistry");
+
+dojo.AdapterRegistry = function(/*Boolean?*/ returnWrappers){
+	//	summary:
+	//		A registry to make contextual calling/searching easier.
+	//	description:
+	//		Objects of this class keep list of arrays in the form [name, check,
+	//		wrap, directReturn] that are used to determine what the contextual
+	//		result of a set of checked arguments is. All check/wrap functions
+	//		in this registry should be of the same arity.
+	//	example:
+	//	|	// create a new registry
+	//	|	var reg = new dojo.AdapterRegistry();
+	//	|	reg.register("handleString",
+	//	|		dojo.isString,
+	//	|		function(str){
+	//	|			// do something with the string here
+	//	|		}
+	//	|	);
+	//	|	reg.register("handleArr",
+	//	|		dojo.isArray,
+	//	|		function(arr){
+	//	|			// do something with the array here
+	//	|		}
+	//	|	);
+	//	|
+	//	|	// now we can pass reg.match() *either* an array or a string and
+	//	|	// the value we pass will get handled by the right function
+	//	|	reg.match("someValue"); // will call the first function
+	//	|	reg.match(["someValue"]); // will call the second
+
+	this.pairs = [];
+	this.returnWrappers = returnWrappers || false; // Boolean
+}
+
+dojo.extend(dojo.AdapterRegistry, {
+	register: function(/*String*/ name, /*Function*/ check, /*Function*/ wrap, /*Boolean?*/ directReturn, /*Boolean?*/ override){
+		//	summary: 
+		//		register a check function to determine if the wrap function or
+		//		object gets selected
+		//	name:
+		//		a way to identify this matcher.
+		//	check:
+		//		a function that arguments are passed to from the adapter's
+		//		match() function.  The check function should return true if the
+		//		given arguments are appropriate for the wrap function.
+		//	directReturn:
+		//		If directReturn is true, the value passed in for wrap will be
+		//		returned instead of being called. Alternately, the
+		//		AdapterRegistry can be set globally to "return not call" using
+		//		the returnWrappers property. Either way, this behavior allows
+		//		the registry to act as a "search" function instead of a
+		//		function interception library.
+		//	override:
+		//		If override is given and true, the check function will be given
+		//		highest priority. Otherwise, it will be the lowest priority
+		//		adapter.
+		this.pairs[((override) ? "unshift" : "push")]([name, check, wrap, directReturn]);
+	},
+
+	match: function(/* ... */){
+		// summary:
+		//		Find an adapter for the given arguments. If no suitable adapter
+		//		is found, throws an exception. match() accepts any number of
+		//		arguments, all of which are passed to all matching functions
+		//		from the registered pairs.
+		for(var i = 0; i < this.pairs.length; i++){
+			var pair = this.pairs[i];
+			if(pair[1].apply(this, arguments)){
+				if((pair[3])||(this.returnWrappers)){
+					return pair[2];
+				}else{
+					return pair[2].apply(this, arguments);
+				}
+			}
+		}
+		throw new Error("No match found");
+	},
+
+	unregister: function(name){
+		// summary: Remove a named adapter from the registry
+
+		// FIXME: this is kind of a dumb way to handle this. On a large
+		// registry this will be slow-ish and we can use the name as a lookup
+		// should we choose to trade memory for speed.
+		for(var i = 0; i < this.pairs.length; i++){
+			var pair = this.pairs[i];
+			if(pair[0] == name){
+				this.pairs.splice(i, 1);
+				return true;
+			}
+		}
+		return false;
+	}
+});
+
+}
+
+if(!dojo._hasResource["dijit._base.place"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._base.place"] = true;
+dojo.provide("dijit._base.place");
+
+
+
+// ported from dojo.html.util
+
+dijit.getViewport = function(){
+	// summary:
+	//		Returns the dimensions and scroll position of the viewable area of a browser window
+
+	var scrollRoot = (dojo.doc.compatMode == 'BackCompat')? dojo.body() : dojo.doc.documentElement;
+
+	// get scroll position
+	var scroll = dojo._docScroll(); // scrollRoot.scrollTop/Left should work
+	return { w: scrollRoot.clientWidth, h: scrollRoot.clientHeight, l: scroll.x, t: scroll.y };
+};
+
+/*=====
+dijit.__Position = function(){
+	// x: Integer
+	//		horizontal coordinate in pixels, relative to document body
+	// y: Integer
+	//		vertical coordinate in pixels, relative to document body
+
+	thix.x = x;
+	this.y = y;
+}
+=====*/
+
+
+dijit.placeOnScreen = function(
+	/* DomNode */			node,
+	/* dijit.__Position */	pos,
+	/* String[] */			corners,
+	/* dijit.__Position? */	padding){
+	//	summary:
+	//		Positions one of the node's corners at specified position
+	//		such that node is fully visible in viewport.
+	//	description:
+	//		NOTE: node is assumed to be absolutely or relatively positioned.
+	//	pos:
+	//		Object like {x: 10, y: 20}
+	//	corners:
+	//		Array of Strings representing order to try corners in, like ["TR", "BL"].
+	//		Possible values are:
+	//			* "BL" - bottom left
+	//			* "BR" - bottom right
+	//			* "TL" - top left
+	//			* "TR" - top right
+	//	padding:
+	//		set padding to put some buffer around the element you want to position.
+	//	example:	
+	//		Try to place node's top right corner at (10,20).
+	//		If that makes node go (partially) off screen, then try placing
+	//		bottom left corner at (10,20).
+	//	|	placeOnScreen(node, {x: 10, y: 20}, ["TR", "BL"])
+
+	var choices = dojo.map(corners, function(corner){
+		var c = { corner: corner, pos: {x:pos.x,y:pos.y} };
+		if(padding){
+			c.pos.x += corner.charAt(1) == 'L' ? padding.x : -padding.x;
+			c.pos.y += corner.charAt(0) == 'T' ? padding.y : -padding.y;
+		}
+		return c; 
+	});
+
+	return dijit._place(node, choices);
+}
+
+dijit._place = function(/*DomNode*/ node, /* Array */ choices, /* Function */ layoutNode){
+	// summary:
+	//		Given a list of spots to put node, put it at the first spot where it fits,
+	//		of if it doesn't fit anywhere then the place with the least overflow
+	// choices: Array
+	//		Array of elements like: {corner: 'TL', pos: {x: 10, y: 20} }
+	//		Above example says to put the top-left corner of the node at (10,20)
+	// layoutNode: Function(node, aroundNodeCorner, nodeCorner)
+	//		for things like tooltip, they are displayed differently (and have different dimensions)
+	//		based on their orientation relative to the parent.   This adjusts the popup based on orientation.
+
+	// get {x: 10, y: 10, w: 100, h:100} type obj representing position of
+	// viewport over document
+	var view = dijit.getViewport();
+
+	// This won't work if the node is inside a <div style="position: relative">,
+	// so reattach it to dojo.doc.body.   (Otherwise, the positioning will be wrong
+	// and also it might get cutoff)
+	if(!node.parentNode || String(node.parentNode.tagName).toLowerCase() != "body"){
+		dojo.body().appendChild(node);
+	}
+
+	var best = null;
+	dojo.some(choices, function(choice){
+		var corner = choice.corner;
+		var pos = choice.pos;
+
+		// configure node to be displayed in given position relative to button
+		// (need to do this in order to get an accurate size for the node, because
+		// a tooltips size changes based on position, due to triangle)
+		if(layoutNode){
+			layoutNode(node, choice.aroundCorner, corner);
+		}
+
+		// get node's size
+		var style = node.style;
+		var oldDisplay = style.display;
+		var oldVis = style.visibility;
+		style.visibility = "hidden";
+		style.display = "";
+		var mb = dojo.marginBox(node);
+		style.display = oldDisplay;
+		style.visibility = oldVis;
+
+		// coordinates and size of node with specified corner placed at pos,
+		// and clipped by viewport
+		var startX = (corner.charAt(1) == 'L' ? pos.x : Math.max(view.l, pos.x - mb.w)),
+			startY = (corner.charAt(0) == 'T' ? pos.y : Math.max(view.t, pos.y -  mb.h)),
+			endX = (corner.charAt(1) == 'L' ? Math.min(view.l + view.w, startX + mb.w) : pos.x),
+			endY = (corner.charAt(0) == 'T' ? Math.min(view.t + view.h, startY + mb.h) : pos.y),
+			width = endX - startX,
+			height = endY - startY,
+			overflow = (mb.w - width) + (mb.h - height);
+
+		if(best == null || overflow < best.overflow){
+			best = {
+				corner: corner,
+				aroundCorner: choice.aroundCorner,
+				x: startX,
+				y: startY,
+				w: width,
+				h: height,
+				overflow: overflow
+			};
+		}
+		return !overflow;
+	});
+
+	node.style.left = best.x + "px";
+	node.style.top = best.y + "px";
+	if(best.overflow && layoutNode){
+		layoutNode(node, best.aroundCorner, best.corner);
+	}
+	return best;
+}
+
+dijit.placeOnScreenAroundNode = function(
+	/* DomNode */		node,
+	/* DomNode */		aroundNode,
+	/* Object */		aroundCorners,
+	/* Function? */		layoutNode){
+
+	// summary:
+	//		Position node adjacent or kitty-corner to aroundNode
+	//		such that it's fully visible in viewport.
+	//
+	// description:
+	//		Place node such that corner of node touches a corner of
+	//		aroundNode, and that node is fully visible.
+	//
+	// aroundCorners:
+	//		Ordered list of pairs of corners to try matching up.
+	//		Each pair of corners is represented as a key/value in the hash,
+	//		where the key corresponds to the aroundNode's corner, and
+	//		the value corresponds to the node's corner:
+	//
+	//	|	{ aroundNodeCorner1: nodeCorner1, aroundNodeCorner2: nodeCorner2,  ...}
+	//
+	//		The following strings are used to represent the four corners:
+	//			* "BL" - bottom left
+	//			* "BR" - bottom right
+	//			* "TL" - top left
+	//			* "TR" - top right
+	//
+	// layoutNode: Function(node, aroundNodeCorner, nodeCorner)
+	//		For things like tooltip, they are displayed differently (and have different dimensions)
+	//		based on their orientation relative to the parent.   This adjusts the popup based on orientation.
+	//
+	// example:
+	//	|	dijit.placeOnScreenAroundNode(node, aroundNode, {'BL':'TL', 'TR':'BR'}); 
+	//		This will try to position node such that node's top-left corner is at the same position
+	//		as the bottom left corner of the aroundNode (ie, put node below
+	//		aroundNode, with left edges aligned).  If that fails it will try to put
+	// 		the bottom-right corner of node where the top right corner of aroundNode is
+	//		(ie, put node above aroundNode, with right edges aligned)
+	//
+
+	// get coordinates of aroundNode
+	aroundNode = dojo.byId(aroundNode);
+	var oldDisplay = aroundNode.style.display;
+	aroundNode.style.display="";
+	// #3172: use the slightly tighter border box instead of marginBox
+	var aroundNodeW = aroundNode.offsetWidth; //mb.w; 
+	var aroundNodeH = aroundNode.offsetHeight; //mb.h;
+	var aroundNodePos = dojo.coords(aroundNode, true);
+	aroundNode.style.display=oldDisplay;
+
+	// place the node around the calculated rectangle
+	return dijit._placeOnScreenAroundRect(node, 
+		aroundNodePos.x, aroundNodePos.y, aroundNodeW, aroundNodeH,	// rectangle
+		aroundCorners, layoutNode);
+};
+
+/*=====
+dijit.__Rectangle = function(){
+	// x: Integer
+	//		horizontal offset in pixels, relative to document body
+	// y: Integer
+	//		vertical offset in pixels, relative to document body
+	// width: Integer
+	//		width in pixels
+	// height: Integer
+	//		height in pixels
+
+	thix.x = x;
+	this.y = y;
+	thix.width = width;
+	this.height = height;
+}
+=====*/
+
+
+dijit.placeOnScreenAroundRectangle = function(
+	/* DomNode */			node,
+	/* dijit.__Rectangle */	aroundRect,
+	/* Object */			aroundCorners,
+	/* Function */			layoutNode){
+
+	// summary:
+	//		Like dijit.placeOnScreenAroundNode(), except that the "around"
+	//		parameter is an arbitrary rectangle on the screen (x, y, width, height)
+	//		instead of a dom node.
+
+	return dijit._placeOnScreenAroundRect(node, 
+		aroundRect.x, aroundRect.y, aroundRect.width, aroundRect.height,	// rectangle
+		aroundCorners, layoutNode);
+};
+
+dijit._placeOnScreenAroundRect = function(
+	/* DomNode */		node,
+	/* Number */		x,
+	/* Number */		y,
+	/* Number */		width,
+	/* Number */		height,
+	/* Object */		aroundCorners,
+	/* Function */		layoutNode){
+
+	// summary:
+	//		Like dijit.placeOnScreenAroundNode(), except it accepts coordinates
+	//		of a rectangle to place node adjacent to.
+
+	// TODO: combine with placeOnScreenAroundRectangle()
+
+	// Generate list of possible positions for node
+	var choices = [];
+	for(var nodeCorner in aroundCorners){
+		choices.push( {
+			aroundCorner: nodeCorner,
+			corner: aroundCorners[nodeCorner],
+			pos: {
+				x: x + (nodeCorner.charAt(1) == 'L' ? 0 : width),
+				y: y + (nodeCorner.charAt(0) == 'T' ? 0 : height)
+			}
+		});
+	}
+
+	return dijit._place(node, choices, layoutNode);
+};
+
+dijit.placementRegistry = new dojo.AdapterRegistry();
+dijit.placementRegistry.register("node",
+	function(n, x){
+		return typeof x == "object" &&
+			typeof x.offsetWidth != "undefined" && typeof x.offsetHeight != "undefined";
+	},
+	dijit.placeOnScreenAroundNode);
+dijit.placementRegistry.register("rect",
+	function(n, x){
+		return typeof x == "object" &&
+			"x" in x && "y" in x && "width" in x && "height" in x;
+	},
+	dijit.placeOnScreenAroundRectangle);
+
+dijit.placeOnScreenAroundElement = function(
+	/* DomNode */		node,
+	/* Object */		aroundElement,
+	/* Object */		aroundCorners,
+	/* Function */		layoutNode){
+
+	// summary:
+	//		Like dijit.placeOnScreenAroundNode(), except it accepts an arbitrary object
+	//		for the "around" argument and finds a proper processor to place a node.
+
+	return dijit.placementRegistry.match.apply(dijit.placementRegistry, arguments);
+};
+
+}
+
+if(!dojo._hasResource["dijit._base.window"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._base.window"] = true;
+dojo.provide("dijit._base.window");
+
+// TODO: remove this in 2.0, it's not used anymore, or at least not internally
+
+dijit.getDocumentWindow = function(doc){
+	// summary:
+	// 		Get window object associated with document doc
+
+	// In some IE versions (at least 6.0), document.parentWindow does not return a
+	// reference to the real window object (maybe a copy), so we must fix it as well
+	// We use IE specific execScript to attach the real window reference to
+	// document._parentWindow for later use
+	if(dojo.isIE && window !== document.parentWindow && !doc._parentWindow){
+		/*
+		In IE 6, only the variable "window" can be used to connect events (others
+		may be only copies).
+		*/
+		doc.parentWindow.execScript("document._parentWindow = window;", "Javascript");
+		//to prevent memory leak, unset it after use
+		//another possibility is to add an onUnload handler which seems overkill to me (liucougar)
+		var win = doc._parentWindow;
+		doc._parentWindow = null;
+		return win;	//	Window
+	}
+
+	return doc._parentWindow || doc.parentWindow || doc.defaultView;	//	Window
+}
+
+}
+
+if(!dojo._hasResource["dijit._base.popup"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._base.popup"] = true;
+dojo.provide("dijit._base.popup");
+
+
+
+
+
+dijit.popup = new function(){
+	// summary:
+	//		This class is used to show/hide widgets as popups.
+
+	var stack = [],
+		beginZIndex=1000,
+		idGen = 1;
+
+	this.prepare = function(/*DomNode*/ node){
+		// summary:
+		//		Prepares a node to be used as a popup
+		//
+		// description:
+		//		Attaches node to dojo.doc.body, and
+		//		positions it off screen, but not display:none, so that
+		//		the widget doesn't appear in the page flow and/or cause a blank
+		//		area at the bottom of the viewport (making scrollbar longer), but
+		//		initialization of contained widgets works correctly
+
+		var s = node.style;
+		s.visibility = "hidden";	// so TAB key doesn't navigate to hidden popup
+		s.position = "absolute";
+		s.top = "-9999px";
+		if(s.display == "none"){
+			s.display="";
+		}
+		dojo.body().appendChild(node);
+	};
+
+/*=====
+dijit.popup.__OpenArgs = function(){
+	// popup: Widget
+	//		widget to display
+	// parent: Widget
+	//		the button etc. that is displaying this popup
+	// around: DomNode
+	//		DOM node (typically a button); place popup relative to this node.  (Specify this *or* "x" and "y" parameters.)
+	// x: Integer
+	//		Absolute horizontal position (in pixels) to place node at.  (Specify this *or* "around" parameter.)
+	// y: Integer
+	//		Absolute vertical position (in pixels) to place node at.  (Specity this *or* "around" parameter.)
+	// orient: Object || String
+	//		When the around parameter is specified, orient should be an 
+	//		ordered list of tuples of the form (around-node-corner, popup-node-corner).
+	//		dijit.popup.open() tries to position the popup according to each tuple in the list, in order,
+	//		until the popup appears fully within the viewport.
+	//
+	//		The default value is {BL:'TL', TL:'BL'}, which represents a list of two tuples:
+	//			1. (BL, TL)
+	//			2. (TL, BL)
+	//		where BL means "bottom left" and "TL" means "top left".
+	//		So by default, it first tries putting the popup below the around node, left-aligning them,
+	//		and then tries to put it above the around node, still left-aligning them.   Note that the
+	//		default is horizontally reversed when in RTL mode.
+	//
+	//		When an (x,y) position is specified rather than an around node, orient is either
+	//		"R" or "L".  R (for right) means that it tries to put the popup to the right of the mouse,
+	//		specifically positioning the popup's top-right corner at the mouse position, and if that doesn't
+	//		fit in the viewport, then it tries, in order, the bottom-right corner, the top left corner,
+	//		and the top-right corner.
+	// onCancel: Function
+	//		callback when user has canceled the popup by
+	//			1. hitting ESC or
+	//			2. by using the popup widget's proprietary cancel mechanism (like a cancel button in a dialog);
+	//			   i.e. whenever popupWidget.onCancel() is called, args.onCancel is called
+	// onClose: Function
+	//		callback whenever this popup is closed
+	// onExecute: Function
+	//		callback when user "executed" on the popup/sub-popup by selecting a menu choice, etc. (top menu only)
+	// padding: dijit.__Position
+	//		adding a buffer around the opening position. This is only useful when around is not set.
+	this.popup = popup;
+	this.parent = parent;
+	this.around = around;
+	this.x = x;
+	this.y = y;
+	this.orient = orient;
+	this.onCancel = onCancel;
+	this.onClose = onClose;
+	this.onExecute = onExecute;
+	this.padding = padding;
+}
+=====*/
+	this.open = function(/*dijit.popup.__OpenArgs*/ args){
+		// summary:
+		//		Popup the widget at the specified position
+		//
+		// example:
+		//		opening at the mouse position
+		//		|		dijit.popup.open({popup: menuWidget, x: evt.pageX, y: evt.pageY});
+		//
+		// example:
+		//		opening the widget as a dropdown
+		//		|		dijit.popup.open({parent: this, popup: menuWidget, around: this.domNode, onClose: function(){...}  });
+		//
+		//		Note that whatever widget called dijit.popup.open() should also listen to its own _onBlur callback
+		//		(fired from _base/focus.js) to know that focus has moved somewhere else and thus the popup should be closed.
+
+		var widget = args.popup,
+			orient = args.orient || {'BL':'TL', 'TL':'BL'},
+			around = args.around,
+			id = (args.around && args.around.id) ? (args.around.id+"_dropdown") : ("popup_"+idGen++);
+
+		// make wrapper div to hold widget and possibly hold iframe behind it.
+		// we can't attach the iframe as a child of the widget.domNode because
+		// widget.domNode might be a <table>, <ul>, etc.
+		var wrapper = dojo.create("div",{
+			id: id, 
+			"class":"dijitPopup",
+			style:{
+				zIndex: beginZIndex + stack.length,
+				visibility:"hidden"
+			}
+		}, dojo.body());
+		dijit.setWaiRole(wrapper, "presentation");
+		
+		// prevent transient scrollbar causing misalign (#5776)
+		wrapper.style.left = wrapper.style.top = "0px";		
+
+		if(args.parent){
+			wrapper.dijitPopupParent=args.parent.id;
+		}
+
+		var s = widget.domNode.style;
+		s.display = "";
+		s.visibility = "";
+		s.position = "";
+		s.top = "0px";
+		wrapper.appendChild(widget.domNode);
+
+		var iframe = new dijit.BackgroundIframe(wrapper);
+
+		// position the wrapper node
+		var best = around ?
+			dijit.placeOnScreenAroundElement(wrapper, around, orient, widget.orient ? dojo.hitch(widget, "orient") : null) :
+			dijit.placeOnScreen(wrapper, args, orient == 'R' ? ['TR','BR','TL','BL'] : ['TL','BL','TR','BR'], args.padding);
+
+		wrapper.style.visibility = "visible";
+		// TODO: use effects to fade in wrapper
+
+		var handlers = [];
+
+		// Compute the closest ancestor popup that's *not* a child of another popup.
+		// Ex: For a TooltipDialog with a button that spawns a tree of menus, find the popup of the button.
+		var getTopPopup = function(){
+			for(var pi=stack.length-1; pi > 0 && stack[pi].parent === stack[pi-1].widget; pi--){
+				/* do nothing, just trying to get right value for pi */
+			}
+			return stack[pi];
+		}
+
+		// provide default escape and tab key handling
+		// (this will work for any widget, not just menu)
+		handlers.push(dojo.connect(wrapper, "onkeypress", this, function(evt){
+			if(evt.charOrCode == dojo.keys.ESCAPE && args.onCancel){
+				dojo.stopEvent(evt);
+				args.onCancel();
+			}else if(evt.charOrCode === dojo.keys.TAB){
+				dojo.stopEvent(evt);
+				var topPopup = getTopPopup();
+				if(topPopup && topPopup.onCancel){
+					topPopup.onCancel();
+				}
+			}
+		}));
+
+		// watch for cancel/execute events on the popup and notify the caller
+		// (for a menu, "execute" means clicking an item)
+		if(widget.onCancel){
+			handlers.push(dojo.connect(widget, "onCancel", null, args.onCancel));
+		}
+
+		handlers.push(dojo.connect(widget, widget.onExecute ? "onExecute" : "onChange", null, function(){
+			var topPopup = getTopPopup();
+			if(topPopup && topPopup.onExecute){
+				topPopup.onExecute();
+			}
+		}));
+
+		stack.push({
+			wrapper: wrapper,
+			iframe: iframe,
+			widget: widget,
+			parent: args.parent,
+			onExecute: args.onExecute,
+			onCancel: args.onCancel,
+ 			onClose: args.onClose,
+			handlers: handlers
+		});
+
+		if(widget.onOpen){
+			widget.onOpen(best);
+		}
+
+		return best;
+	};
+
+	this.close = function(/*Widget*/ popup){
+		// summary:
+		//		Close specified popup and any popups that it parented
+		while(dojo.some(stack, function(elem){return elem.widget == popup;})){
+			var top = stack.pop(),
+				wrapper = top.wrapper,
+				iframe = top.iframe,
+				widget = top.widget,
+				onClose = top.onClose;
+	
+			if(widget.onClose){
+				widget.onClose();
+			}
+			dojo.forEach(top.handlers, dojo.disconnect);
+	
+			// #2685: check if the widget still has a domNode so ContentPane can change its URL without getting an error
+			if(!widget||!widget.domNode){ return; }
+			
+			this.prepare(widget.domNode);
+
+			iframe.destroy();
+			dojo.destroy(wrapper);
+	
+			if(onClose){
+				onClose();
+			}
+		}
+	};
+}();
+
+dijit._frames = new function(){
+	// summary: cache of iframes
+	var queue = [];
+
+	this.pop = function(){
+		var iframe;
+		if(queue.length){
+			iframe = queue.pop();
+			iframe.style.display="";
+		}else{
+			if(dojo.isIE){
+				var burl = dojo.config["dojoBlankHtmlUrl"] || (dojo.moduleUrl("dojo", "resources/blank.html")+"") || "javascript:\"\"";
+				var html="<iframe src='" + burl + "'"
+					+ " style='position: absolute; left: 0px; top: 0px;"
+					+ "z-index: -1; filter:Alpha(Opacity=\"0\");'>";
+				iframe = dojo.doc.createElement(html);
+			}else{
+			 	iframe = dojo.create("iframe");
+				iframe.src = 'javascript:""';
+				iframe.className = "dijitBackgroundIframe";
+			}
+			iframe.tabIndex = -1; // Magic to prevent iframe from getting focus on tab keypress - as style didnt work.
+			dojo.body().appendChild(iframe);
+		}
+		return iframe;
+	};
+
+	this.push = function(iframe){
+		iframe.style.display="none";
+		if(dojo.isIE){
+			iframe.style.removeExpression("width");
+			iframe.style.removeExpression("height");
+		}
+		queue.push(iframe);
+	}
+}();
+
+
+dijit.BackgroundIframe = function(/* DomNode */node){
+	// summary:
+	//		For IE z-index schenanigans. id attribute is required.
+	//
+	// description:
+	//		new dijit.BackgroundIframe(node)
+	//			Makes a background iframe as a child of node, that fills
+	//			area (and position) of node
+
+	if(!node.id){ throw new Error("no id"); }
+	if(dojo.isIE < 7 || (dojo.isFF < 3 && dojo.hasClass(dojo.body(), "dijit_a11y"))){
+		var iframe = dijit._frames.pop();
+		node.appendChild(iframe);
+		if(dojo.isIE){
+			iframe.style.setExpression("width", dojo._scopeName + ".doc.getElementById('" + node.id + "').offsetWidth");
+			iframe.style.setExpression("height", dojo._scopeName + ".doc.getElementById('" + node.id + "').offsetHeight");
+		}
+		this.iframe = iframe;
+	}
+};
+
+dojo.extend(dijit.BackgroundIframe, {
+	destroy: function(){
+		//	summary: destroy the iframe
+		if(this.iframe){
+			dijit._frames.push(this.iframe);
+			delete this.iframe;
+		}
+	}
+});
+
+}
+
+if(!dojo._hasResource["dijit._base.scroll"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._base.scroll"] = true;
+dojo.provide("dijit._base.scroll");
+
+dijit.scrollIntoView = function(/* DomNode */node){
+	// summary:
+	//		Scroll the passed node into view, if it is not.
+
+	// don't rely on that node.scrollIntoView works just because the function is there
+	// it doesnt work in Konqueror or Opera even though the function is there and probably
+	//	not safari either
+	// native scrollIntoView() causes FF3's whole window to scroll if there is no scroll bar 
+	//	on the immediate parent
+	// dont like browser sniffs implementations but sometimes you have to use it
+	// It's not enough just to scroll the menu node into view if
+	// node.scrollIntoView hides part of the parent's scrollbar,
+	// so just manage the parent scrollbar ourselves
+
+	//var testdir="H"; //debug
+	try{ // catch unexpected/unrecreatable errors (#7808) since we can recover using a semi-acceptable native method
+	node = dojo.byId(node);
+	var doc = dojo.doc;
+	var body = dojo.body();
+	var html = body.parentNode;
+	// if FF2 (which is perfect) or an untested browser, then use the native method
+
+	if((!(dojo.isFF >= 3 || dojo.isIE || dojo.isWebKit) || node == body || node == html) && (typeof node.scrollIntoView == "function")){ // FF2 is perfect, too bad FF3 is not
+		node.scrollIntoView(false); // short-circuit to native if possible
+		return;
+	}
+	var ltr = dojo._isBodyLtr();
+	var isIE8strict = dojo.isIE >= 8 && !compatMode;
+	var rtl = !ltr && !isIE8strict; // IE8 flips scrolling so pretend it's ltr
+	// body and html elements are all messed up due to browser bugs and inconsistencies related to doctype
+	// normalize the values before proceeding (FF2 is not listed since its native behavior is perfect)
+	// for computation simplification, client and offset width and height are the same for body and html
+	// strict:       html:       |      body:       | compatMode:
+	//           width   height  |  width   height  |------------
+	//    ie*:  clientW  clientH | scrollW  clientH | CSS1Compat
+	//    ff3:  clientW  clientH |HscrollW  clientH | CSS1Compat
+	//    sf3:  clientW  clientH | clientW HclientH | CSS1Compat
+	//    op9:  clientW  clientH |HscrollW  clientH | CSS1Compat
+	// ---------------------------------------------|-----------
+	//   none:        html:      |      body:       |
+	//           width    height |  width   height  |
+	//    ie*: BclientW BclientH | clientW  clientH | BackCompat
+	//    ff3: BclientW BclientH | clientW  clientH | BackCompat
+	//    sf3:  clientW  clientH | clientW HclientH | CSS1Compat
+	//    op9: BclientW BclientH | clientW  clientH | BackCompat
+	// ---------------------------------------------|-----------
+	//  loose:        html:      |      body:       |
+	//           width    height |  width   height  |
+	//    ie*:  clientW  clientH | scrollW  clientH | CSS1Compat
+	//    ff3: BclientW BclientH | clientW  clientH | BackCompat
+	//    sf3:  clientW  clientH | clientW HclientH | CSS1Compat
+	//    op9:  clientW  clientH |HscrollW  clientH | CSS1Compat
+	var scrollRoot = body;
+	var compatMode = doc.compatMode == 'BackCompat';
+	if(compatMode){ // BODY is scrollable, HTML has same client size
+		// body client values already OK
+		html._offsetWidth = html._clientWidth = body._offsetWidth = body.clientWidth;
+		html._offsetHeight = html._clientHeight = body._offsetHeight = body.clientHeight;
+	}else{
+		if(dojo.isWebKit){
+			body._offsetWidth = body._clientWidth  = html.clientWidth;
+			body._offsetHeight = body._clientHeight = html.clientHeight;
+		}else{
+			scrollRoot = html;
+		}
+		html._offsetHeight = html.clientHeight;
+		html._offsetWidth  = html.clientWidth;
+	}
+
+	function isFixedPosition(element){
+		var ie = dojo.isIE;
+		return ((ie <= 6 || (ie >= 7 && compatMode))? false : (dojo.style(element, 'position').toLowerCase() == "fixed"));
+	}
+
+	function addPseudoAttrs(element){
+		var parent = element.parentNode;
+		var offsetParent = element.offsetParent;
+		if(offsetParent == null || isFixedPosition(element)){ // position:fixed has no real offsetParent
+			offsetParent = html; // prevents exeptions
+			parent = (element == body)? html : null;
+		}
+		// all the V/H object members below are to reuse code for both directions
+		element._offsetParent = offsetParent;
+		element._parent = parent;
+		//
+		//
+		var bp = dojo._getBorderExtents(element);
+		element._borderStart = { H:(isIE8strict && !ltr)? (bp.w-bp.l):bp.l, V:bp.t };
+		element._borderSize = { H:bp.w, V:bp.h };
+		element._scrolledAmount = { H:element.scrollLeft, V:element.scrollTop };
+		element._offsetSize = { H: element._offsetWidth||element.offsetWidth, V: element._offsetHeight||element.offsetHeight };
+		//
+		// IE8 flips everything in rtl mode except offsetLeft and borderLeft - so manually change offsetLeft to offsetRight here 
+		element._offsetStart = { H:(isIE8strict && !ltr)? offsetParent.clientWidth-element.offsetLeft-element._offsetSize.H:element.offsetLeft, V:element.offsetTop };
+		//
+		element._clientSize = { H:element._clientWidth||element.clientWidth, V:element._clientHeight||element.clientHeight };
+		if(element != body && element != html && element != node){
+			for(var dir in element._offsetSize){ // for both x and y directions
+				var scrollBarSize = element._offsetSize[dir] - element._clientSize[dir] - element._borderSize[dir];
+				//if(dir==testdir)
+				var hasScrollBar = element._clientSize[dir] > 0 && scrollBarSize > 0; // can't check for a specific scrollbar size since it changes dramatically as you zoom
+				//if(dir==testdir)
+				if(hasScrollBar){
+					element._offsetSize[dir] -= scrollBarSize;
+					if(dojo.isIE && rtl && dir=="H"){ element._offsetStart[dir] += scrollBarSize; }
+				}
+			}
+		}
+	}
+
+	var element = node;
+	while(element != null){
+		if(isFixedPosition(element)){ node.scrollIntoView(false); return; } //TODO: handle without native call
+		addPseudoAttrs(element);
+		element = element._parent;
+	}
+	if(dojo.isIE && node._parent){ // if no parent, then offsetParent._borderStart may not tbe set
+		var offsetParent = node._offsetParent;
+		//
+		node._offsetStart.H += offsetParent._borderStart.H;
+		node._offsetStart.V += offsetParent._borderStart.V;
+	}
+	if(dojo.isIE >= 7 && scrollRoot == html && rtl && body._offsetStart && body._offsetStart.H == 0){ // IE7 bug
+		var scroll = html.scrollWidth - html._offsetSize.H;
+		if(scroll > 0){
+			//
+			body._offsetStart.H = -scroll;
+		}
+	}
+	if(dojo.isIE <= 6 && !compatMode){
+		html._offsetSize.H += html._borderSize.H;
+		html._offsetSize.V += html._borderSize.V;
+	}
+	// eliminate offsetLeft/Top oddities by tweaking scroll for ease of computation
+	if(rtl && body._offsetStart && scrollRoot == html && html._scrolledAmount){
+		var ofs = body._offsetStart.H;
+		if(ofs < 0){
+			html._scrolledAmount.H += ofs;
+			body._offsetStart.H = 0;
+		}
+	}
+	element = node;
+	while(element){
+		var parent = element._parent;
+		if(!parent){ break; }
+			//
+			if(parent.tagName == "TD"){
+				var table = parent._parent._parent._parent; // point to TABLE
+				if(parent != element._offsetParent && parent._offsetParent != element._offsetParent){
+					parent = table; // child of TD has the same offsetParent as TABLE, so skip TD, TR, and TBODY (ie. verticalslider)
+				}
+			}
+			// check if this node and its parent share the same offsetParent
+			var relative = element._offsetParent == parent;
+			//
+			for(var dir in element._offsetStart){ // for both x and y directions
+				var otherDir = dir=="H"? "V" : "H";
+				if(rtl && dir=="H" && (parent != html) && (parent != body) && (dojo.isIE || dojo.isWebKit) && parent._clientSize.H > 0 && parent.scrollWidth > parent._clientSize.H){ // scroll starts on the right
+					var delta = parent.scrollWidth - parent._clientSize.H;
+					//
+					if(delta > 0){
+						parent._scrolledAmount.H -= delta;
+					} // match FF3 which has cool negative scrollLeft values
+				}
+				if(parent._offsetParent.tagName == "TABLE"){ // make it consistent
+					if(dojo.isIE){ // make it consistent with Safari and FF3 and exclude the starting TABLE border of TABLE children
+						parent._offsetStart[dir] -= parent._offsetParent._borderStart[dir];
+						parent._borderStart[dir] = parent._borderSize[dir] = 0;
+					}
+					else{
+						parent._offsetStart[dir] += parent._offsetParent._borderStart[dir];
+					}
+				}
+				//if(dir==testdir)
+				if(dojo.isIE){
+					//if(dir==testdir)
+					parent._offsetStart[dir] += parent._offsetParent._borderStart[dir];
+				}
+				//if(dir==testdir)
+				// underflow = visible gap between parent and this node taking scrolling into account
+				// if negative, part of the node is obscured by the parent's beginning and should be scrolled to become visible
+				var underflow = element._offsetStart[dir] - parent._scrolledAmount[dir] - (relative? 0 : parent._offsetStart[dir]) - parent._borderStart[dir];
+				// if overflow is positive, number of pixels obscured by the parent's end
+				var overflow = underflow + element._offsetSize[dir] - parent._offsetSize[dir] + parent._borderSize[dir];
+				//if(dir==testdir)
+				var scrollAttr = (dir=="H")? "scrollLeft" : "scrollTop";
+				// see if we should scroll forward or backward
+				var reverse = dir=="H" && rtl; // flip everything
+				var underflowScroll = reverse? -overflow : underflow;
+				var overflowScroll = reverse? -underflow : overflow;
+				// don't scroll if the over/underflow signs are opposite since that means that
+				// the node extends beyond parent's boundary in both/neither directions
+				var scrollAmount = (underflowScroll*overflowScroll <= 0)? 0 : Math[(underflowScroll < 0)? "max" : "min"](underflowScroll, overflowScroll);
+				//if(dir==testdir)
+				if(scrollAmount != 0){
+					var oldScroll = parent[scrollAttr];
+					parent[scrollAttr] += (reverse)? -scrollAmount : scrollAmount; // actually perform the scroll
+					var scrolledAmount = parent[scrollAttr] - oldScroll; // in case the scroll failed
+					//if(dir==testdir)
+				}
+				if(relative){
+					element._offsetStart[dir] += parent._offsetStart[dir];
+				}
+				element._offsetStart[dir] -= parent[scrollAttr];
+			}
+			element._parent = parent._parent;
+			element._offsetParent = parent._offsetParent;
+	}
+	parent = node;
+	var next;
+	while(parent && parent.removeAttribute){
+		next = parent.parentNode;
+		parent.removeAttribute('_offsetParent');
+		parent.removeAttribute('_parent');
+		parent = next;
+	}
+	}catch(error){
+		console.error('scrollIntoView: ' + error);
+		node.scrollIntoView(false);
+	}
+};
+
+}
+
+if(!dojo._hasResource["dijit._base.sniff"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._base.sniff"] = true;
+// summary:
+//		Applies pre-set CSS classes to the top-level HTML node, based on:
+// 			- browser (ex: dj_ie)
+//			- browser version (ex: dj_ie6)
+//			- box model (ex: dj_contentBox)
+//			- text direction (ex: dijitRtl)
+//
+//		In addition, browser, browser version, and box model are
+//		combined with an RTL flag when browser text is RTL.  ex: dj_ie-rtl.
+//
+//		Simply doing a require on this module will
+//		establish this CSS.  Modified version of Morris' CSS hack.
+
+dojo.provide("dijit._base.sniff");
+
+(function(){
+	
+	var d = dojo,
+		html = d.doc.documentElement,
+		ie = d.isIE,
+		opera = d.isOpera,
+		maj = Math.floor,
+		ff = d.isFF,
+		boxModel = d.boxModel.replace(/-/,''),
+		classes = {
+			dj_ie: ie,
+//			dj_ie55: ie == 5.5,
+			dj_ie6: maj(ie) == 6,
+			dj_ie7: maj(ie) == 7,
+			dj_iequirks: ie && d.isQuirks,
+			// NOTE: Opera not supported by dijit
+			dj_opera: opera,
+			dj_opera8: maj(opera) == 8,
+			dj_opera9: maj(opera) == 9,
+			dj_khtml: d.isKhtml,
+			dj_webkit: d.isWebKit,
+			dj_safari: d.isSafari,
+			dj_gecko: d.isMozilla,
+			dj_ff2: maj(ff) == 2,
+			dj_ff3: maj(ff) == 3
+		}; // no dojo unsupported browsers
+		
+	classes["dj_" + boxModel] = true;
+	
+	// apply browser, browser version, and box model class names
+	for(var p in classes){
+		if(classes[p]){
+			if(html.className){
+				html.className += " " + p;
+			}else{
+				html.className = p;
+			}
+		}
+	}
+
+	// If RTL mode then add dijitRtl flag plus repeat existing classes
+	// with -rtl extension
+	// (unshift is to make this code run after <body> node is loaded but before parser runs)
+	dojo._loaders.unshift(function(){
+		if(!dojo._isBodyLtr()){
+			html.className += " dijitRtl";
+			for(var p in classes){
+				if(classes[p]){
+					html.className += " " + p + "-rtl";
+				}
+			}
+		}
+	});
+	
+})();
+
+}
+
+if(!dojo._hasResource["dijit._base.typematic"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._base.typematic"] = true;
+dojo.provide("dijit._base.typematic");
+
+dijit.typematic = {
+	// summary:
+	//		These functions are used to repetitively call a user specified callback
+	//		method when a specific key or mouse click over a specific DOM node is
+	//		held down for a specific amount of time.
+	//		Only 1 such event is allowed to occur on the browser page at 1 time.
+
+	_fireEventAndReload: function(){
+		this._timer = null;
+		this._callback(++this._count, this._node, this._evt);
+		this._currentTimeout = (this._currentTimeout < 0) ? this._initialDelay : ((this._subsequentDelay > 1) ? this._subsequentDelay : Math.round(this._currentTimeout * this._subsequentDelay));
+		this._timer = setTimeout(dojo.hitch(this, "_fireEventAndReload"), this._currentTimeout);
+	},
+
+	trigger: function(/*Event*/ evt, /* Object */ _this, /*DOMNode*/ node, /* Function */ callback, /* Object */ obj, /* Number */ subsequentDelay, /* Number */ initialDelay){
+		// summary:
+		//	    Start a timed, repeating callback sequence.
+		//	    If already started, the function call is ignored.
+		//	    This method is not normally called by the user but can be
+		//	    when the normal listener code is insufficient.
+		// evt:
+		//		key or mouse event object to pass to the user callback
+		// _this:
+		//		pointer to the user's widget space.
+		// node:
+		//		the DOM node object to pass the the callback function
+		// callback:
+		//		function to call until the sequence is stopped called with 3 parameters:
+		// count:
+		//		integer representing number of repeated calls (0..n) with -1 indicating the iteration has stopped
+		// node:
+		//		the DOM node object passed in
+		// evt:
+		//		key or mouse event object
+		// obj:
+		//		user space object used to uniquely identify each typematic sequence
+		// subsequentDelay:
+		//		if > 1, the number of milliseconds until the 3->n events occur
+		//		or else the fractional time multiplier for the next event's delay, default=0.9
+		// initialDelay:
+		//		the number of milliseconds until the 2nd event occurs, default=500ms
+		if(obj != this._obj){
+			this.stop();
+			this._initialDelay = initialDelay || 500;
+			this._subsequentDelay = subsequentDelay || 0.90;
+			this._obj = obj;
+			this._evt = evt;
+			this._node = node;
+			this._currentTimeout = -1;
+			this._count = -1;
+			this._callback = dojo.hitch(_this, callback);
+			this._fireEventAndReload();
+		}
+	},
+
+	stop: function(){
+		// summary:
+		//	  Stop an ongoing timed, repeating callback sequence.
+		if(this._timer){
+			clearTimeout(this._timer);
+			this._timer = null;
+		}
+		if(this._obj){
+			this._callback(-1, this._node, this._evt);
+			this._obj = null;
+		}
+	},
+
+	addKeyListener: function(/*DOMNode*/ node, /*Object*/ keyObject, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay){
+		// summary:
+		//		Start listening for a specific typematic key.
+		//		See also the trigger method for other parameters.
+		// keyObject:
+		//		an object defining the key to listen for.
+		// charOrCode:
+		//		the printable character (string) or keyCode (number) to listen for.
+		// keyCode:
+		//		(deprecated - use charOrCode) the keyCode (number) to listen for (implies charCode = 0).
+		// charCode:
+		//		(deprecated - use charOrCode) the charCode (number) to listen for.
+		// ctrlKey:
+		//		desired ctrl key state to initiate the calback sequence:
+		//			- pressed (true)
+		//			- released (false)
+		//			- either (unspecified)
+		// altKey:
+		//		same as ctrlKey but for the alt key
+		// shiftKey:
+		//		same as ctrlKey but for the shift key
+		// returns:
+		//		an array of dojo.connect handles
+		if(keyObject.keyCode){
+			keyObject.charOrCode = keyObject.keyCode;
+			dojo.deprecated("keyCode attribute parameter for dijit.typematic.addKeyListener is deprecated. Use charOrCode instead.", "", "2.0");
+		}else if(keyObject.charCode){
+			keyObject.charOrCode = String.fromCharCode(keyObject.charCode);
+			dojo.deprecated("charCode attribute parameter for dijit.typematic.addKeyListener is deprecated. Use charOrCode instead.", "", "2.0");
+		}
+		return [
+			dojo.connect(node, "onkeypress", this, function(evt){
+				if(evt.charOrCode == keyObject.charOrCode &&
+				(keyObject.ctrlKey === undefined || keyObject.ctrlKey == evt.ctrlKey) &&
+				(keyObject.altKey === undefined || keyObject.altKey == evt.ctrlKey) &&
+				(keyObject.shiftKey === undefined || keyObject.shiftKey == evt.ctrlKey)){
+					dojo.stopEvent(evt);
+					dijit.typematic.trigger(keyObject, _this, node, callback, keyObject, subsequentDelay, initialDelay);
+				}else if(dijit.typematic._obj == keyObject){
+					dijit.typematic.stop();
+				}
+			}),
+			dojo.connect(node, "onkeyup", this, function(evt){
+				if(dijit.typematic._obj == keyObject){
+					dijit.typematic.stop();
+				}
+			})
+		];
+	},
+
+	addMouseListener: function(/*DOMNode*/ node, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay){
+		// summary:
+		//		Start listening for a typematic mouse click.
+		//		See the trigger method for other parameters.
+		// returns:
+		//		an array of dojo.connect handles
+		var dc = dojo.connect;
+		return [
+			dc(node, "mousedown", this, function(evt){
+				dojo.stopEvent(evt);
+				dijit.typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay);
+			}),
+			dc(node, "mouseup", this, function(evt){
+				dojo.stopEvent(evt);
+				dijit.typematic.stop();
+			}),
+			dc(node, "mouseout", this, function(evt){
+				dojo.stopEvent(evt);
+				dijit.typematic.stop();
+			}),
+			dc(node, "mousemove", this, function(evt){
+				dojo.stopEvent(evt);
+			}),
+			dc(node, "dblclick", this, function(evt){
+				dojo.stopEvent(evt);
+				if(dojo.isIE){
+					dijit.typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay);
+					setTimeout(dojo.hitch(this, dijit.typematic.stop), 50);
+				}
+			})
+		];
+	},
+
+	addListener: function(/*Node*/ mouseNode, /*Node*/ keyNode, /*Object*/ keyObject, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay){
+		// summary:
+		//		Start listening for a specific typematic key and mouseclick.
+		//		This is a thin wrapper to addKeyListener and addMouseListener.
+		//		See the addMouseListener and addKeyListener methods for other parameters.
+		// mouseNode:
+		//		the DOM node object to listen on for mouse events.
+		// keyNode:
+		//		the DOM node object to listen on for key events.
+		// returns:
+		//		an array of dojo.connect handles
+		return this.addKeyListener(keyNode, keyObject, _this, callback, subsequentDelay, initialDelay).concat(
+			this.addMouseListener(mouseNode, _this, callback, subsequentDelay, initialDelay));
+	}
+};
+
+}
+
+if(!dojo._hasResource["dijit._base.wai"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._base.wai"] = true;
+dojo.provide("dijit._base.wai");
+
+dijit.wai = {
+	onload: function(){
+		// summary:
+		//		Detects if we are in high-contrast mode or not
+
+		// This must be a named function and not an anonymous
+		// function, so that the widget parsing code can make sure it
+		// registers its onload function after this function.
+		// DO NOT USE "this" within this function.
+
+		// create div for testing if high contrast mode is on or images are turned off
+		var div = dojo.create("div",{
+			id: "a11yTestNode",
+			style:{
+				cssText:'border: 1px solid;'
+					+ 'border-color:red green;'
+					+ 'position: absolute;'
+					+ 'height: 5px;'
+					+ 'top: -999px;'
+					+ 'background-image: url("' + (dojo.config.blankGif || dojo.moduleUrl("dojo", "resources/blank.gif")) + '");'
+			}
+		}, dojo.body());
+
+		// test it
+		var cs = dojo.getComputedStyle(div);
+		if(cs){
+			var bkImg = cs.backgroundImage;
+			var needsA11y = (cs.borderTopColor==cs.borderRightColor) || (bkImg != null && (bkImg == "none" || bkImg == "url(invalid-url:)" ));
+			dojo[needsA11y ? "addClass" : "removeClass"](dojo.body(), "dijit_a11y");
+			if(dojo.isIE){
+				div.outerHTML = "";		// prevent mixed-content warning, see http://support.microsoft.com/kb/925014
+			}else{
+				dojo.body().removeChild(div);
+			}
+		}
+	}
+};
+
+// Test if computer is in high contrast mode.
+// Make sure the a11y test runs first, before widgets are instantiated.
+if(dojo.isIE || dojo.isMoz){	// NOTE: checking in Safari messes things up
+	dojo._loaders.unshift(dijit.wai.onload);
+}
+
+dojo.mixin(dijit,
+{
+	_XhtmlRoles: /banner|contentinfo|definition|main|navigation|search|note|secondary|seealso/,
+
+	hasWaiRole: function(/*Element*/ elem, /*String*/ role){
+		// summary:
+		//		Determines if an element has a particular non-XHTML role.
+		// returns:
+		//		True if elem has the specific non-XHTML role attribute and false if not.
+		// 		For backwards compatibility if role parameter not provided, 
+		// 		returns true if has non XHTML role 
+		var waiRole = this.getWaiRole(elem);		
+		return role ? (waiRole.indexOf(role) > -1) : (waiRole.length > 0);
+	},
+
+	getWaiRole: function(/*Element*/ elem){
+		// summary:
+		//		Gets the non-XHTML role for an element (which should be a wai role).
+		// returns:
+		//		The non-XHTML role of elem or an empty string if elem
+		//		does not have a role.
+		 return dojo.trim((dojo.attr(elem, "role") || "").replace(this._XhtmlRoles,"").replace("wairole:",""));
+	},
+
+	setWaiRole: function(/*Element*/ elem, /*String*/ role){
+		// summary:
+		//		Sets the role on an element.
+		// description:
+		//		In other than FF2 replace existing role attribute with new role.
+		//		FF3 supports XHTML and ARIA roles so    
+		//		if elem already has an XHTML role, append this role to XHTML role 
+		//		and remove other ARIA roles.
+		//		On Firefox 2 and below, "wairole:" is
+		//		prepended to the provided role value.
+
+		var curRole = dojo.attr(elem, "role") || "";
+		if(dojo.isFF < 3 || !this._XhtmlRoles.test(curRole)){
+			dojo.attr(elem, "role", dojo.isFF < 3 ? "wairole:" + role : role);
+		}else{
+			if((" "+ curRole +" ").indexOf(" " + role + " ") < 0){
+				var clearXhtml = dojo.trim(curRole.replace(this._XhtmlRoles, ""));
+				var cleanRole = dojo.trim(curRole.replace(clearXhtml, ""));	 
+         		dojo.attr(elem, "role", cleanRole + (cleanRole ? ' ' : '') + role);
+			}
+		}
+	},
+
+	removeWaiRole: function(/*Element*/ elem, /*String*/ role){
+		// summary:
+		//		Removes the specified non-XHTML role from an element.
+		// 		Removes role attribute if no specific role provided (for backwards compat.)
+
+		var roleValue = dojo.attr(elem, "role"); 
+		if(!roleValue){ return; }
+		if(role){
+			var searchRole = dojo.isFF < 3 ? "wairole:" + role : role;
+			var t = dojo.trim((" " + roleValue + " ").replace(" " + searchRole + " ", " "));
+			dojo.attr(elem, "role", t);
+		}else{
+			elem.removeAttribute("role");	
+		}
+	},
+
+	hasWaiState: function(/*Element*/ elem, /*String*/ state){
+		// summary:
+		//		Determines if an element has a given state.
+		// description:
+		//		On Firefox 2 and below, we check for an attribute in namespace
+		//		"http://www.w3.org/2005/07/aaa" with a name of the given state.
+		//		On all other browsers, we check for an attribute
+		//		called "aria-"+state.
+		// returns:
+		//		true if elem has a value for the given state and
+		//		false if it does not.
+		if(dojo.isFF < 3){
+			return elem.hasAttributeNS("http://www.w3.org/2005/07/aaa", state);
+		}
+		return elem.hasAttribute ? elem.hasAttribute("aria-"+state) : !!elem.getAttribute("aria-"+state);
+	},
+
+	getWaiState: function(/*Element*/ elem, /*String*/ state){
+		// summary:
+		//		Gets the value of a state on an element.
+		// description:
+		//		On Firefox 2 and below, we check for an attribute in namespace
+		//		"http://www.w3.org/2005/07/aaa" with a name of the given state.
+		//		On all other browsers, we check for an attribute called
+		//		"aria-"+state.
+		// returns:
+		//		The value of the requested state on elem
+		//		or an empty string if elem has no value for state.
+		if(dojo.isFF < 3){
+			return elem.getAttributeNS("http://www.w3.org/2005/07/aaa", state);
+		}
+		return elem.getAttribute("aria-"+state) || "";
+	},
+
+	setWaiState: function(/*Element*/ elem, /*String*/ state, /*String*/ value){
+		// summary:
+		//		Sets a state on an element.
+		// description:
+		//		On Firefox 2 and below, we set an attribute in namespace
+		//		"http://www.w3.org/2005/07/aaa" with a name of the given state.
+		//		On all other browsers, we set an attribute called
+		//		"aria-"+state.
+		if(dojo.isFF < 3){
+			elem.setAttributeNS("http://www.w3.org/2005/07/aaa",
+				"aaa:"+state, value);
+		}else{
+			elem.setAttribute("aria-"+state, value);
+		}
+	},
+
+	removeWaiState: function(/*Element*/ elem, /*String*/ state){
+		// summary:
+		//		Removes a state from an element.
+		// description:
+		//		On Firefox 2 and below, we remove the attribute in namespace
+		//		"http://www.w3.org/2005/07/aaa" with a name of the given state.
+		//		On all other browsers, we remove the attribute called
+		//		"aria-"+state.
+		if(dojo.isFF < 3){
+			elem.removeAttributeNS("http://www.w3.org/2005/07/aaa", state);
+		}else{
+			elem.removeAttribute("aria-"+state);
+		}
+	}
+});
+
+}
+
+if(!dojo._hasResource["dijit._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._base"] = true;
+dojo.provide("dijit._base");
+
+
+
+
+
+
+
+
+
+
+
+}
+
+if(!dojo._hasResource["dijit._Widget"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._Widget"] = true;
+dojo.provide("dijit._Widget");
+
+dojo.require( "dijit._base" );
+
+dojo.connect(dojo, "connect", 
+	function(/*Widget*/ widget, /*String*/ event){
+		if(widget && dojo.isFunction(widget._onConnect)){
+			widget._onConnect(event);
+		}
+	});
+
+dijit._connectOnUseEventHandler = function(/*Event*/ event){};
+
+(function(){
+
+var _attrReg = {};
+var getAttrReg = function(dc){
+	if(!_attrReg[dc]){
+		var r = [];
+		var attrs;
+		var proto = dojo.getObject(dc).prototype;
+		for(var fxName in proto){
+			if(dojo.isFunction(proto[fxName]) && (attrs = fxName.match(/^_set([a-zA-Z]*)Attr$/)) && attrs[1]){
+				r.push(attrs[1].charAt(0).toLowerCase() + attrs[1].substr(1));
+			}
+		}
+		_attrReg[dc] = r;
+	}
+	return _attrReg[dc]||[];
+}
+
+dojo.declare("dijit._Widget", null, {
+	// summary:
+	//		Base class for all dijit widgets. 	
+
+	// id: [const] String
+	//		A unique, opaque ID string that can be assigned by users or by the
+	//		system. If the developer passes an ID which is known not to be
+	//		unique, the specified ID is ignored and the system-generated ID is
+	//		used instead.
+	id: "",
+
+	// lang: [const] String
+	//		Rarely used.  Overrides the default Dojo locale used to render this widget,
+	//		as defined by the [HTML LANG](http://www.w3.org/TR/html401/struct/dirlang.html#adef-lang) attribute.
+	//		Value must be among the list of locales specified during by the Dojo bootstrap,
+	//		formatted according to [RFC 3066](http://www.ietf.org/rfc/rfc3066.txt) (like en-us).
+	lang: "",
+
+	// dir: [const] String
+	//		Unsupported by Dijit, but here for completeness.  Dijit only supports setting text direction on the
+	//		entire document.
+	//		Bi-directional support, as defined by the [HTML DIR](http://www.w3.org/TR/html401/struct/dirlang.html#adef-dir)
+	//		attribute. Either left-to-right "ltr" or right-to-left "rtl".
+	dir: "",
+
+	// class: String
+	//		HTML class attribute
+	"class": "",
+
+	// style: String||Object
+	//		HTML style attributes as cssText string or name/value hash
+	style: "",
+
+	// title: String
+	//		HTML title attribute, used to specify the title of tabs, accordion panes, etc.
+	title: "",
+
+	// srcNodeRef: [readonly] DomNode
+	//		pointer to original dom node
+	srcNodeRef: null,
+
+	// domNode: [readonly] DomNode
+	//		This is our visible representation of the widget! Other DOM
+	//		Nodes may by assigned to other properties, usually through the
+	//		template system's dojoAttachPoint syntax, but the domNode
+	//		property is the canonical "top level" node in widget UI.
+	domNode: null,
+
+	// containerNode: [readonly] DomNode
+	//		Designates where children of the source dom node will be placed.
+	//		"Children" in this case refers to both dom nodes and widgets.
+	//		For example, for myWidget:
+	//
+	//		|	<div dojoType=myWidget>
+	//		|		<b> here's a plain dom node
+	//		|		<span dojoType=subWidget>and a widget</span>
+	//		|		<i> and another plain dom node </i>
+	//		|	</div>
+	//
+	//		containerNode would point to:
+	//
+	//		|		<b> here's a plain dom node
+	//		|		<span dojoType=subWidget>and a widget</span>
+	//		|		<i> and another plain dom node </i>
+	//
+	//		In templated widgets, "containerNode" is set via a
+	//		dojoAttachPoint assignment.
+	//
+	//		containerNode must be defined for any widget that accepts innerHTML
+	//		(like ContentPane or BorderContainer or even Button), and conversely
+	//		is null for widgets that don't, like TextBox.
+	containerNode: null,
+
+	// attributeMap: [protected] Object
+	//		attributeMap sets up a "binding" between attributes (aka properties)
+	//		of the widget and the widget's DOM.
+	//		Changes to widget attributes listed in attributeMap will be 
+	//		reflected into the DOM.
+	//
+	//		For example, calling attr('title', 'hello')
+	//		on a TitlePane will automatically cause the TitlePane's DOM to update
+	//		with the new title.
+	//
+	//		attributeMap is a hash where the key is an attribute of the widget,
+	//		and the value reflects a binding to a:
+	//
+	//		- DOM node attribute
+	// |		focus: {node: "focusNode", type: "attribute"}
+	// 		Maps this.focus to this.focusNode.focus
+	//
+	//		- DOM node innerHTML
+	//	|		title: { node: "titleNode", type: "innerHTML" }
+	//		Maps this.title to this.titleNode.innerHTML
+	//
+	//		- DOM node CSS class
+	// |		myClass: { node: "domNode", type: "class" }
+	//		Maps this.myClass to this.domNode.className
+	//
+	//		If the value is an array, then each element in the array matches one of the
+	//		formats of the above list.
+	//
+	//		There are also some shorthands for backwards compatibility:
+	//		- string --> { node: string, type: "attribute" }, for example:
+	//	|	"focusNode" ---> { node: "focusNode", type: "attribute" }
+	//		- "" --> { node: "domNode", type: "attribute" }
+	attributeMap: {id:"", dir:"", lang:"", "class":"", style:"", title:""},
+
+	// _deferredConnects: [protected] Object
+	//		attributeMap addendum for event handlers that should be connected only on first use
+	_deferredConnects: {
+		onClick: "",
+		onDblClick: "",
+		onKeyDown: "",
+		onKeyPress: "",
+		onKeyUp: "",
+		onMouseMove: "",
+		onMouseDown: "",
+		onMouseOut: "",
+		onMouseOver: "",
+		onMouseLeave: "",
+		onMouseEnter: "",
+		onMouseUp: ""},
+
+	onClick: dijit._connectOnUseEventHandler,
+	/*=====
+	onClick: function(event){
+		// summary: 
+		//		Connect to this function to receive notifications of mouse click events.
+		// event:
+		//		mouse Event
+		// tags:
+		//		callback
+	},
+	=====*/
+	onDblClick: dijit._connectOnUseEventHandler,
+	/*=====
+	onDblClick: function(event){
+		// summary: 
+		//		Connect to this function to receive notifications of mouse double click events.
+		// event:
+		//		mouse Event
+		// tags:
+		//		callback
+	},
+	=====*/
+	onKeyDown: dijit._connectOnUseEventHandler,
+	/*=====
+	onKeyDown: function(event){
+		// summary: 
+		//		Connect to this function to receive notifications of keys being pressed down.
+		// event:
+		//		key Event
+		// tags:
+		//		callback
+	},
+	=====*/
+	onKeyPress: dijit._connectOnUseEventHandler,
+	/*=====
+	onKeyPress: function(event){
+		// summary: 
+		//		Connect to this function to receive notifications of printable keys being typed.
+		// event:
+		//		key Event
+		// tags:
+		//		callback
+	},
+	=====*/
+	onKeyUp: dijit._connectOnUseEventHandler,
+	/*=====
+	onKeyUp: function(event){
+		// summary: 
+		//		Connect to this function to receive notifications of keys being released.
+		// event:
+		//		key Event
+		// tags:
+		//		callback
+	},
+	=====*/
+	onMouseDown: dijit._connectOnUseEventHandler,
+	/*=====
+	onMouseDown: function(event){
+		// summary: 
+		//		Connect to this function to receive notifications of when the mouse button is pressed down.
+		// event:
+		//		mouse Event
+		// tags:
+		//		callback
+	},
+	=====*/
+	onMouseMove: dijit._connectOnUseEventHandler,
+	/*=====
+	onMouseMove: function(event){
+		// summary: 
+		//		Connect to this function to receive notifications of when the mouse moves over nodes contained within this widget.
+		// event:
+		//		mouse Event
+		// tags:
+		//		callback
+	},
+	=====*/
+	onMouseOut: dijit._connectOnUseEventHandler,
+	/*=====
+	onMouseOut: function(event){
+		// summary: 
+		//		Connect to this function to receive notifications of when the mouse moves off of nodes contained within this widget.
+		// event:
+		//		mouse Event
+		// tags:
+		//		callback
+	},
+	=====*/
+	onMouseOver: dijit._connectOnUseEventHandler,
+	/*=====
+	onMouseOver: function(event){
+		// summary: 
+		//		Connect to this function to receive notifications of when the mouse moves onto nodes contained within this widget.
+		// event:
+		//		mouse Event
+		// tags:
+		//		callback
+	},
+	=====*/
+	onMouseLeave: dijit._connectOnUseEventHandler,
+	/*=====
+	onMouseLeave: function(event){
+		// summary: 
+		//		Connect to this function to receive notifications of when the mouse moves off of this widget.
+		// event:
+		//		mouse Event
+		// tags:
+		//		callback
+	},
+	=====*/
+	onMouseEnter: dijit._connectOnUseEventHandler,
+	/*=====
+	onMouseEnter: function(event){
+		// summary: 
+		//		Connect to this function to receive notifications of when the mouse moves onto this widget.
+		// event:
+		//		mouse Event
+		// tags:
+		//		callback
+	},
+	=====*/
+	onMouseUp: dijit._connectOnUseEventHandler,
+	/*=====
+	onMouseUp: function(event){
+		// summary: 
+		//		Connect to this function to receive notifications of when the mouse button is released.
+		// event:
+		//		mouse Event
+		// tags:
+		//		callback
+	},
+	=====*/
+
+	// Constants used in templates
+	
+	// _blankGif: [protected] URL
+	//		Used by <img> nodes in templates that really get there image via CSS background-image
+	_blankGif: (dojo.config.blankGif || dojo.moduleUrl("dojo", "resources/blank.gif")),
+
+	//////////// INITIALIZATION METHODS ///////////////////////////////////////
+
+	postscript: function(/*Object?*/params, /*DomNode|String*/srcNodeRef){
+		// summary:
+		//		Kicks off widget instantiation.  See create() for details.
+		// tags:
+		//		private
+		this.create(params, srcNodeRef);
+	},
+
+	create: function(/*Object?*/params, /*DomNode|String?*/srcNodeRef){
+		// summary:
+		//		Kick off the life-cycle of a widget
+		// params:
+		//		Hash of initialization parameters for widget, including
+		//		scalar values (like title, duration etc.) and functions,
+		//		typically callbacks like onClick.
+		// srcNodeRef:
+		//		If a srcNodeRef (dom node) is specified:
+		//			- use srcNodeRef.innerHTML as my contents
+		//			- if this is a behavioral widget then apply behavior
+		//			  to that srcNodeRef 
+		//			- otherwise, replace srcNodeRef with my generated DOM
+		//			  tree
+		// description:
+		//		To understand the process by which widgets are instantiated, it
+		//		is critical to understand what other methods create calls and
+		//		which of them you'll want to override. Of course, adventurous
+		//		developers could override create entirely, but this should
+		//		only be done as a last resort.
+		//
+		//		Below is a list of the methods that are called, in the order
+		//		they are fired, along with notes about what they do and if/when
+		//		you should over-ride them in your widget:
+		//
+		// * postMixInProperties:
+		//	|	* a stub function that you can over-ride to modify
+		//		variables that may have been naively assigned by
+		//		mixInProperties
+		// * widget is added to manager object here
+		// * buildRendering:
+		//	|	* Subclasses use this method to handle all UI initialization
+		//		Sets this.domNode.  Templated widgets do this automatically
+		//		and otherwise it just uses the source dom node.
+		// * postCreate:
+		//	|	* a stub function that you can over-ride to modify take
+		//		actions once the widget has been placed in the UI
+		// tags:
+		//		private
+
+		// store pointer to original dom tree
+		this.srcNodeRef = dojo.byId(srcNodeRef);
+
+		// For garbage collection.  An array of handles returned by Widget.connect()
+		// Each handle returned from Widget.connect() is an array of handles from dojo.connect()
+		this._connects = [];
+
+		// To avoid double-connects, remove entries from _deferredConnects
+		// that have been setup manually by a subclass (ex, by dojoAttachEvent).
+		// If a subclass has redefined a callback (ex: onClick) then assume it's being
+		// connected to manually.
+		this._deferredConnects = dojo.clone(this._deferredConnects);
+		for(var attr in this.attributeMap){
+			delete this._deferredConnects[attr]; // can't be in both attributeMap and _deferredConnects
+		}
+		for(attr in this._deferredConnects){
+			if(this[attr] !== dijit._connectOnUseEventHandler){
+				delete this._deferredConnects[attr];	// redefined, probably dojoAttachEvent exists
+			}
+		}
+
+		//mixin our passed parameters
+		if(this.srcNodeRef && (typeof this.srcNodeRef.id == "string")){ this.id = this.srcNodeRef.id; }
+		if(params){
+			this.params = params;
+			dojo.mixin(this,params);
+		}
+		this.postMixInProperties();
+
+		// generate an id for the widget if one wasn't specified
+		// (be sure to do this before buildRendering() because that function might
+		// expect the id to be there.)
+		if(!this.id){
+			this.id = dijit.getUniqueId(this.declaredClass.replace(/\./g,"_"));
+		}
+		dijit.registry.add(this);
+
+		this.buildRendering();
+
+		if(this.domNode){
+			// Copy attributes listed in attributeMap into the [newly created] DOM for the widget.
+			this._applyAttributes();
+
+			var source = this.srcNodeRef;
+			if(source && source.parentNode){
+				source.parentNode.replaceChild(this.domNode, source);
+			}
+
+			// If the developer has specified a handler as a widget parameter
+			// (ex: new Button({onClick: ...})
+			// then naturally need to connect from dom node to that handler immediately, 
+			for(attr in this.params){
+				this._onConnect(attr);
+			}
+		}
+		
+		if(this.domNode){
+			this.domNode.setAttribute("widgetId", this.id);
+		}
+		this.postCreate();
+
+		// If srcNodeRef has been processed and removed from the DOM (e.g. TemplatedWidget) then delete it to allow GC.
+		if(this.srcNodeRef && !this.srcNodeRef.parentNode){
+			delete this.srcNodeRef;
+		}	
+
+		this._created = true;
+	},
+
+	_applyAttributes: function(){
+		// summary:
+		//		Step during widget creation to copy all widget attributes to the
+		//		DOM as per attributeMap and _setXXXAttr functions.
+		// description:
+		//		Skips over blank/false attribute values, unless they were explicitly specified
+		//		as parameters to the widget, since those are the default anyway,
+		//		and setting tabIndex="" is different than not setting tabIndex at all.
+		//
+		//		It processes the attributes in the attribute map first, and then
+		//		it goes through and processes the attributes for the _setXXXAttr
+		//		functions that have been specified
+		// tags:
+		//		private
+		var condAttrApply = function(attr, scope){
+			if( (scope.params && attr in scope.params) || scope[attr]){
+				scope.attr(attr, scope[attr]);
+			}
+		};
+		for(var attr in this.attributeMap){
+			condAttrApply(attr, this);
+		}
+		dojo.forEach(getAttrReg(this.declaredClass), function(a){
+			if(!(a in this.attributeMap)){
+				condAttrApply(a, this);
+			}
+		}, this);
+	},
+
+	postMixInProperties: function(){
+		// summary:
+		//		Called after the parameters to the widget have been read-in,
+		//		but before the widget template is instantiated. Especially
+		//		useful to set properties that are referenced in the widget
+		//		template.
+		// tags:
+		//		protected
+	},
+
+	buildRendering: function(){
+		// summary:
+		//		Construct the UI for this widget, setting this.domNode.  Most
+		//		widgets will mixin `dijit._Templated`, which implements this
+		//		method.
+		// tags:
+		//		protected
+		this.domNode = this.srcNodeRef || dojo.create('div');
+	},
+
+	postCreate: function(){
+		// summary:
+		//		Called after a widget's dom has been setup
+		// tags:
+		//		protected
+	},
+
+	startup: function(){
+		// summary:
+		//		Called after a widget's children, and other widgets on the page, have been created.
+		//		Provides an opportunity to manipulate any children before they are displayed.
+		//		This is useful for composite widgets that need to control or layout sub-widgets.
+		//		Many layout widgets can use this as a wiring phase.
+		this._started = true;
+	},
+
+	//////////// DESTROY FUNCTIONS ////////////////////////////////
+
+	destroyRecursive: function(/*Boolean?*/ preserveDom){
+		// summary:
+		// 		Destroy this widget and it's descendants. This is the generic
+		// 		"destructor" function that all widget users should call to
+		// 		cleanly discard with a widget. Once a widget is destroyed, it's
+		// 		removed from the manager object.
+		// preserveDom:
+		//		If true, this method will leave the original Dom structure
+		//		alone of descendant Widgets. Note: This will NOT work with
+		//		dijit._Templated widgets.
+
+		this.destroyDescendants(preserveDom);
+		this.destroy(preserveDom);
+	},
+
+	destroy: function(/*Boolean*/ preserveDom){
+		// summary:
+		// 		Destroy this widget, but not its descendants.
+		//		Will, however, destroy internal widgets such as those used within a template.
+		// preserveDom: Boolean
+		//		If true, this method will leave the original Dom structure alone.
+		//		Note: This will not yet work with _Templated widgets
+
+		this.uninitialize();
+		dojo.forEach(this._connects, function(array){
+			dojo.forEach(array, dojo.disconnect);
+		});
+
+		// destroy widgets created as part of template, etc.
+		dojo.forEach(this._supportingWidgets||[], function(w){ 
+			if(w.destroy){
+				w.destroy();
+			}
+		});
+		
+		this.destroyRendering(preserveDom);
+		dijit.registry.remove(this.id);
+	},
+
+	destroyRendering: function(/*Boolean?*/ preserveDom){
+		// summary:
+		//		Destroys the DOM nodes associated with this widget
+		// preserveDom:
+		//		If true, this method will leave the original Dom structure alone
+		//		during tear-down. Note: this will not work with _Templated
+		//		widgets yet. 
+		// tags:
+		//		protected
+
+		if(this.bgIframe){
+			this.bgIframe.destroy(preserveDom);
+			delete this.bgIframe;
+		}
+
+		if(this.domNode){
+			if(preserveDom){
+				dojo.removeAttr(this.domNode, "widgetId");
+			}else{
+				dojo.destroy(this.domNode);
+			}
+			delete this.domNode;
+		}
+
+		if(this.srcNodeRef){
+			if(!preserveDom){
+				dojo.destroy(this.srcNodeRef);
+			}
+			delete this.srcNodeRef;
+		}
+	},
+
+	destroyDescendants: function(/*Boolean?*/ preserveDom){
+		// summary:
+		//		Recursively destroy the children of this widget and their
+		//		descendants.
+		// preserveDom:
+		//		If true, the preserveDom attribute is passed to all descendant
+		//		widget's .destroy() method. Not for use with _Templated
+		//		widgets.
+
+		// get all direct descendants and destroy them recursively
+		dojo.forEach(this.getChildren(), function(widget){ 
+			if(widget.destroyRecursive){
+				widget.destroyRecursive(preserveDom);
+			}
+		});
+	},
+
+
+	uninitialize: function(){
+		// summary:
+		//		Stub function. Override to implement custom widget tear-down
+		//		behavior.
+		// tags:
+		//		protected
+		return false;
+	},
+
+	////////////////// MISCELLANEOUS METHODS ///////////////////
+
+	onFocus: function(){
+		// summary:
+		//		Called when the widget becomes "active" because
+		//		it or a widget inside of it either has focus, or has recently
+		//		been clicked.
+		// tags:
+		//		callback
+	},
+
+	onBlur: function(){
+		// summary:
+		//		Called when the widget stops being "active" because
+		//		focus moved to something outside of it, or the user
+		//		clicked somewhere outside of it, or the widget was
+		//		hidden.
+		// tags:
+		//		callback
+	},
+
+	_onFocus: function(e){
+		// summary:
+		//		This is where widgets do processing for when they are active,
+		//		such as changing CSS classes.  See onFocus() for more details.
+		// tags:
+		//		protected
+		this.onFocus();
+	},
+
+	_onBlur: function(){
+		// summary:
+		//		This is where widgets do processing for when they stop being active,
+		//		such as changing CSS classes.  See onBlur() for more details.
+		// tags:
+		//		protected
+		this.onBlur();
+	},
+
+	_onConnect: function(/*String*/ event){
+		// summary:
+		//		Called when someone connects to one of my handlers.
+		//		"Turn on" that handler if it isn't active yet.
+		//
+		//		This is also called for every single initialization parameter
+		//		so need to do nothing for parameters like "id".
+		// tags:
+		//		private
+		if(event in this._deferredConnects){
+			var mapNode = this[this._deferredConnects[event]||'domNode'];
+			this.connect(mapNode, event.toLowerCase(), event);
+			delete this._deferredConnects[event];
+		}
+	},
+
+	_setClassAttr: function(/*String*/ value){
+		// summary:
+		//		Custom setter for the CSS "class" attribute
+		// tags:
+		//		protected
+		var mapNode = this[this.attributeMap["class"]||'domNode'];
+		dojo.removeClass(mapNode, this["class"])
+		this["class"] = value;
+		dojo.addClass(mapNode, value);
+	},
+
+	_setStyleAttr: function(/*String||Object*/ value){
+		// summary:
+		//		Sets the style attribut of the widget according to value,
+		//		which is either a hash like {height: "5px", width: "3px"}
+		//		or a plain string
+		// description:
+		//		Determines which node to set the style on based on style setting
+		//		in attributeMap.
+		// tags:
+		//		protected
+
+		var mapNode = this[this.attributeMap["style"]||'domNode'];
+		
+		// Note: technically we should revert any style setting made in a previous call
+		// to his method, but that's difficult to keep track of.
+
+		if(dojo.isObject(value)){
+			dojo.style(mapNode, value);
+		}else{
+			if(mapNode.style.cssText){
+				mapNode.style.cssText += "; " + value;
+			}else{
+				mapNode.style.cssText = value;
+			}
+		}
+
+		this["style"] = value;
+	},
+
+	setAttribute: function(/*String*/ attr, /*anything*/ value){
+		// summary:
+		//		Deprecated.  Use attr() instead.
+		// tags:
+		//		deprecated
+		dojo.deprecated(this.declaredClass+"::setAttribute() is deprecated. Use attr() instead.", "", "2.0");
+		this.attr(attr, value);
+	},
+	
+	_attrToDom: function(/*String*/ attr, /*String*/ value){
+		// summary:
+		//		Reflect a widget attribute (title, tabIndex, duration etc.) to
+		//		the widget DOM, as specified in attributeMap.
+		//
+		// description:
+		//		Also sets this["attr"] to the new value.
+		//		Note some attributes like "type"
+		//		cannot be processed this way as they are not mutable.
+		//
+		// tags:
+		//		private
+
+		var commands = this.attributeMap[attr];
+		dojo.forEach( dojo.isArray(commands) ? commands : [commands], function(command){
+
+			// Get target node and what we are doing to that node
+			var mapNode = this[command.node || command || "domNode"];	// DOM node
+			var type = command.type || "attribute";	// class, innerHTML, or attribute
+	
+			switch(type){
+				case "attribute":
+					if(dojo.isFunction(value)){ // functions execute in the context of the widget
+						value = dojo.hitch(this, value);
+					}
+					if(/^on[A-Z][a-zA-Z]*$/.test(attr)){ // eg. onSubmit needs to be onsubmit
+						attr = attr.toLowerCase();
+					}
+					dojo.attr(mapNode, attr, value);
+					break;
+				case "innerHTML":
+					mapNode.innerHTML = value;
+					break;
+				case "class":
+					dojo.removeClass(mapNode, this[attr]);
+					dojo.addClass(mapNode, value);
+					break;
+			}
+		}, this);
+		this[attr] = value;
+	},
+
+	attr: function(/*String|Object*/name, /*Object?*/value){
+		//	summary:
+		//		Set or get properties on a widget instance.
+		//	name:
+		//		The property to get or set. If an object is passed here and not
+		//		a string, its keys are used as names of attributes to be set
+		//		and the value of the object as values to set in the widget.
+		//	value:
+		//		Optional. If provided, attr() operates as a setter. If omitted,
+		//		the current value of the named property is returned.
+		//	description:
+		//		Get or set named properties on a widget. If no value is
+		//		provided, the current value of the attribute is returned,
+		//		potentially via a getter method. If a value is provided, then
+		//		the method acts as a setter, assigning the value to the name,
+		//		potentially calling any explicitly provided setters to handle
+		//		the operation. For instance, if the widget has properties "foo"
+		//		and "bar" and a method named "_setFooAttr", calling:
+		//	|	myWidget.attr("foo", "Howdy!");
+		//		would be equivalent to calling:
+		//	|	widget._setFooAttr("Howdy!");
+		//		while calling:
+		//	|	myWidget.attr("bar", "Howdy!");
+		//		would be the same as writing:
+		//	|	widget.bar = "Howdy!";
+		//		It also tries to copy the changes to the widget's DOM according
+		//		to settings in attributeMap (see description of `dijit._Widget.attributeMap`
+		//		for details)
+		//		For example, calling:
+		//	|	myTitlePane.attr("title", "Howdy!");
+		//		will do
+		//	|	myTitlePane.title = "Howdy!";
+		//	|	myTitlePane.title.innerHTML = "Howdy!";
+		//		It works for dom node attributes too.  Calling
+		//	|	widget.attr("disabled", true)
+		//		will set the disabled attribute on the widget's focusNode,
+		//		among other housekeeping for a change in disabled state.
+
+		//	open questions:
+		//		- how to handle build shortcut for attributes which want to map
+		//		into DOM attributes?
+		//		- what relationship should setAttribute()/attr() have to
+		//		layout() calls?
+		var args = arguments.length;
+		if(args == 1 && !dojo.isString(name)){
+			for(var x in name){ this.attr(x, name[x]); }
+			return this;
+		}
+		var names = this._getAttrNames(name);
+		if(args == 2){ // setter
+			if(this[names.s]){
+				// use the explicit setter
+				return this[names.s](value) || this;
+			}else{
+				// if param is specified as DOM node attribute, copy it
+				if(name in this.attributeMap){
+					this._attrToDom(name, value);
+				}
+
+				// FIXME: what about function assignments? Any way to connect() here?
+				this[name] = value;
+			}
+			return this;
+		}else{ // getter
+			if(this[names.g]){
+				return this[names.g]();
+			}else{
+				return this[name];
+			}
+		}
+	},
+
+	_attrPairNames: {},		// shared between all widgets
+	_getAttrNames: function(name){
+		// summary:
+		//		Helper function for Widget.attr().
+		//		Caches attribute name values so we don't do the string ops every time.
+		// tags:
+		//		private
+
+		var apn = this._attrPairNames;
+		if(apn[name]){ return apn[name]; }
+		var uc = name.charAt(0).toUpperCase() + name.substr(1);
+		return apn[name] = {
+			n: name+"Node",
+			s: "_set"+uc+"Attr",
+			g: "_get"+uc+"Attr"
+		};
+	},
+
+	toString: function(){
+		// summary:
+		//		Returns a string that represents the widget. When a widget is
+		//		cast to a string, this method will be used to generate the
+		//		output. Currently, it does not implement any sort of reversable
+		//		serialization.
+		return '[Widget ' + this.declaredClass + ', ' + (this.id || 'NO ID') + ']'; // String
+	},
+
+	getDescendants: function(){
+		// summary:
+		//		Returns all the widgets that contained by this, i.e., all widgets underneath this.containerNode.
+		//		This method should generally be avoided as it returns widgets declared in templates, which are
+		//		supposed to be internal/hidden, but it's left here for back-compat reasons.
+
+		if(this.containerNode){
+			var list = dojo.query('[widgetId]', this.containerNode);
+			return list.map(dijit.byNode);		// Array
+		}else{
+			return [];
+		}
+	},
+
+	getChildren: function(){
+		// summary:
+		//		Returns all the widgets contained by this, i.e., all widgets underneath this.containerNode.
+		//		Does not return nested widgets, nor widgets that are part of this widget's template.
+		if(this.containerNode){
+			return dijit.findWidgets(this.containerNode);
+		}else{
+			return [];
+		}
+	},
+
+	// nodesWithKeyClick: [private] String[]
+	//		List of nodes that correctly handle click events via native browser support,
+	//		and don't need dijit's help
+	nodesWithKeyClick: ["input", "button"],
+
+	connect: function(
+			/*Object|null*/ obj,
+			/*String|Function*/ event,
+			/*String|Function*/ method){
+		// summary:
+		//		Connects specified obj/event to specified method of this object
+		//		and registers for disconnect() on widget destroy.
+		// description:
+		//		Provide widget-specific analog to dojo.connect, except with the
+		//		implicit use of this widget as the target object.
+		//		This version of connect also provides a special "ondijitclick"
+		//		event which triggers on a click or space-up, enter-down in IE
+		//		or enter press in FF (since often can't cancel enter onkeydown
+		//		in FF)
+		// example:
+		//	|	var btn = new dijit.form.Button();
+		//	|	// when foo.bar() is called, call the listener we're going to
+		//	|	// provide in the scope of btn
+		//	|	btn.connect(foo, "bar", function(){ 
+		//	|		
+		//	|	});
+		// tags:
+		//		protected
+
+		var d = dojo;
+		var dc = dojo.connect;
+		var handles =[];
+		if(event == "ondijitclick"){
+			// add key based click activation for unsupported nodes.
+			if(!this.nodesWithKeyClick[obj.nodeName]){
+				var m = d.hitch(this, method);
+				handles.push(
+					dc(obj, "onkeydown", this, function(e){
+						if(!d.isFF && e.keyCode == d.keys.ENTER &&
+							!e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey){
+							return m(e);
+						}else if(e.keyCode == d.keys.SPACE){
+							// stop space down as it causes IE to scroll
+							// the browser window
+							d.stopEvent(e);
+						}
+			 		}),
+					dc(obj, "onkeyup", this, function(e){
+						if(e.keyCode == d.keys.SPACE && 
+							!e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey){ return m(e); }
+					})
+				);
+			 	if(d.isFF){
+					handles.push(
+						dc(obj, "onkeypress", this, function(e){
+							if(e.keyCode == d.keys.ENTER &&
+								!e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey){ return m(e); }
+						})
+					);
+			 	}
+			}
+			event = "onclick";
+		}
+		handles.push(dc(obj, event, this, method));
+
+		// return handles for FormElement and ComboBox
+		this._connects.push(handles);
+		return handles;
+	},
+
+	disconnect: function(/*Object*/ handles){
+		// summary:
+		//		Disconnects handle created by this.connect.
+		//		Also removes handle from this widget's list of connects
+		// tags:
+		//		protected
+		for(var i=0; i<this._connects.length; i++){
+			if(this._connects[i]==handles){
+				dojo.forEach(handles, dojo.disconnect);
+				this._connects.splice(i, 1);
+				return;
+			}
+		}
+	},
+
+	isLeftToRight: function(){
+		// summary:
+		//		Checks the page for text direction
+		// tags:
+		//		protected
+		return dojo._isBodyLtr(); //Boolean
+	},
+
+	isFocusable: function(){
+		// summary:
+		//		Return true if this widget can currently be focused
+		//		and false if not
+		return this.focus && (dojo.style(this.domNode, "display") != "none");
+	},
+	
+	placeAt: function(/* String|DomNode|_Widget */reference, /* String?|Int? */position){
+		// summary:
+		//		Place this widget's domNode reference somewhere in the DOM based
+		//		on standard dojo.place conventions, or passing a Widget reference that
+		//		contains and addChild member.
+		//
+		// description:
+		//		A convenience function provided in all _Widgets, providing a simple
+		//		shorthand mechanism to put an existing (or newly created) Widget
+		//		somewhere in the dom, and allow chaining.
+		//
+		// reference: 
+		//		The String id of a domNode, a domNode reference, or a reference to a Widget posessing 
+		//		an addChild method.
+		//
+		// position: 
+		//		If passed a string or domNode reference, the position argument
+		//		accepts a string just as dojo.place does, one of: "first", "last", 
+		//		"before", or "after". 
+		//
+		//		If passed a _Widget reference, and that widget reference has an ".addChild" method, 
+		//		it will be called passing this widget instance into that method, supplying the optional
+		//		position index passed.
+		//
+		// returns: dijit._Widget
+		//		Provides a useful return of the newly created dijit._Widget instance so you 
+		//		can "chain" this function by instantiating, placing, then saving the return value
+		//		to a variable. 
+		//
+		// example:
+		// | 	// create a Button with no srcNodeRef, and place it in the body:
+		// | 	var button = new dijit.form.Button({ label:"click" }).placeAt(dojo.body());
+		// | 	// now, 'button' is still the widget reference to the newly created button
+		// | 	dojo.connect(button, "onClick", function(e){  });
+		//
+		// example:
+		// |	// create a button out of a node with id="src" and append it to id="wrapper":
+		// | 	var button = new dijit.form.Button({},"src").placeAt("wrapper");
+		//
+		// example:
+		// |	// place a new button as the first element of some div
+		// |	var button = new dijit.form.Button({ label:"click" }).placeAt("wrapper","first");
+		//
+		// example: 
+		// |	// create a contentpane and add it to a TabContainer
+		// |	var tc = dijit.byId("myTabs");
+		// |	new dijit.layout.ContentPane({ href:"foo.html", title:"Wow!" }).placeAt(tc)
+
+		if(reference["declaredClass"] && reference["addChild"]){
+			reference.addChild(this, position);
+		}else{
+			dojo.place(this.domNode, reference, position);
+		}
+		return this;
+	}
+
+});
+
+})();
+
+}
+
+if(!dojo._hasResource["dijit._Templated"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._Templated"] = true;
+dojo.provide("dijit._Templated");
+
+
+
+
+
+dojo.declare("dijit._Templated",
+	null,
+	{
+		//	summary:
+		//		Mixin for widgets that are instantiated from a template
+		// 
+
+		// templateString: [protected] String
+		//		A string that represents the widget template. Pre-empts the
+		//		templatePath. In builds that have their strings "interned", the
+		//		templatePath is converted to an inline templateString, thereby
+		//		preventing a synchronous network call.
+		templateString: null,
+
+		// templatePath: [protected] String
+		//		Path to template (HTML file) for this widget relative to dojo.baseUrl
+		templatePath: null,
+
+		// widgetsInTemplate: [protected] Boolean
+		//		Should we parse the template to find widgets that might be
+		//		declared in markup inside it?  False by default.
+		widgetsInTemplate: false,
+
+		// skipNodeCache: [protected] Boolean
+		//		If using a cached widget template node poses issues for a
+		//		particular widget class, it can set this property to ensure
+		//		that its template is always re-built from a string
+		_skipNodeCache: false,
+
+		_stringRepl: function(tmpl){
+			// summary:
+			//		Does substitution of ${foo} type properties in template string
+			// tags:
+			//		private
+			var className = this.declaredClass, _this = this;
+			// Cache contains a string because we need to do property replacement
+			// do the property replacement
+			return dojo.string.substitute(tmpl, this, function(value, key){
+				if(key.charAt(0) == '!'){ value = dojo.getObject(key.substr(1), false, _this); }
+				if(typeof value == "undefined"){ throw new Error(className+" template:"+key); } // a debugging aide
+				if(value == null){ return ""; }
+
+				// Substitution keys beginning with ! will skip the transform step,
+				// in case a user wishes to insert unescaped markup, e.g. ${!foo}
+				return key.charAt(0) == "!" ? value :
+					// Safer substitution, see heading "Attribute values" in
+					// http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2
+					value.toString().replace(/"/g,"&quot;"); //TODO: add &amp? use encodeXML method?
+			}, this);
+		},
+
+		// method over-ride
+		buildRendering: function(){
+			// summary:
+			//		Construct the UI for this widget from a template, setting this.domNode.
+			// tags:
+			//		protected
+
+			// Lookup cached version of template, and download to cache if it
+			// isn't there already.  Returns either a DomNode or a string, depending on
+			// whether or not the template contains ${foo} replacement parameters.
+			var cached = dijit._Templated.getCachedTemplate(this.templatePath, this.templateString, this._skipNodeCache);
+
+			var node;
+			if(dojo.isString(cached)){
+				node = dojo._toDom(this._stringRepl(cached));
+			}else{
+				// if it's a node, all we have to do is clone it
+				node = cached.cloneNode(true);
+			}
+
+			this.domNode = node;
+
+			// recurse through the node, looking for, and attaching to, our
+			// attachment points and events, which should be defined on the template node.
+			this._attachTemplateNodes(node);
+
+			if(this.widgetsInTemplate){
+				var cw = (this._supportingWidgets = dojo.parser.parse(node));
+				this._attachTemplateNodes(cw, function(n,p){
+					return n[p];
+				});
+			}
+
+			this._fillContent(this.srcNodeRef);
+		},
+
+		_fillContent: function(/*DomNode*/ source){
+			// summary:
+			//		Relocate source contents to templated container node.
+			//		this.containerNode must be able to receive children, or exceptions will be thrown.
+			// tags:
+			//		protected
+			var dest = this.containerNode;
+			if(source && dest){
+				while(source.hasChildNodes()){
+					dest.appendChild(source.firstChild);
+				}
+			}
+		},
+
+		_attachTemplateNodes: function(rootNode, getAttrFunc){
+			// summary:
+			//		Iterate through the template and attach functions and nodes accordingly.	
+			// description:		
+			//		Map widget properties and functions to the handlers specified in
+			//		the dom node and it's descendants. This function iterates over all
+			//		nodes and looks for these properties:
+			//			* dojoAttachPoint
+			//			* dojoAttachEvent	
+			//			* waiRole
+			//			* waiState
+			// rootNode: DomNode|Array[Widgets]
+			//		the node to search for properties. All children will be searched.
+			// getAttrFunc: Function?
+			//		a function which will be used to obtain property for a given
+			//		DomNode/Widget
+			// tags:
+			//		private
+
+			getAttrFunc = getAttrFunc || function(n,p){ return n.getAttribute(p); };
+
+			var nodes = dojo.isArray(rootNode) ? rootNode : (rootNode.all || rootNode.getElementsByTagName("*"));
+			var x = dojo.isArray(rootNode) ? 0 : -1;
+			for(; x<nodes.length; x++){
+				var baseNode = (x == -1) ? rootNode : nodes[x];
+				if(this.widgetsInTemplate && getAttrFunc(baseNode, "dojoType")){
+					continue;
+				}
+				// Process dojoAttachPoint
+				var attachPoint = getAttrFunc(baseNode, "dojoAttachPoint");
+				if(attachPoint){
+					var point, points = attachPoint.split(/\s*,\s*/);
+					while((point = points.shift())){
+						if(dojo.isArray(this[point])){
+							this[point].push(baseNode);
+						}else{
+							this[point]=baseNode;
+						}
+					}
+				}
+
+				// Process dojoAttachEvent
+				var attachEvent = getAttrFunc(baseNode, "dojoAttachEvent");
+				if(attachEvent){
+					// NOTE: we want to support attributes that have the form
+					// "domEvent: nativeEvent; ..."
+					var event, events = attachEvent.split(/\s*,\s*/);
+					var trim = dojo.trim;
+					while((event = events.shift())){
+						if(event){
+							var thisFunc = null;
+							if(event.indexOf(":") != -1){
+								// oh, if only JS had tuple assignment
+								var funcNameArr = event.split(":");
+								event = trim(funcNameArr[0]);
+								thisFunc = trim(funcNameArr[1]);
+							}else{
+								event = trim(event);
+							}
+							if(!thisFunc){
+								thisFunc = event;
+							}
+							this.connect(baseNode, event, thisFunc);
+						}
+					}
+				}
+
+				// waiRole, waiState
+				var role = getAttrFunc(baseNode, "waiRole");
+				if(role){
+					dijit.setWaiRole(baseNode, role);
+				}
+				var values = getAttrFunc(baseNode, "waiState");
+				if(values){
+					dojo.forEach(values.split(/\s*,\s*/), function(stateValue){
+						if(stateValue.indexOf('-') != -1){
+							var pair = stateValue.split('-');
+							dijit.setWaiState(baseNode, pair[0], pair[1]);
+						}
+					});
+				}
+			}
+		}
+	}
+);
+
+// key is either templatePath or templateString; object is either string or DOM tree
+dijit._Templated._templateCache = {};
+
+dijit._Templated.getCachedTemplate = function(templatePath, templateString, alwaysUseString){
+	// summary:
+	//		Static method to get a template based on the templatePath or
+	//		templateString key
+	// templatePath: String
+	//		The URL to get the template from. dojo.uri.Uri is often passed as well.
+	// templateString: String?
+	//		a string to use in lieu of fetching the template from a URL. Takes precedence
+	//		over templatePath
+	// returns: Mixed
+	//		Either string (if there are ${} variables that need to be replaced) or just
+	//		a DOM tree (if the node can be cloned directly)
+
+	// is it already cached?
+	var tmplts = dijit._Templated._templateCache;
+	var key = templateString || templatePath;
+	var cached = tmplts[key];
+	if(cached){
+		if(!cached.ownerDocument || cached.ownerDocument == dojo.doc){
+			// string or node of the same document
+			return cached;
+		}
+		// destroy the old cached node of a different document
+		dojo.destroy(cached);
+	}
+
+	// If necessary, load template string from template path
+	if(!templateString){
+		templateString = dijit._Templated._sanitizeTemplateString(dojo.trim(dojo._getText(templatePath)));
+	}
+
+	templateString = dojo.string.trim(templateString);
+
+	if(alwaysUseString || templateString.match(/\$\{([^\}]+)\}/g)){
+		// there are variables in the template so all we can do is cache the string
+		return (tmplts[key] = templateString); //String
+	}else{
+		// there are no variables in the template so we can cache the DOM tree
+		return (tmplts[key] = dojo._toDom(templateString)); //Node
+	}
+};
+
+dijit._Templated._sanitizeTemplateString = function(/*String*/tString){
+	// summary: 
+	//		Strips <?xml ...?> declarations so that external SVG and XML
+	// 		documents can be added to a document without worry. Also, if the string
+	//		is an HTML document, only the part inside the body tag is returned.
+	if(tString){
+		tString = tString.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, "");
+		var matches = tString.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
+		if(matches){
+			tString = matches[1];
+		}
+	}else{
+		tString = "";
+	}
+	return tString; //String
+};
+
+
+if(dojo.isIE){
+	dojo.addOnWindowUnload(function(){
+		var cache = dijit._Templated._templateCache;
+		for(var key in cache){
+			var value = cache[key];
+			if(!isNaN(value.nodeType)){ // isNode equivalent
+				dojo.destroy(value);
+			}
+			delete cache[key];
+		}
+	});
+}
+
+// These arguments can be specified for widgets which are used in templates.
+// Since any widget can be specified as sub widgets in template, mix it
+// into the base widget class.  (This is a hack, but it's effective.)
+dojo.extend(dijit._Widget,{
+	dojoAttachEvent: "",
+	dojoAttachPoint: "",
+	waiRole: "",
+	waiState:""
+});
+
+}
+
+if(!dojo._hasResource["dijit._Calendar"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._Calendar"] = true;
+dojo.provide("dijit._Calendar");
+
+
+
+
+
+
+
+
+dojo.declare(
+	"dijit._Calendar",
+	[dijit._Widget, dijit._Templated],
+	{
+	// summary:
+	//		A simple GUI for choosing a date in the context of a monthly calendar.
+	//
+	// description:
+	//		A simple GUI for choosing a date in the context of a monthly calendar.
+	//		This widget is used internally by other widgets and is not accessible
+	//		as a standalone widget.
+	//		This widget can't be used in a form because it doesn't serialize the date to an
+	//		`<input>` field.  For a form element, use dijit.form.DateTextBox instead.
+	//
+	//		Note that the parser takes all dates attributes passed in the
+	//		[RFC 3339 format](http://www.faqs.org/rfcs/rfc3339.html), e.g. `2005-06-30T08:05:00-07:00`
+	//		so that they are serializable and locale-independent.
+	//
+	// example:
+	//	|	var calendar = new dijit._Calendar({}, dojo.byId("calendarNode"));
+	//
+	//	example:
+	//	|	<div dojoType="dijit._Calendar"></div>
+
+		templateString:"<table cellspacing=\"0\" cellpadding=\"0\" class=\"dijitCalendarContainer\">\n\t<thead>\n\t\t<tr class=\"dijitReset dijitCalendarMonthContainer\" valign=\"top\">\n\t\t\t<th class='dijitReset' dojoAttachPoint=\"decrementMonth\">\n\t\t\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitCalendarIncrementControl dijitCalendarDecrease\" waiRole=\"presentation\">\n\t\t\t\t<span dojoAttachPoint=\"decreaseArrowNode\" class=\"dijitA11ySideArrow\">-</span>\n\t\t\t</th>\n\t\t\t<th class='dijitReset' colspan=\"5\">\n\t\t\t\t<div dojoAttachPoint=\"monthLabelSpacer\" class=\"dijitCalendarMonthLabelSpacer\"></div>\n\t\t\t\t<div dojoAttachPoint=\"monthLabelNode\" class=\"dijitCalendarMonthLabel\"></div>\n\t\t\t</th>\n\t\t\t<th class='dijitReset' dojoAttachPoint=\"incrementMonth\">\n\t\t\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitCalendarIncrementControl dijitCalendarIncrease\" waiRole=\"presentation\">\n\t\t\t\t<span dojoAttachPoint=\"increaseArrowNode\" class=\"dijitA11ySideArrow\">+</span>\n\t\t\t</th>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<th class=\"dijitReset dijitCalendarDayLabelTemplate\"><span class=\"dijitCalendarDayLabel\"></span></th>\n\t\t</tr>\n\t</thead>\n\t<tbody dojoAttachEvent=\"onclick: _onDayClick, onmouseover: _onDayMouseOver, onmouseout: _onDayMouseOut\" class=\"dijitReset dijitCalendarBodyContainer\">\n\t\t<tr class=\"dijitReset dijitCalendarWeekTemplate\">\n\t\t\t<td class=\"dijitReset dijitCalendarDateTemplate\"><span class=\"dijitCalendarDateLabel\"></span></td>\n\t\t</tr>\n\t</tbody>\n\t<tfoot class=\"dijitReset dijitCalendarYearContainer\">\n\t\t<tr>\n\t\t\t<td class='dijitReset' valign=\"top\" colspan=\"7\">\n\t\t\t\t<h3 class=\"dijitCalendarYearLabel\">\n\t\t\t\t\t<span dojoAttachPoint=\"previousYearLabelNode\" class=\"dijitInline dijitCalendarPreviousYear\"></span>\n\t\t\t\t\t<span dojoAttachPoint=\"currentYearLabelNode\" class=\"dijitInline dijitCalendarSelectedYear\"></span>\n\t\t\t\t\t<span dojoAttachPoint=\"nextYearLabelNode\" class=\"dijitInline dijitCalendarNextYear\"></span>\n\t\t\t\t</h3>\n\t\t\t</td>\n\t\t</tr>\n\t</tfoot>\n</table>\t\n",
+
+		// value: Date
+		//		The currently selected Date
+		value: new Date(),
+
+		// dayWidth: String
+		//		How to represent the days of the week in the calendar header. See dojo.date.locale
+		dayWidth: "narrow",
+
+		setValue: function(/*Date*/ value){
+			// summary:
+			//      Deprecated.   Used attr('value', ...) instead.
+			// tags:
+			//      deprecated
+			dojo.deprecated("dijit.Calendar:setValue() is deprecated.  Use attr('value', ...) instead.", "", "2.0");
+			this.attr('value', value);
+		},
+
+		_getValueAttr: function(/*String*/ value){
+			// summary:
+			//		Hook so attr('value') works.
+			var value = new Date(this.value);
+			value.setHours(0, 0, 0, 0); // return midnight, local time for back-compat
+
+			// If daylight savings pushes midnight to the previous date, fix the Date
+			// object to point at 1am so it will represent the correct day. See #9366
+			if(value.getDate() < this.value.getDate()){
+				value = dojo.date.add(value, "hour", 1);
+			}
+			return value;
+		},
+
+		_setValueAttr: function(/*Date*/ value){
+			// summary:
+			//		Hook to make attr("value", ...) work.
+			// description:
+			// 		Set the current date and update the UI.  If the date is disabled, the selection will
+			//		not change, but the display will change to the corresponding month.
+			// tags:
+			//      protected
+			if(!this.value || dojo.date.compare(value, this.value)){
+				value = new Date(value);
+				value.setHours(1); // to avoid issues when DST shift occurs at midnight, see #8521, #9366
+				this.displayMonth = new Date(value);
+				if(!this.isDisabledDate(value, this.lang)){
+					this.value = value;
+					this.onChange(this.attr('value'));
+				}
+				this._populateGrid();
+			}
+		},
+
+		_setText: function(node, text){
+			// summary:
+			//		This just sets the content of node to the specified text.
+			//		Can't do "node.innerHTML=text" because of an IE bug w/tables, see #3434.
+			// tags:
+			//      private
+			while(node.firstChild){
+				node.removeChild(node.firstChild);
+			}
+			node.appendChild(dojo.doc.createTextNode(text));
+		},
+
+		_populateGrid: function(){
+			// summary:
+			//      Fills in the calendar grid with each day (1-31)
+			// tags:
+			//      private
+			var month = this.displayMonth;
+			month.setDate(1);
+			var firstDay = month.getDay();
+			var daysInMonth = dojo.date.getDaysInMonth(month);
+			var daysInPreviousMonth = dojo.date.getDaysInMonth(dojo.date.add(month, "month", -1));
+			var today = new Date();
+			var selected = this.value;
+
+			var dayOffset = dojo.cldr.supplemental.getFirstDayOfWeek(this.lang);
+			if(dayOffset > firstDay){ dayOffset -= 7; }
+
+			// Iterate through dates in the calendar and fill in date numbers and style info
+			dojo.query(".dijitCalendarDateTemplate", this.domNode).forEach(function(template, i){
+				i += dayOffset;
+				var date = new Date(month);
+				var number, clazz = "dijitCalendar", adj = 0;
+
+				if(i < firstDay){
+					number = daysInPreviousMonth - firstDay + i + 1;
+					adj = -1;
+					clazz += "Previous";
+				}else if(i >= (firstDay + daysInMonth)){
+					number = i - firstDay - daysInMonth + 1;
+					adj = 1;
+					clazz += "Next";
+				}else{
+					number = i - firstDay + 1;
+					clazz += "Current";
+				}
+
+				if(adj){
+					date = dojo.date.add(date, "month", adj);
+				}
+				date.setDate(number);
+
+				if(!dojo.date.compare(date, today, "date")){
+					clazz = "dijitCalendarCurrentDate " + clazz;
+				}
+
+				if(!dojo.date.compare(date, selected, "date")){
+					clazz = "dijitCalendarSelectedDate " + clazz;
+				}
+
+				if(this.isDisabledDate(date, this.lang)){
+					clazz = "dijitCalendarDisabledDate " + clazz;
+				}
+
+				var clazz2 = this.getClassForDate(date, this.lang);
+				if(clazz2){
+					clazz = clazz2 + " " + clazz;
+				}
+
+				template.className =  clazz + "Month dijitCalendarDateTemplate";
+				template.dijitDateValue = date.valueOf();
+				var label = dojo.query(".dijitCalendarDateLabel", template)[0];
+				this._setText(label, date.getDate());
+			}, this);
+
+			// Fill in localized month name
+			var monthNames = dojo.date.locale.getNames('months', 'wide', 'standAlone', this.lang);
+			this._setText(this.monthLabelNode, monthNames[month.getMonth()]);
+
+			// Fill in localized prev/current/next years
+			var y = month.getFullYear() - 1;
+			var d = new Date();
+			dojo.forEach(["previous", "current", "next"], function(name){
+				d.setFullYear(y++);
+				this._setText(this[name+"YearLabelNode"],
+					dojo.date.locale.format(d, {selector:'year', locale:this.lang}));
+			}, this);
+
+			// Set up repeating mouse behavior
+			var _this = this;
+			var typematic = function(nodeProp, dateProp, adj){
+				_this._connects.push(
+					dijit.typematic.addMouseListener(_this[nodeProp], _this, function(count){
+						if(count >= 0){ _this._adjustDisplay(dateProp, adj); }
+					}, 0.8, 500)
+				);
+			};
+			typematic("incrementMonth", "month", 1);
+			typematic("decrementMonth", "month", -1);
+			typematic("nextYearLabelNode", "year", 1);
+			typematic("previousYearLabelNode", "year", -1);
+		},
+
+		goToToday: function(){
+			// summary:
+			//      Sets calendar's value to today's date
+			this.attr('value', new Date());
+		},
+
+		postCreate: function(){
+			this.inherited(arguments);
+			dojo.setSelectable(this.domNode, false);
+
+			var cloneClass = dojo.hitch(this, function(clazz, n){
+				var template = dojo.query(clazz, this.domNode)[0];
+	 			for(var i=0; i<n; i++){
+					template.parentNode.appendChild(template.cloneNode(true));
+				}
+			});
+
+			// clone the day label and calendar day templates 6 times to make 7 columns
+			cloneClass(".dijitCalendarDayLabelTemplate", 6);
+			cloneClass(".dijitCalendarDateTemplate", 6);
+
+			// now make 6 week rows
+			cloneClass(".dijitCalendarWeekTemplate", 5);
+
+			// insert localized day names in the header
+			var dayNames = dojo.date.locale.getNames('days', this.dayWidth, 'standAlone', this.lang);
+			var dayOffset = dojo.cldr.supplemental.getFirstDayOfWeek(this.lang);
+			dojo.query(".dijitCalendarDayLabel", this.domNode).forEach(function(label, i){
+				this._setText(label, dayNames[(i + dayOffset) % 7]);
+			}, this);
+
+			// Fill in spacer element with all the month names (invisible) so that the maximum width will affect layout
+			var monthNames = dojo.date.locale.getNames('months', 'wide', 'standAlone', this.lang);
+			dojo.forEach(monthNames, function(name){
+				var monthSpacer = dojo.create("div", null, this.monthLabelSpacer);
+				this._setText(monthSpacer, name);
+			}, this);
+
+			this.value = null;
+			this.attr('value', new Date());
+		},
+
+		_adjustDisplay: function(/*String*/ part, /*int*/ amount){
+			// summary:
+			//      Moves calendar forwards or backwards by months or years
+			// part:
+			//      "month" or "year"
+			// amount:
+			//      Number of months or years
+			// tags:
+			//      private
+			this.displayMonth = dojo.date.add(this.displayMonth, part, amount);
+			this._populateGrid();
+		},
+
+		_onDayClick: function(/*Event*/ evt){
+			// summary:
+			//      Handler for when user clicks a day
+			// tags:
+			//      protected
+			dojo.stopEvent(evt);
+			for(var node = evt.target; node && !node.dijitDateValue; node = node.parentNode);
+			if(node && !dojo.hasClass(node, "dijitCalendarDisabledDate")){
+				this.attr('value', node.dijitDateValue);
+				this.onValueSelected(this.attr('value'));
+			}
+		},
+
+		_onDayMouseOver: function(/*Event*/ evt){
+			// summary:
+			//      Handler for when user clicks a day
+			// tags:
+			//      protected
+			var node = evt.target;
+			if(node && (node.dijitDateValue || node == this.previousYearLabelNode || node == this.nextYearLabelNode) ){
+				dojo.addClass(node, "dijitCalendarHoveredDate");
+				this._currentNode = node;
+			}
+		},
+
+		_onDayMouseOut: function(/*Event*/ evt){
+			// summary:
+			//      Handler for when user clicks a day
+			// tags:
+			//      protected
+			if(!this._currentNode){ return; }
+			for(var node = evt.relatedTarget; node;){
+				if(node == this._currentNode){ return; }
+				try{
+					node = node.parentNode;
+				}catch(x){
+					node = null;
+				}
+			}
+			dojo.removeClass(this._currentNode, "dijitCalendarHoveredDate");
+			this._currentNode = null;
+		},
+
+		onValueSelected: function(/*Date*/ date){
+			// summary:
+			//		Notification that a date cell was selected.  It may be the same as the previous value.
+			// description:
+			//      Used by `dijit.form._DateTimeTextBox` (and thus `dijit.form.DateTextBox`)
+			//      to get notification when the user has clicked a date.
+			// tags:
+			//      protected
+		},
+
+		onChange: function(/*Date*/ date){
+			// summary:
+			//		Called only when the selected date has changed
+		},
+
+		isDisabledDate: function(/*Date*/ dateObject, /*String?*/ locale){
+			// summary:
+			//		May be overridden to disable certain dates in the calendar e.g. `isDisabledDate=dojo.date.locale.isWeekend`
+			// tags:
+			//      extension
+/*=====
+			return false; // Boolean
+=====*/
+		},
+
+		getClassForDate: function(/*Date*/ dateObject, /*String?*/ locale){
+			// summary:
+			//		May be overridden to return CSS classes to associate with the date entry for the given dateObject,
+			//		for example to indicate a holiday in specified locale.
+			// tags:
+			//      extension
+
+/*=====
+			return ""; // String
+=====*/
+		}
+	}
+);
+
+}
+
+if(!dojo._hasResource["dojo.dnd.common"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.dnd.common"] = true;
+dojo.provide("dojo.dnd.common");
+
+dojo.dnd._isMac = navigator.appVersion.indexOf("Macintosh") >= 0;
+dojo.dnd._copyKey = dojo.dnd._isMac ? "metaKey" : "ctrlKey";
+
+dojo.dnd.getCopyKeyState = function(e) {
+	// summary: abstracts away the difference between selection on Mac and PC,
+	//	and returns the state of the "copy" key to be pressed.
+	// e: Event: mouse event
+	return e[dojo.dnd._copyKey];	// Boolean
+};
+
+dojo.dnd._uniqueId = 0;
+dojo.dnd.getUniqueId = function(){
+	// summary: returns a unique string for use with any DOM element
+	var id;
+	do{
+		id = dojo._scopeName + "Unique" + (++dojo.dnd._uniqueId);
+	}while(dojo.byId(id));
+	return id;
+};
+
+dojo.dnd._empty = {};
+
+dojo.dnd.isFormElement = function(/*Event*/ e){
+	// summary: returns true, if user clicked on a form element
+	var t = e.target;
+	if(t.nodeType == 3 /*TEXT_NODE*/){
+		t = t.parentNode;
+	}
+	return " button textarea input select option ".indexOf(" " + t.tagName.toLowerCase() + " ") >= 0;	// Boolean
+};
+
+// doesn't take into account when multiple buttons are pressed
+dojo.dnd._lmb = dojo.isIE ? 1 : 0;	// left mouse button
+
+dojo.dnd._isLmbPressed = dojo.isIE ?
+	function(e){ return e.button & 1; } : // intentional bit-and
+	function(e){ return e.button === 0; };
+
+}
+
+if(!dojo._hasResource["dojo.dnd.autoscroll"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.dnd.autoscroll"] = true;
+dojo.provide("dojo.dnd.autoscroll");
+
+dojo.dnd.getViewport = function(){
+	// summary: returns a viewport size (visible part of the window)
+
+	// FIXME: need more docs!!
+	var d = dojo.doc, dd = d.documentElement, w = window, b = dojo.body();
+	if(dojo.isMozilla){
+		return {w: dd.clientWidth, h: w.innerHeight};	// Object
+	}else if(!dojo.isOpera && w.innerWidth){
+		return {w: w.innerWidth, h: w.innerHeight};		// Object
+	}else if (!dojo.isOpera && dd && dd.clientWidth){
+		return {w: dd.clientWidth, h: dd.clientHeight};	// Object
+	}else if (b.clientWidth){
+		return {w: b.clientWidth, h: b.clientHeight};	// Object
+	}
+	return null;	// Object
+};
+
+dojo.dnd.V_TRIGGER_AUTOSCROLL = 32;
+dojo.dnd.H_TRIGGER_AUTOSCROLL = 32;
+
+dojo.dnd.V_AUTOSCROLL_VALUE = 16;
+dojo.dnd.H_AUTOSCROLL_VALUE = 16;
+
+dojo.dnd.autoScroll = function(e){
+	// summary:
+	//		a handler for onmousemove event, which scrolls the window, if
+	//		necesary
+	// e: Event:
+	//		onmousemove event
+
+	// FIXME: needs more docs!
+	var v = dojo.dnd.getViewport(), dx = 0, dy = 0;
+	if(e.clientX < dojo.dnd.H_TRIGGER_AUTOSCROLL){
+		dx = -dojo.dnd.H_AUTOSCROLL_VALUE;
+	}else if(e.clientX > v.w - dojo.dnd.H_TRIGGER_AUTOSCROLL){
+		dx = dojo.dnd.H_AUTOSCROLL_VALUE;
+	}
+	if(e.clientY < dojo.dnd.V_TRIGGER_AUTOSCROLL){
+		dy = -dojo.dnd.V_AUTOSCROLL_VALUE;
+	}else if(e.clientY > v.h - dojo.dnd.V_TRIGGER_AUTOSCROLL){
+		dy = dojo.dnd.V_AUTOSCROLL_VALUE;
+	}
+	window.scrollBy(dx, dy);
+};
+
+dojo.dnd._validNodes = {"div": 1, "p": 1, "td": 1};
+dojo.dnd._validOverflow = {"auto": 1, "scroll": 1};
+
+dojo.dnd.autoScrollNodes = function(e){
+	// summary:
+	//		a handler for onmousemove event, which scrolls the first avaialble
+	//		Dom element, it falls back to dojo.dnd.autoScroll()
+	// e: Event:
+	//		onmousemove event
+
+	// FIXME: needs more docs!
+	for(var n = e.target; n;){
+		if(n.nodeType == 1 && (n.tagName.toLowerCase() in dojo.dnd._validNodes)){
+			var s = dojo.getComputedStyle(n);
+			if(s.overflow.toLowerCase() in dojo.dnd._validOverflow){
+				var b = dojo._getContentBox(n, s), t = dojo._abs(n, true);
+				//
+				var w = Math.min(dojo.dnd.H_TRIGGER_AUTOSCROLL, b.w / 2), 
+					h = Math.min(dojo.dnd.V_TRIGGER_AUTOSCROLL, b.h / 2),
+					rx = e.pageX - t.x, ry = e.pageY - t.y, dx = 0, dy = 0;
+				if(dojo.isWebKit || dojo.isOpera){
+					// FIXME: this code should not be here, it should be taken into account 
+					// either by the event fixing code, or the dojo._abs()
+					// FIXME: this code doesn't work on Opera 9.5 Beta
+					rx += dojo.body().scrollLeft, ry += dojo.body().scrollTop;
+				}
+				if(rx > 0 && rx < b.w){
+					if(rx < w){
+						dx = -w;
+					}else if(rx > b.w - w){
+						dx = w;
+					}
+				}
+				//
+				if(ry > 0 && ry < b.h){
+					if(ry < h){
+						dy = -h;
+					}else if(ry > b.h - h){
+						dy = h;
+					}
+				}
+				var oldLeft = n.scrollLeft, oldTop = n.scrollTop;
+				n.scrollLeft = n.scrollLeft + dx;
+				n.scrollTop  = n.scrollTop  + dy;
+				if(oldLeft != n.scrollLeft || oldTop != n.scrollTop){ return; }
+			}
+		}
+		try{
+			n = n.parentNode;
+		}catch(x){
+			n = null;
+		}
+	}
+	dojo.dnd.autoScroll(e);
+};
+
+}
+
+if(!dojo._hasResource["dojo.dnd.Mover"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.dnd.Mover"] = true;
+dojo.provide("dojo.dnd.Mover");
+
+
+
+
+dojo.declare("dojo.dnd.Mover", null, {
+	constructor: function(node, e, host){
+		// summary: an object, which makes a node follow the mouse, 
+		//	used as a default mover, and as a base class for custom movers
+		// node: Node: a node (or node's id) to be moved
+		// e: Event: a mouse event, which started the move;
+		//	only pageX and pageY properties are used
+		// host: Object?: object which implements the functionality of the move,
+		//	 and defines proper events (onMoveStart and onMoveStop)
+		this.node = dojo.byId(node);
+		this.marginBox = {l: e.pageX, t: e.pageY};
+		this.mouseButton = e.button;
+		var h = this.host = host, d = node.ownerDocument, 
+			firstEvent = dojo.connect(d, "onmousemove", this, "onFirstMove");
+		this.events = [
+			dojo.connect(d, "onmousemove", this, "onMouseMove"),
+			dojo.connect(d, "onmouseup",   this, "onMouseUp"),
+			// cancel text selection and text dragging
+			dojo.connect(d, "ondragstart",   dojo.stopEvent),
+			dojo.connect(d.body, "onselectstart", dojo.stopEvent),
+			firstEvent
+		];
+		// notify that the move has started
+		if(h && h.onMoveStart){
+			h.onMoveStart(this);
+		}
+	},
+	// mouse event processors
+	onMouseMove: function(e){
+		// summary: event processor for onmousemove
+		// e: Event: mouse event
+		dojo.dnd.autoScroll(e);
+		var m = this.marginBox;
+		this.host.onMove(this, {l: m.l + e.pageX, t: m.t + e.pageY});
+		dojo.stopEvent(e);
+	},
+	onMouseUp: function(e){
+		if(dojo.isWebKit && dojo.dnd._isMac && this.mouseButton == 2 ? 
+				e.button == 0 : this.mouseButton == e.button){
+			this.destroy();
+		}
+		dojo.stopEvent(e);
+	},
+	// utilities
+	onFirstMove: function(){
+		// summary: makes the node absolute; it is meant to be called only once. 
+		// 	relative and absolutely positioned nodes are assumed to use pixel units
+		var s = this.node.style, l, t, h = this.host;
+		switch(s.position){
+			case "relative":
+			case "absolute":
+				// assume that left and top values are in pixels already
+				l = Math.round(parseFloat(s.left));
+				t = Math.round(parseFloat(s.top));
+				break;
+			default:
+				s.position = "absolute";	// enforcing the absolute mode
+				var m = dojo.marginBox(this.node);
+				// event.pageX/pageY (which we used to generate the initial
+				// margin box) includes padding and margin set on the body.
+				// However, setting the node's position to absolute and then
+				// doing dojo.marginBox on it *doesn't* take that additional
+				// space into account - so we need to subtract the combined
+				// padding and margin.  We use getComputedStyle and
+				// _getMarginBox/_getContentBox to avoid the extra lookup of
+				// the computed style. 
+				var b = dojo.doc.body;
+				var bs = dojo.getComputedStyle(b);
+				var bm = dojo._getMarginBox(b, bs);
+				var bc = dojo._getContentBox(b, bs);
+				l = m.l - (bc.l - bm.l);
+				t = m.t - (bc.t - bm.t);
+				break;
+		}
+		this.marginBox.l = l - this.marginBox.l;
+		this.marginBox.t = t - this.marginBox.t;
+		if(h && h.onFirstMove){
+			h.onFirstMove(this);
+		}
+		dojo.disconnect(this.events.pop());
+	},
+	destroy: function(){
+		// summary: stops the move, deletes all references, so the object can be garbage-collected
+		dojo.forEach(this.events, dojo.disconnect);
+		// undo global settings
+		var h = this.host;
+		if(h && h.onMoveStop){
+			h.onMoveStop(this);
+		}
+		// destroy objects
+		this.events = this.node = this.host = null;
+	}
+});
+
+}
+
+if(!dojo._hasResource["dojo.dnd.Moveable"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.dnd.Moveable"] = true;
+dojo.provide("dojo.dnd.Moveable");
+
+
+
+dojo.declare("dojo.dnd.Moveable", null, {
+	// object attributes (for markup)
+	handle: "",
+	delay: 0,
+	skip: false,
+	
+	constructor: function(node, params){
+		// summary: an object, which makes a node moveable
+		// node: Node: a node (or node's id) to be moved
+		// params: Object: an optional object with additional parameters;
+		//	following parameters are recognized:
+		//		handle: Node: a node (or node's id), which is used as a mouse handle
+		//			if omitted, the node itself is used as a handle
+		//		delay: Number: delay move by this number of pixels
+		//		skip: Boolean: skip move of form elements
+		//		mover: Object: a constructor of custom Mover
+		this.node = dojo.byId(node);
+		if(!params){ params = {}; }
+		this.handle = params.handle ? dojo.byId(params.handle) : null;
+		if(!this.handle){ this.handle = this.node; }
+		this.delay = params.delay > 0 ? params.delay : 0;
+		this.skip  = params.skip;
+		this.mover = params.mover ? params.mover : dojo.dnd.Mover;
+		this.events = [
+			dojo.connect(this.handle, "onmousedown", this, "onMouseDown"),
+			// cancel text selection and text dragging
+			dojo.connect(this.handle, "ondragstart",   this, "onSelectStart"),
+			dojo.connect(this.handle, "onselectstart", this, "onSelectStart")
+		];
+	},
+
+	// markup methods
+	markupFactory: function(params, node){
+		return new dojo.dnd.Moveable(node, params);
+	},
+
+	// methods
+	destroy: function(){
+		// summary: stops watching for possible move, deletes all references, so the object can be garbage-collected
+		dojo.forEach(this.events, dojo.disconnect);
+		this.events = this.node = this.handle = null;
+	},
+	
+	// mouse event processors
+	onMouseDown: function(e){
+		// summary: event processor for onmousedown, creates a Mover for the node
+		// e: Event: mouse event
+		if(this.skip && dojo.dnd.isFormElement(e)){ return; }
+		if(this.delay){
+			this.events.push(
+				dojo.connect(this.handle, "onmousemove", this, "onMouseMove"),
+				dojo.connect(this.handle, "onmouseup", this, "onMouseUp")
+			);
+			this._lastX = e.pageX;
+			this._lastY = e.pageY;
+		}else{
+			this.onDragDetected(e);
+		}
+		dojo.stopEvent(e);
+	},
+	onMouseMove: function(e){
+		// summary: event processor for onmousemove, used only for delayed drags
+		// e: Event: mouse event
+		if(Math.abs(e.pageX - this._lastX) > this.delay || Math.abs(e.pageY - this._lastY) > this.delay){
+			this.onMouseUp(e);
+			this.onDragDetected(e);
+		}
+		dojo.stopEvent(e);
+	},
+	onMouseUp: function(e){
+		// summary: event processor for onmouseup, used only for delayed drags
+		// e: Event: mouse event
+		for(var i = 0; i < 2; ++i){
+			dojo.disconnect(this.events.pop());
+		}
+		dojo.stopEvent(e);
+	},
+	onSelectStart: function(e){
+		// summary: event processor for onselectevent and ondragevent
+		// e: Event: mouse event
+		if(!this.skip || !dojo.dnd.isFormElement(e)){
+			dojo.stopEvent(e);
+		}
+	},
+	
+	// local events
+	onDragDetected: function(/* Event */ e){
+		// summary: called when the drag is detected,
+		// responsible for creation of the mover
+		new this.mover(this.node, e, this);
+	},
+	onMoveStart: function(/* dojo.dnd.Mover */ mover){
+		// summary: called before every move operation
+		dojo.publish("/dnd/move/start", [mover]);
+		dojo.addClass(dojo.body(), "dojoMove"); 
+		dojo.addClass(this.node, "dojoMoveItem"); 
+	},
+	onMoveStop: function(/* dojo.dnd.Mover */ mover){
+		// summary: called after every move operation
+		dojo.publish("/dnd/move/stop", [mover]);
+		dojo.removeClass(dojo.body(), "dojoMove");
+		dojo.removeClass(this.node, "dojoMoveItem");
+	},
+	onFirstMove: function(/* dojo.dnd.Mover */ mover){
+		// summary: called during the very first move notification,
+		//	can be used to initialize coordinates, can be overwritten.
+		
+		// default implementation does nothing
+	},
+	onMove: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop){
+		// summary: called during every move notification,
+		//	should actually move the node, can be overwritten.
+		this.onMoving(mover, leftTop);
+		var s = mover.node.style;
+		s.left = leftTop.l + "px";
+		s.top  = leftTop.t + "px";
+		this.onMoved(mover, leftTop);
+	},
+	onMoving: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop){
+		// summary: called before every incremental move,
+		//	can be overwritten.
+		
+		// default implementation does nothing
+	},
+	onMoved: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop){
+		// summary: called after every incremental move,
+		//	can be overwritten.
+		
+		// default implementation does nothing
+	}
+});
+
+}
+
+if(!dojo._hasResource["dojo.dnd.move"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.dnd.move"] = true;
+dojo.provide("dojo.dnd.move");
+
+
+
+
+dojo.declare("dojo.dnd.move.constrainedMoveable", dojo.dnd.Moveable, {
+	// object attributes (for markup)
+	constraints: function(){},
+	within: false,
+	
+	// markup methods
+	markupFactory: function(params, node){
+		return new dojo.dnd.move.constrainedMoveable(node, params);
+	},
+
+	constructor: function(node, params){
+		// summary: an object, which makes a node moveable
+		// node: Node: a node (or node's id) to be moved
+		// params: Object: an optional object with additional parameters;
+		//	following parameters are recognized:
+		//		constraints: Function: a function, which calculates a constraint box,
+		//			it is called in a context of the moveable object.
+		//		within: Boolean: restrict move within boundaries.
+		//	the rest is passed to the base class
+		if(!params){ params = {}; }
+		this.constraints = params.constraints;
+		this.within = params.within;
+	},
+	onFirstMove: function(/* dojo.dnd.Mover */ mover){
+		// summary: called during the very first move notification,
+		//	can be used to initialize coordinates, can be overwritten.
+		var c = this.constraintBox = this.constraints.call(this, mover);
+		c.r = c.l + c.w;
+		c.b = c.t + c.h;
+		if(this.within){
+			var mb = dojo.marginBox(mover.node);
+			c.r -= mb.w;
+			c.b -= mb.h;
+		}
+	},
+	onMove: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop){
+		// summary: called during every move notification,
+		//	should actually move the node, can be overwritten.
+		var c = this.constraintBox, s = mover.node.style;
+		s.left = (leftTop.l < c.l ? c.l : c.r < leftTop.l ? c.r : leftTop.l) + "px";
+		s.top  = (leftTop.t < c.t ? c.t : c.b < leftTop.t ? c.b : leftTop.t) + "px";
+	}
+});
+
+dojo.declare("dojo.dnd.move.boxConstrainedMoveable", dojo.dnd.move.constrainedMoveable, {
+	// object attributes (for markup)
+	box: {},
+	
+	// markup methods
+	markupFactory: function(params, node){
+		return new dojo.dnd.move.boxConstrainedMoveable(node, params);
+	},
+
+	constructor: function(node, params){
+		// summary: an object, which makes a node moveable
+		// node: Node: a node (or node's id) to be moved
+		// params: Object: an optional object with additional parameters;
+		//	following parameters are recognized:
+		//		box: Object: a constraint box
+		//	the rest is passed to the base class
+		var box = params && params.box;
+		this.constraints = function(){ return box; };
+	}
+});
+
+dojo.declare("dojo.dnd.move.parentConstrainedMoveable", dojo.dnd.move.constrainedMoveable, {
+	// object attributes (for markup)
+	area: "content",
+
+	// markup methods
+	markupFactory: function(params, node){
+		return new dojo.dnd.move.parentConstrainedMoveable(node, params);
+	},
+
+	constructor: function(node, params){
+		// summary: an object, which makes a node moveable
+		// node: Node: a node (or node's id) to be moved
+		// params: Object: an optional object with additional parameters;
+		//	following parameters are recognized:
+		//		area: String: a parent's area to restrict the move,
+		//			can be "margin", "border", "padding", or "content".
+		//	the rest is passed to the base class
+		var area = params && params.area;
+		this.constraints = function(){
+			var n = this.node.parentNode, 
+				s = dojo.getComputedStyle(n), 
+				mb = dojo._getMarginBox(n, s);
+			if(area == "margin"){
+				return mb;	// Object
+			}
+			var t = dojo._getMarginExtents(n, s);
+			mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;
+			if(area == "border"){
+				return mb;	// Object
+			}
+			t = dojo._getBorderExtents(n, s);
+			mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;
+			if(area == "padding"){
+				return mb;	// Object
+			}
+			t = dojo._getPadExtents(n, s);
+			mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;
+			return mb;	// Object
+		};
+	}
+});
+
+// WARNING: below are obsolete objects, instead of custom movers use custom moveables (above)
+
+dojo.dnd.move.constrainedMover = function(fun, within){
+	// summary: returns a constrained version of dojo.dnd.Mover
+	// description: this function produces n object, which will put a constraint on 
+	//	the margin box of dragged object in absolute coordinates
+	// fun: Function: called on drag, and returns a constraint box
+	// within: Boolean: if true, constraints the whole dragged object withtin the rectangle, 
+	//	otherwise the constraint is applied to the left-top corner
+	dojo.deprecated("dojo.dnd.move.constrainedMover, use dojo.dnd.move.constrainedMoveable instead");
+	var mover = function(node, e, notifier){
+		dojo.dnd.Mover.call(this, node, e, notifier);
+	};
+	dojo.extend(mover, dojo.dnd.Mover.prototype);
+	dojo.extend(mover, {
+		onMouseMove: function(e){
+			// summary: event processor for onmousemove
+			// e: Event: mouse event
+			dojo.dnd.autoScroll(e);
+			var m = this.marginBox, c = this.constraintBox,
+				l = m.l + e.pageX, t = m.t + e.pageY;
+			l = l < c.l ? c.l : c.r < l ? c.r : l;
+			t = t < c.t ? c.t : c.b < t ? c.b : t;
+			this.host.onMove(this, {l: l, t: t});
+		},
+		onFirstMove: function(){
+			// summary: called once to initialize things; it is meant to be called only once
+			dojo.dnd.Mover.prototype.onFirstMove.call(this);
+			var c = this.constraintBox = fun.call(this);
+			c.r = c.l + c.w;
+			c.b = c.t + c.h;
+			if(within){
+				var mb = dojo.marginBox(this.node);
+				c.r -= mb.w;
+				c.b -= mb.h;
+			}
+		}
+	});
+	return mover;	// Object
+};
+
+dojo.dnd.move.boxConstrainedMover = function(box, within){
+	// summary: a specialization of dojo.dnd.constrainedMover, which constrains to the specified box
+	// box: Object: a constraint box (l, t, w, h)
+	// within: Boolean: if true, constraints the whole dragged object withtin the rectangle, 
+	//	otherwise the constraint is applied to the left-top corner
+	dojo.deprecated("dojo.dnd.move.boxConstrainedMover, use dojo.dnd.move.boxConstrainedMoveable instead");
+	return dojo.dnd.move.constrainedMover(function(){ return box; }, within);	// Object
+};
+
+dojo.dnd.move.parentConstrainedMover = function(area, within){
+	// summary: a specialization of dojo.dnd.constrainedMover, which constrains to the parent node
+	// area: String: "margin" to constrain within the parent's margin box, "border" for the border box,
+	//	"padding" for the padding box, and "content" for the content box; "content" is the default value.
+	// within: Boolean: if true, constraints the whole dragged object withtin the rectangle, 
+	//	otherwise the constraint is applied to the left-top corner
+	dojo.deprecated("dojo.dnd.move.parentConstrainedMover, use dojo.dnd.move.parentConstrainedMoveable instead");
+	var fun = function(){
+		var n = this.node.parentNode, 
+			s = dojo.getComputedStyle(n), 
+			mb = dojo._getMarginBox(n, s);
+		if(area == "margin"){
+			return mb;	// Object
+		}
+		var t = dojo._getMarginExtents(n, s);
+		mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;
+		if(area == "border"){
+			return mb;	// Object
+		}
+		t = dojo._getBorderExtents(n, s);
+		mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;
+		if(area == "padding"){
+			return mb;	// Object
+		}
+		t = dojo._getPadExtents(n, s);
+		mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;
+		return mb;	// Object
+	};
+	return dojo.dnd.move.constrainedMover(fun, within);	// Object
+};
+
+// patching functions one level up for compatibility
+
+dojo.dnd.constrainedMover = dojo.dnd.move.constrainedMover;
+dojo.dnd.boxConstrainedMover = dojo.dnd.move.boxConstrainedMover;
+dojo.dnd.parentConstrainedMover = dojo.dnd.move.parentConstrainedMover;
+
+}
+
+if(!dojo._hasResource["dojo.dnd.TimedMoveable"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.dnd.TimedMoveable"] = true;
+dojo.provide("dojo.dnd.TimedMoveable");
+
+
+
+(function(){
+	// precalculate long expressions
+	var oldOnMove = dojo.dnd.Moveable.prototype.onMove;
+		
+	dojo.declare("dojo.dnd.TimedMoveable", dojo.dnd.Moveable, {
+		// summary:
+		//	A specialized version of Moveable to support an FPS throttling.
+		//	This class puts an upper restriction on FPS, which may reduce 
+		//	the CPU load. The additional parameter "timeout" regulates
+		//	the delay before actually moving the moveable object.
+		
+		// object attributes (for markup)
+		timeout: 40,	// in ms, 40ms corresponds to 25 fps
+	
+		constructor: function(node, params){
+			// summary: an object, which makes a node moveable with a timer
+			// node: Node: a node (or node's id) to be moved
+			// params: Object: an optional object with additional parameters.
+			//	See dojo.dnd.Moveable for details on general parameters.
+			//	Following parameters are specific for this class:
+			//		timeout: Number: delay move by this number of ms
+			//			accumulating position changes during the timeout
+			
+			// sanitize parameters
+			if(!params){ params = {}; }
+			if(params.timeout && typeof params.timeout == "number" && params.timeout >= 0){
+				this.timeout = params.timeout;
+			}
+		},
+	
+		// markup methods
+		markupFactory: function(params, node){
+			return new dojo.dnd.TimedMoveable(node, params);
+		},
+	
+		onMoveStop: function(/* dojo.dnd.Mover */ mover){
+			if(mover._timer){
+				// stop timer
+				clearTimeout(mover._timer)
+				// reflect the last received position
+				oldOnMove.call(this, mover, mover._leftTop)
+			}
+			dojo.dnd.Moveable.prototype.onMoveStop.apply(this, arguments);
+		},
+		onMove: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop){
+			mover._leftTop = leftTop;
+			if(!mover._timer){
+				var _t = this;	// to avoid using dojo.hitch()
+				mover._timer = setTimeout(function(){
+					// we don't have any pending requests
+					mover._timer = null;
+					// reflect the last received position
+					oldOnMove.call(_t, mover, mover._leftTop);
+				}, this.timeout);
+			}
+		}
+	});
+})();
+
+}
+
+if(!dojo._hasResource["dojo.fx.Toggler"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.fx.Toggler"] = true;
+dojo.provide("dojo.fx.Toggler");
+
+dojo.declare("dojo.fx.Toggler", null, {
+	// summary:
+	//		class constructor for an animation toggler. It accepts a packed
+	//		set of arguments about what type of animation to use in each
+	//		direction, duration, etc.
+	//
+	// example:
+	//	|	var t = new dojo.fx.Toggler({
+	//	|		node: "nodeId",
+	//	|		showDuration: 500,
+	//	|		// hideDuration will default to "200"
+	//	|		showFunc: dojo.wipeIn, 
+	//	|		// hideFunc will default to "fadeOut"
+	//	|	});
+	//	|	t.show(100); // delay showing for 100ms
+	//	|	// ...time passes...
+	//	|	t.hide();
+
+	// FIXME: need a policy for where the toggler should "be" the next
+	// time show/hide are called if we're stopped somewhere in the
+	// middle.
+
+	constructor: function(args){
+		var _t = this;
+
+		dojo.mixin(_t, args);
+		_t.node = args.node;
+		_t._showArgs = dojo.mixin({}, args);
+		_t._showArgs.node = _t.node;
+		_t._showArgs.duration = _t.showDuration;
+		_t.showAnim = _t.showFunc(_t._showArgs);
+
+		_t._hideArgs = dojo.mixin({}, args);
+		_t._hideArgs.node = _t.node;
+		_t._hideArgs.duration = _t.hideDuration;
+		_t.hideAnim = _t.hideFunc(_t._hideArgs);
+
+		dojo.connect(_t.showAnim, "beforeBegin", dojo.hitch(_t.hideAnim, "stop", true));
+		dojo.connect(_t.hideAnim, "beforeBegin", dojo.hitch(_t.showAnim, "stop", true));
+	},
+
+	// node: DomNode
+	//	the node to toggle
+	node: null,
+
+	// showFunc: Function
+	//	The function that returns the dojo._Animation to show the node
+	showFunc: dojo.fadeIn,
+
+	// hideFunc: Function	
+	//	The function that returns the dojo._Animation to hide the node
+	hideFunc: dojo.fadeOut,
+
+	// showDuration:
+	//	Time in milliseconds to run the show Animation
+	showDuration: 200,
+
+	// hideDuration:
+	//	Time in milliseconds to run the hide Animation
+	hideDuration: 200,
+
+	/*=====
+	_showArgs: null,
+	_showAnim: null,
+
+	_hideArgs: null,
+	_hideAnim: null,
+
+	_isShowing: false,
+	_isHiding: false,
+	=====*/
+
+	show: function(delay){
+		// summary: Toggle the node to showing
+		return this.showAnim.play(delay || 0);
+	},
+
+	hide: function(delay){
+		// summary: Toggle the node to hidden
+		return this.hideAnim.play(delay || 0);
+	}
+});
+
+}
+
+if(!dojo._hasResource["dojo.fx"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.fx"] = true;
+dojo.provide("dojo.fx");
+
+/*=====
+dojo.fx = {
+	// summary: Effects library on top of Base animations
+};
+=====*/
+(function(){
+	
+	var d = dojo, 
+		_baseObj = {
+			_fire: function(evt, args){
+				if(this[evt]){
+					this[evt].apply(this, args||[]);
+				}
+				return this;
+			}
+		};
+
+	var _chain = function(animations){
+		this._index = -1;
+		this._animations = animations||[];
+		this._current = this._onAnimateCtx = this._onEndCtx = null;
+
+		this.duration = 0;
+		d.forEach(this._animations, function(a){
+			this.duration += a.duration;
+			if(a.delay){ this.duration += a.delay; }
+		}, this);
+	};
+	d.extend(_chain, {
+		_onAnimate: function(){
+			this._fire("onAnimate", arguments);
+		},
+		_onEnd: function(){
+			d.disconnect(this._onAnimateCtx);
+			d.disconnect(this._onEndCtx);
+			this._onAnimateCtx = this._onEndCtx = null;
+			if(this._index + 1 == this._animations.length){
+				this._fire("onEnd");
+			}else{
+				// switch animations
+				this._current = this._animations[++this._index];
+				this._onAnimateCtx = d.connect(this._current, "onAnimate", this, "_onAnimate");
+				this._onEndCtx = d.connect(this._current, "onEnd", this, "_onEnd");
+				this._current.play(0, true);
+			}
+		},
+		play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){
+			if(!this._current){ this._current = this._animations[this._index = 0]; }
+			if(!gotoStart && this._current.status() == "playing"){ return this; }
+			var beforeBegin = d.connect(this._current, "beforeBegin", this, function(){
+					this._fire("beforeBegin");
+				}),
+				onBegin = d.connect(this._current, "onBegin", this, function(arg){
+					this._fire("onBegin", arguments);
+				}),
+				onPlay = d.connect(this._current, "onPlay", this, function(arg){
+					this._fire("onPlay", arguments);
+					d.disconnect(beforeBegin);
+					d.disconnect(onBegin);
+					d.disconnect(onPlay);
+				});
+			if(this._onAnimateCtx){
+				d.disconnect(this._onAnimateCtx);
+			}
+			this._onAnimateCtx = d.connect(this._current, "onAnimate", this, "_onAnimate");
+			if(this._onEndCtx){
+				d.disconnect(this._onEndCtx);
+			}
+			this._onEndCtx = d.connect(this._current, "onEnd", this, "_onEnd");
+			this._current.play.apply(this._current, arguments);
+			return this;
+		},
+		pause: function(){
+			if(this._current){
+				var e = d.connect(this._current, "onPause", this, function(arg){
+						this._fire("onPause", arguments);
+						d.disconnect(e);
+					});
+				this._current.pause();
+			}
+			return this;
+		},
+		gotoPercent: function(/*Decimal*/percent, /*Boolean?*/ andPlay){
+			this.pause();
+			var offset = this.duration * percent;
+			this._current = null;
+			d.some(this._animations, function(a){
+				if(a.duration <= offset){
+					this._current = a;
+					return true;
+				}
+				offset -= a.duration;
+				return false;
+			});
+			if(this._current){
+				this._current.gotoPercent(offset / this._current.duration, andPlay);
+			}
+			return this;
+		},
+		stop: function(/*boolean?*/ gotoEnd){
+			if(this._current){
+				if(gotoEnd){
+					for(; this._index + 1 < this._animations.length; ++this._index){
+						this._animations[this._index].stop(true);
+					}
+					this._current = this._animations[this._index];
+				}
+				var e = d.connect(this._current, "onStop", this, function(arg){
+						this._fire("onStop", arguments);
+						d.disconnect(e);
+					});
+				this._current.stop();
+			}
+			return this;
+		},
+		status: function(){
+			return this._current ? this._current.status() : "stopped";
+		},
+		destroy: function(){
+			if(this._onAnimateCtx){ d.disconnect(this._onAnimateCtx); }
+			if(this._onEndCtx){ d.disconnect(this._onEndCtx); }
+		}
+	});
+	d.extend(_chain, _baseObj);
+
+	dojo.fx.chain = function(/*dojo._Animation[]*/ animations){
+		// summary: Chain a list of dojo._Animation s to run in sequence
+		// example:
+		//	|	dojo.fx.chain([
+		//	|		dojo.fadeIn({ node:node }),
+		//	|		dojo.fadeOut({ node:otherNode })
+		//	|	]).play();
+		//
+		return new _chain(animations) // dojo._Animation
+	};
+
+	var _combine = function(animations){
+		this._animations = animations||[];
+		this._connects = [];
+		this._finished = 0;
+
+		this.duration = 0;
+		d.forEach(animations, function(a){
+			var duration = a.duration;
+			if(a.delay){ duration += a.delay; }
+			if(this.duration < duration){ this.duration = duration; }
+			this._connects.push(d.connect(a, "onEnd", this, "_onEnd"));
+		}, this);
+		
+		this._pseudoAnimation = new d._Animation({curve: [0, 1], duration: this.duration});
+		var self = this;
+		d.forEach(["beforeBegin", "onBegin", "onPlay", "onAnimate", "onPause", "onStop"], 
+			function(evt){
+				self._connects.push(d.connect(self._pseudoAnimation, evt,
+					function(){ self._fire(evt, arguments); }
+				));
+			}
+		);
+	};
+	d.extend(_combine, {
+		_doAction: function(action, args){
+			d.forEach(this._animations, function(a){
+				a[action].apply(a, args);
+			});
+			return this;
+		},
+		_onEnd: function(){
+			if(++this._finished == this._animations.length){
+				this._fire("onEnd");
+			}
+		},
+		_call: function(action, args){
+			var t = this._pseudoAnimation;
+			t[action].apply(t, args);
+		},
+		play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){
+			this._finished = 0;
+			this._doAction("play", arguments);
+			this._call("play", arguments);
+			return this;
+		},
+		pause: function(){
+			this._doAction("pause", arguments);
+			this._call("pause", arguments);
+			return this;
+		},
+		gotoPercent: function(/*Decimal*/percent, /*Boolean?*/ andPlay){
+			var ms = this.duration * percent;
+			d.forEach(this._animations, function(a){
+				a.gotoPercent(a.duration < ms ? 1 : (ms / a.duration), andPlay);
+			});
+			this._call("gotoPercent", arguments);
+			return this;
+		},
+		stop: function(/*boolean?*/ gotoEnd){
+			this._doAction("stop", arguments);
+			this._call("stop", arguments);
+			return this;
+		},
+		status: function(){
+			return this._pseudoAnimation.status();
+		},
+		destroy: function(){
+			d.forEach(this._connects, dojo.disconnect);
+		}
+	});
+	d.extend(_combine, _baseObj);
+
+	dojo.fx.combine = function(/*dojo._Animation[]*/ animations){
+		// summary: Combine an array of `dojo._Animation`s to run in parallel
+		//
+		// description:
+		//		Combine an array of `dojo._Animation`s to run in parallel, 
+		//		providing a new `dojo._Animation` instance encompasing each
+		//		animation, firing standard animation events.
+		//
+		// example:
+		//	|	dojo.fx.combine([
+		//	|		dojo.fadeIn({ node:node }),
+		//	|		dojo.fadeOut({ node:otherNode })
+		//	|	]).play();
+		//
+		// example:
+		//	When the longest animation ends, execute a function:
+		//	| 	var anim = dojo.fx.combine([
+		//	|		dojo.fadeIn({ node: n, duration:700 }),
+		//	|		dojo.fadeOut({ node: otherNode, duration: 300 })
+		//	|	]);
+		//	|	dojo.connect(anim, "onEnd", function(){
+		//	|		// overall animation is done.
+		//	|	});
+		//	|	anim.play(); // play the animation
+		//
+		return new _combine(animations); // dojo._Animation
+	};
+
+	dojo.fx.wipeIn = function(/*Object*/ args){
+		// summary:
+		//		Returns an animation that will expand the
+		//		node defined in 'args' object from it's current height to
+		//		it's natural height (with no scrollbar).
+		//		Node must have no margin/border/padding.
+		args.node = d.byId(args.node);
+		var node = args.node, s = node.style, o;
+
+		var anim = d.animateProperty(d.mixin({
+			properties: {
+				height: {
+					// wrapped in functions so we wait till the last second to query (in case value has changed)
+					start: function(){
+						// start at current [computed] height, but use 1px rather than 0
+						// because 0 causes IE to display the whole panel
+						o = s.overflow;
+						s.overflow="hidden";
+						if(s.visibility=="hidden"||s.display=="none"){
+							s.height="1px";
+							s.display="";
+							s.visibility="";
+							return 1;
+						}else{
+							var height = d.style(node, "height");
+							return Math.max(height, 1);
+						}
+					},
+					end: function(){
+						return node.scrollHeight;
+					}
+				}
+			}
+		}, args));
+
+		d.connect(anim, "onEnd", function(){ 
+			s.height = "auto";
+			s.overflow = o;
+		});
+
+		return anim; // dojo._Animation
+	}
+
+	dojo.fx.wipeOut = function(/*Object*/ args){
+		// summary:
+		//		Returns an animation that will shrink node defined in "args"
+		//		from it's current height to 1px, and then hide it.
+		var node = args.node = d.byId(args.node), s = node.style, o;
+		
+		var anim = d.animateProperty(d.mixin({
+			properties: {
+				height: {
+					end: 1 // 0 causes IE to display the whole panel
+				}
+			}
+		}, args));
+
+		d.connect(anim, "beforeBegin", function(){
+			o = s.overflow;
+			s.overflow = "hidden";
+			s.display = "";
+		});
+		d.connect(anim, "onEnd", function(){
+			s.overflow = o;
+			s.height = "auto";
+			s.display = "none";
+		});
+
+		return anim; // dojo._Animation
+	}
+
+	dojo.fx.slideTo = function(/*Object?*/ args){
+		// summary:
+		//		Returns an animation that will slide "node" 
+		//		defined in args Object from its current position to
+		//		the position defined by (args.left, args.top).
+		// example:
+		//	|	dojo.fx.slideTo({ node: node, left:"40", top:"50", unit:"px" }).play()
+
+		var node = args.node = d.byId(args.node), 
+			top = null, left = null;
+
+		var init = (function(n){
+			return function(){
+				var cs = d.getComputedStyle(n);
+				var pos = cs.position;
+				top = (pos == 'absolute' ? n.offsetTop : parseInt(cs.top) || 0);
+				left = (pos == 'absolute' ? n.offsetLeft : parseInt(cs.left) || 0);
+				if(pos != 'absolute' && pos != 'relative'){
+					var ret = d.coords(n, true);
+					top = ret.y;
+					left = ret.x;
+					n.style.position="absolute";
+					n.style.top=top+"px";
+					n.style.left=left+"px";
+				}
+			};
+		})(node);
+		init();
+
+		var anim = d.animateProperty(d.mixin({
+			properties: {
+				top: args.top || 0,
+				left: args.left || 0
+			}
+		}, args));
+		d.connect(anim, "beforeBegin", anim, init);
+
+		return anim; // dojo._Animation
+	}
+
+})();
+
+}
+
+if(!dojo._hasResource["dijit.form._FormMixin"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form._FormMixin"] = true;
+dojo.provide("dijit.form._FormMixin");
+
+dojo.declare("dijit.form._FormMixin", null,
+	{
+	// summary:
+	//		Mixin for containers of form widgets (i.e. widgets that represent a single value
+	//		and can be children of a <form> node or dijit.form.Form widget)
+	// description:
+	//		Can extract all the form widgets
+	//		values and combine them into a single javascript object, or alternately
+	//		take such an object and set the values for all the contained
+	//		form widgets
+
+/*=====
+    // value: Object
+	//		Name/value hash for each form element.
+	//		If there are multiple elements w/the same name, value is an array,
+	//		unless they are radio buttons in which case value is a scalar since only
+	//		one can be checked at a time.
+	//
+	//		If the name is a dot separated list (like a.b.c.d), it's a nested structure.
+	//		Only works on widget form elements.
+	// example:
+	//	| { name: "John Smith", interests: ["sports", "movies"] }
+=====*/
+	
+	//	TODO:
+	//	* Repeater
+	//	* better handling for arrays.  Often form elements have names with [] like
+	//	* people[3].sex (for a list of people [{name: Bill, sex: M}, ...])
+	//
+	//	
+
+		reset: function(){
+			dojo.forEach(this.getDescendants(), function(widget){
+				if(widget.reset){
+					widget.reset();
+				}
+			});
+		},
+
+		validate: function(){
+			// summary: returns if the form is valid - same as isValid - but
+			//			provides a few additional (ui-specific) features.
+			//			1 - it will highlight any sub-widgets that are not
+			//				valid
+			//			2 - it will call focus() on the first invalid 
+			//				sub-widget
+			var didFocus = false;
+			return dojo.every(dojo.map(this.getDescendants(), function(widget){
+				// Need to set this so that "required" widgets get their 
+				// state set.
+				widget._hasBeenBlurred = true;
+				var valid = widget.disabled || !widget.validate || widget.validate();
+				if (!valid && !didFocus) {
+					// Set focus of the first non-valid widget
+					dijit.scrollIntoView(widget.containerNode||widget.domNode);
+					widget.focus();
+					didFocus = true;
+				}
+	 			return valid;
+	 		}), function(item) { return item; });
+		},
+	
+		setValues: function(val){
+			dojo.deprecated(this.declaredClass+"::setValues() is deprecated. Use attr('value', val) instead.", "", "2.0");
+			return this.attr('value', val);
+		},
+		_setValueAttr: function(/*object*/obj){
+			// summary: Fill in form values from according to an Object (in the format returned by attr('value'))
+
+			// generate map from name --> [list of widgets with that name]
+			var map = { };
+			dojo.forEach(this.getDescendants(), function(widget){
+				if(!widget.name){ return; }
+				var entry = map[widget.name] || (map[widget.name] = [] );
+				entry.push(widget);
+			});
+
+			for(var name in map){
+				if(!map.hasOwnProperty(name)){
+					continue;
+				}
+				var widgets = map[name],						// array of widgets w/this name
+					values = dojo.getObject(name, false, obj);	// list of values for those widgets
+
+				if(values===undefined){
+					continue;
+				}
+				if(!dojo.isArray(values)){
+					values = [ values ];
+				}
+				if(typeof widgets[0].checked == 'boolean'){
+					// for checkbox/radio, values is a list of which widgets should be checked
+					dojo.forEach(widgets, function(w, i){
+						w.attr('value', dojo.indexOf(values, w.value) != -1);
+					});
+				}else if(widgets[0]._multiValue){
+					// it takes an array (e.g. multi-select)
+					widgets[0].attr('value', values);
+				}else{
+					// otherwise, values is a list of values to be assigned sequentially to each widget
+					dojo.forEach(widgets, function(w, i){
+						w.attr('value', values[i]);
+					});					
+				}
+			}
+
+			/***
+			 * 	TODO: code for plain input boxes (this shouldn't run for inputs that are part of widgets)
+
+			dojo.forEach(this.containerNode.elements, function(element){
+				if (element.name == ''){return};	// like "continue"	
+				var namePath = element.name.split(".");
+				var myObj=obj;
+				var name=namePath[namePath.length-1];
+				for(var j=1,len2=namePath.length;j<len2;++j){
+					var p=namePath[j - 1];
+					// repeater support block
+					var nameA=p.split("[");
+					if (nameA.length > 1){
+						if(typeof(myObj[nameA[0]]) == "undefined"){
+							myObj[nameA[0]]=[ ];
+						} // if
+
+						nameIndex=parseInt(nameA[1]);
+						if(typeof(myObj[nameA[0]][nameIndex]) == "undefined"){
+							myObj[nameA[0]][nameIndex] = { };
+						}
+						myObj=myObj[nameA[0]][nameIndex];
+						continue;
+					} // repeater support ends
+
+					if(typeof(myObj[p]) == "undefined"){
+						myObj=undefined;
+						break;
+					};
+					myObj=myObj[p];
+				}
+
+				if (typeof(myObj) == "undefined"){
+					return;		// like "continue"
+				}
+				if (typeof(myObj[name]) == "undefined" && this.ignoreNullValues){
+					return;		// like "continue"
+				}
+
+				// TODO: widget values (just call attr('value', ...) on the widget)
+
+				switch(element.type){
+					case "checkbox":
+						element.checked = (name in myObj) &&
+							dojo.some(myObj[name], function(val){ return val==element.value; });
+						break;
+					case "radio":
+						element.checked = (name in myObj) && myObj[name]==element.value;
+						break;
+					case "select-multiple":
+						element.selectedIndex=-1;
+						dojo.forEach(element.options, function(option){
+							option.selected = dojo.some(myObj[name], function(val){ return option.value == val; });
+						});
+						break;
+					case "select-one":
+						element.selectedIndex="0";
+						dojo.forEach(element.options, function(option){
+							option.selected = option.value == myObj[name];
+						});
+						break;
+					case "hidden":
+					case "text":
+					case "textarea":
+					case "password":
+						element.value = myObj[name] || "";
+						break;
+				}
+	  		});
+	  		*/
+		},
+
+		getValues: function(){
+			dojo.deprecated(this.declaredClass+"::getValues() is deprecated. Use attr('value') instead.", "", "2.0");
+			return this.attr('value');
+		},
+		_getValueAttr: function(){
+			// summary:
+			// 		Returns Object representing form values.
+			// description:
+			//		Returns name/value hash for each form element.
+			//		If there are multiple elements w/the same name, value is an array,
+			//		unless they are radio buttons in which case value is a scalar since only
+			//		one can be checked at a time.
+			//
+			//		If the name is a dot separated list (like a.b.c.d), creates a nested structure.
+			//		Only works on widget form elements.
+			// example:
+			//		| { name: "John Smith", interests: ["sports", "movies"] }
+
+			// get widget values
+			var obj = { };
+			dojo.forEach(this.getDescendants(), function(widget){
+				var name = widget.name;
+				if(!name||widget.disabled){ return; }
+
+				// Single value widget (checkbox, radio, or plain <input> type widget
+				var value = widget.attr('value');
+
+				// Store widget's value(s) as a scalar, except for checkboxes which are automatically arrays
+				if(typeof widget.checked == 'boolean'){
+					if(/Radio/.test(widget.declaredClass)){
+						// radio button
+						if(value !== false){
+							dojo.setObject(name, value, obj);
+						}else{
+							// give radio widgets a default of null
+							value = dojo.getObject(name, false, obj);
+							if(value === undefined){
+								dojo.setObject(name, null, obj);
+							}
+						}
+					}else{
+						// checkbox/toggle button
+						var ary=dojo.getObject(name, false, obj);
+						if(!ary){
+							ary=[];
+							dojo.setObject(name, ary, obj);
+						}
+						if(value !== false){
+							ary.push(value);
+						}
+					}
+				}else{
+					// plain input
+					dojo.setObject(name, value, obj);
+				}
+			});
+
+			/***
+			 * code for plain input boxes (see also dojo.formToObject, can we use that instead of this code?
+			 * but it doesn't understand [] notation, presumably)
+			var obj = { };
+			dojo.forEach(this.containerNode.elements, function(elm){
+				if (!elm.name)	{
+					return;		// like "continue"
+				}
+				var namePath = elm.name.split(".");
+				var myObj=obj;
+				var name=namePath[namePath.length-1];
+				for(var j=1,len2=namePath.length;j<len2;++j){
+					var nameIndex = null;
+					var p=namePath[j - 1];
+					var nameA=p.split("[");
+					if (nameA.length > 1){
+						if(typeof(myObj[nameA[0]]) == "undefined"){
+							myObj[nameA[0]]=[ ];
+						} // if
+						nameIndex=parseInt(nameA[1]);
+						if(typeof(myObj[nameA[0]][nameIndex]) == "undefined"){
+							myObj[nameA[0]][nameIndex] = { };
+						}
+					} else if(typeof(myObj[nameA[0]]) == "undefined"){
+						myObj[nameA[0]] = { }
+					} // if
+
+					if (nameA.length == 1){
+						myObj=myObj[nameA[0]];
+					} else{
+						myObj=myObj[nameA[0]][nameIndex];
+					} // if
+				} // for
+
+				if ((elm.type != "select-multiple" && elm.type != "checkbox" && elm.type != "radio") || (elm.type=="radio" && elm.checked)){
+					if(name == name.split("[")[0]){
+						myObj[name]=elm.value;
+					} else{
+						// can not set value when there is no name
+					}
+				} else if (elm.type == "checkbox" && elm.checked){
+					if(typeof(myObj[name]) == 'undefined'){
+						myObj[name]=[ ];
+					}
+					myObj[name].push(elm.value);
+				} else if (elm.type == "select-multiple"){
+					if(typeof(myObj[name]) == 'undefined'){
+						myObj[name]=[ ];
+					}
+					for (var jdx=0,len3=elm.options.length; jdx<len3; ++jdx){
+						if (elm.options[jdx].selected){
+							myObj[name].push(elm.options[jdx].value);
+						}
+					}
+				} // if
+				name=undefined;
+			}); // forEach
+			***/
+			return obj;
+		},
+
+		// TODO: ComboBox might need time to process a recently input value.  This should be async?
+	 	isValid: function(){
+	 		// summary:
+	 		//		Returns true if all of the widgets are valid
+	 		
+	 		// This also populate this._invalidWidgets[] array with list of invalid widgets...
+	 		// TODO: put that into separate function?   It's confusing to have that as a side effect
+	 		// of a method named isValid().
+
+			this._invalidWidgets = dojo.filter(this.getDescendants(), function(widget){
+				return !widget.disabled && widget.isValid && !widget.isValid();
+	 		});
+			return !this._invalidWidgets.length;
+		},
+		
+		
+		onValidStateChange: function(isValid){
+			// summary:
+			//		Stub function to connect to if you want to do something
+			//		(like disable/enable a submit button) when the valid 
+			//		state changes on the form as a whole.
+		},
+		
+		_widgetChange: function(widget){
+			// summary:
+			//		Connected to a widget's onChange function - update our 
+			//		valid state, if needed.
+			var isValid = this._lastValidState;
+			if(!widget || this._lastValidState===undefined){
+				// We have passed a null widget, or we haven't been validated
+				// yet - let's re-check all our children
+				// This happens when we connect (or reconnect) our children
+				isValid = this.isValid();
+				if(this._lastValidState===undefined){
+					// Set this so that we don't fire an onValidStateChange 
+					// the first time
+					this._lastValidState = isValid;
+				}
+			}else if(widget.isValid){
+				this._invalidWidgets = dojo.filter(this._invalidWidgets||[], function(w){
+					return (w != widget);
+				}, this);
+				if(!widget.isValid() && !widget.attr("disabled")){
+					this._invalidWidgets.push(widget);
+				}
+				isValid = (this._invalidWidgets.length === 0);
+			}
+			if (isValid !== this._lastValidState){
+				this._lastValidState = isValid;
+				this.onValidStateChange(isValid);
+			}
+		},
+		
+		connectChildren: function(){
+			// summary:
+			//		Connects to the onChange function of all children to
+			//		track valid state changes.  You can call this function
+			//		directly, ex. in the event that you programmatically
+			//		add a widget to the form *after* the form has been
+			//		initialized.
+			dojo.forEach(this._changeConnections, dojo.hitch(this, "disconnect"));
+			var _this = this;
+			
+			// we connect to validate - so that it better reflects the states
+			// of the widgets - also, we only connect if it has a validate
+			// function (to avoid too many unneeded connections)
+			var conns = this._changeConnections = [];
+			dojo.forEach(dojo.filter(this.getDescendants(),
+				function(item){ return item.validate; }
+			),
+			function(widget){
+				// We are interested in whenever the widget is validated - or
+				// whenever the disabled attribute on that widget is changed
+				conns.push(_this.connect(widget, "validate", 
+									dojo.hitch(_this, "_widgetChange", widget)));
+				conns.push(_this.connect(widget, "_setDisabledAttr", 
+									dojo.hitch(_this, "_widgetChange", widget)));
+			});
+
+			// Call the widget change function to update the valid state, in 
+			// case something is different now.
+			this._widgetChange(null);
+		},
+		
+		startup: function(){
+			this.inherited(arguments);
+			// Initialize our valid state tracking.  Needs to be done in startup
+			// because it's not guaranteed that our children are initialized 
+			// yet.
+			this._changeConnections = [];
+			this.connectChildren();
+		}
+	});
+
+}
+
+if(!dojo._hasResource["dijit._DialogMixin"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._DialogMixin"] = true;
+dojo.provide("dijit._DialogMixin");
+
+dojo.declare("dijit._DialogMixin", null,
+	{
+		// summary:
+		//		This provides functions useful to Dialog and TooltipDialog
+
+		attributeMap: dijit._Widget.prototype.attributeMap,
+
+		execute: function(/*Object*/ formContents){
+			// summary:
+			//		Callback when the user hits the submit button.
+			//		Override this method to handle Dialog execution.
+			// description:
+			//		After the user has pressed the submit button, the Dialog
+			//		first calls onExecute() to notify the container to hide the
+			//		dialog and restore focus to wherever it used to be.
+			//
+			//		*Then* this method is called.
+			// type:
+			//		callback
+		},
+
+		onCancel: function(){
+			// summary:
+			//	    Called when user has pressed the Dialog's cancel button, to notify container.
+			// description:
+			//	    Developer shouldn't override or connect to this method;
+			//		it's a private communication device between the TooltipDialog
+			//		and the thing that opened it (ex: `dijit.form.DropDownButton`)
+			// type:
+			//		protected
+		},
+
+		onExecute: function(){
+			// summary:
+			//	    Called when user has pressed the dialog's OK button, to notify container.
+			// description:
+			//	    Developer shouldn't override or connect to this method;
+			//		it's a private communication device between the TooltipDialog
+			//		and the thing that opened it (ex: `dijit.form.DropDownButton`)
+			// type:
+			//		protected
+		},
+
+		_onSubmit: function(){
+			// summary:
+			//		Callback when user hits submit button
+			// type:
+			//		protected
+			this.onExecute();	// notify container that we are about to execute
+			this.execute(this.attr('value'));
+		},
+
+		_getFocusItems: function(/*Node*/ dialogNode){
+			// summary:
+			//		Find focusable Items each time a dialog is opened,
+			//		setting _firstFocusItem and _lastFocusItem
+			// tags:
+			//		protected
+			
+			var elems = dijit._getTabNavigable(dojo.byId(dialogNode));
+			this._firstFocusItem = elems.lowest || elems.first || dialogNode;
+			this._lastFocusItem = elems.last || elems.highest || this._firstFocusItem;
+			if(dojo.isMoz && this._firstFocusItem.tagName.toLowerCase() == "input" && dojo.attr(this._firstFocusItem, "type").toLowerCase() == "file"){
+					//FF doesn't behave well when first element is input type=file, set first focusable to dialog container
+					dojo.attr(dialogNode, "tabindex", "0");
+					this._firstFocusItem = dialogNode;
+			}
+		}
+	}
+);
+
+}
+
+if(!dojo._hasResource["dijit.DialogUnderlay"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.DialogUnderlay"] = true;
+dojo.provide("dijit.DialogUnderlay");
+
+
+
+
+dojo.declare(
+	"dijit.DialogUnderlay",
+	[dijit._Widget, dijit._Templated],
+	{
+		// summary: The component that blocks the screen behind a `dijit.Dialog`
+		//
+		// description:
+		// 		A component used to block input behind a `dijit.Dialog`. Only a single
+		//		instance of this widget is created by `dijit.Dialog`, and saved as 
+		//		a reference to be shared between all Dialogs as `dijit._underlay`
+		//	
+		//		The underlay itself can be styled based on and id:
+		//	|	#myDialog_underlay { background-color:red; }
+		//
+		//		In the case of `dijit.Dialog`, this id is based on the id of the Dialog,
+		//		suffixed with _underlay. 
+		
+		// Template has two divs; outer div is used for fade-in/fade-out, and also to hold background iframe.
+		// Inner div has opacity specified in CSS file.
+		templateString: "<div class='dijitDialogUnderlayWrapper'><div class='dijitDialogUnderlay' dojoAttachPoint='node'></div></div>",
+
+		// Parameters on creation or updatable later
+
+		// dialogId: String
+		//		Id of the dialog.... DialogUnderlay's id is based on this id
+		dialogId: "",
+
+		// class: String
+		//		This class name is used on the DialogUnderlay node, in addition to dijitDialogUnderlay
+		"class": "",
+
+		attributeMap: { id: "domNode" },
+
+		_setDialogIdAttr: function(id){
+			dojo.attr(this.node, "id", id + "_underlay");
+		},
+
+		_setClassAttr: function(clazz){
+			this.node.className = "dijitDialogUnderlay " + clazz;
+		},
+
+		postCreate: function(){
+			// summary:
+			//		Append the underlay to the body
+			dojo.body().appendChild(this.domNode);
+			this.bgIframe = new dijit.BackgroundIframe(this.domNode);
+		},
+
+		layout: function(){
+			// summary:
+			//		Sets the background to the size of the viewport
+			//
+			// description:
+			//		Sets the background to the size of the viewport (rather than the size
+			//		of the document) since we need to cover the whole browser window, even
+			//		if the document is only a few lines long.
+			// tags:
+			//		private
+
+			var is = this.node.style,
+				os = this.domNode.style;
+
+			// hide the background temporarily, so that the background itself isn't
+			// causing scrollbars to appear (might happen when user shrinks browser
+			// window and then we are called to resize)
+			os.display = "none";
+
+			// then resize and show
+			var viewport = dijit.getViewport();
+			os.top = viewport.t + "px";
+			os.left = viewport.l + "px";
+			is.width = viewport.w + "px";
+			is.height = viewport.h + "px";
+			os.display = "block";
+		},
+
+		show: function(){
+			// summary:
+			//		Show the dialog underlay
+			this.domNode.style.display = "block";
+			this.layout();
+			if(this.bgIframe.iframe){
+				this.bgIframe.iframe.style.display = "block";
+			}
+		},
+
+		hide: function(){
+			// summary:
+			//		Hides the dialog underlay
+			this.domNode.style.display = "none";
+			if(this.bgIframe.iframe){
+				this.bgIframe.iframe.style.display = "none";
+			}
+		},
+
+		uninitialize: function(){
+			if(this.bgIframe){
+				this.bgIframe.destroy();
+			}
+		}
+	}
+);
+
+}
+
+if(!dojo._hasResource["dijit._Contained"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._Contained"] = true;
+dojo.provide("dijit._Contained");
+
+dojo.declare("dijit._Contained",
+		null,
+		{
+			// summary
+			//		Mixin for widgets that are children of a container widget
+			//
+			// example:
+			// | 	// make a basic custom widget that knows about it's parents
+			// |	dojo.declare("my.customClass",[dijit._Widget,dijit._Contained],{});
+			// 
+			getParent: function(){
+				// summary:
+				//		Returns the parent widget of this widget, assuming the parent
+				//		implements dijit._Container
+				for(var p=this.domNode.parentNode; p; p=p.parentNode){
+					var id = p.getAttribute && p.getAttribute("widgetId");
+					if(id){
+						var parent = dijit.byId(id);
+						return parent.isContainer ? parent : null;
+					}
+				}
+				return null;
+			},
+
+			_getSibling: function(which){
+				// summary:
+				//      Returns next or previous sibling
+				// which:
+				//      Either "next" or "previous"
+				// tags:
+				//      private
+				var node = this.domNode;
+				do{
+					node = node[which+"Sibling"];
+				}while(node && node.nodeType != 1);
+				if(!node){ return null; } // null
+				var id = node.getAttribute("widgetId");
+				return dijit.byId(id);
+			},
+
+			getPreviousSibling: function(){
+				// summary:
+				//		Returns null if this is the first child of the parent,
+				//		otherwise returns the next element sibling to the "left".
+
+				return this._getSibling("previous"); // Mixed
+			},
+
+			getNextSibling: function(){
+				// summary:
+				//		Returns null if this is the last child of the parent,
+				//		otherwise returns the next element sibling to the "right".
+
+				return this._getSibling("next"); // Mixed
+			},
+			
+			getIndexInParent: function(){
+				// summary:
+				//		Returns the index of this widget within its container parent.
+				//		It returns -1 if the parent does not exist, or if the parent
+				//		is not a dijit._Container
+				
+				var p = this.getParent();
+				if(!p || !p.getIndexOfChild){
+					return -1; // int
+				}
+				return p.getIndexOfChild(this); // int
+			}
+		}
+	);
+
+
+}
+
+if(!dojo._hasResource["dijit._Container"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._Container"] = true;
+dojo.provide("dijit._Container");
+
+dojo.declare("dijit._Container",
+	null,
+	{
+		// summary:
+		//		Mixin for widgets that contain a set of widget children.
+		// description:
+		//		Use this mixin for widgets that needs to know about and
+		//		keep track of their widget children. Suitable for widgets like BorderContainer
+		//		and TabContainer which contain (only) a set of child widgets.
+		//
+		//		It's not suitable for widgets like ContentPane
+		//		which contains mixed HTML (plain DOM nodes in addition to widgets),
+		//		and where contained widgets are not necessarily directly below
+		//		this.containerNode.   In that case calls like addChild(node, position)
+		//		wouldn't make sense.
+
+		// isContainer: [protected] Boolean
+		//		Just a flag indicating that this widget descends from dijit._Container
+		isContainer: true,
+
+		buildRendering: function(){
+			this.inherited(arguments);
+			if(!this.containerNode){
+				// all widgets with descendants must set containerNode
+   				this.containerNode = this.domNode;
+			}
+		},
+
+		addChild: function(/*Widget*/ widget, /*int?*/ insertIndex){
+			// summary:
+			//		Makes the given widget a child of this widget.
+			// description:
+			//		Inserts specified child widget's dom node as a child of this widget's
+			//		container node, and possibly does other processing (such as layout).
+
+			var refNode = this.containerNode;
+			if(insertIndex && typeof insertIndex == "number"){
+				var children = this.getChildren();
+				if(children && children.length >= insertIndex){
+					refNode = children[insertIndex-1].domNode;
+					insertIndex = "after";
+				}
+			}
+			dojo.place(widget.domNode, refNode, insertIndex);
+
+			// If I've been started but the child widget hasn't been started,
+			// start it now.  Make sure to do this after widget has been
+			// inserted into the DOM tree, so it can see that it's being controlled by me,
+			// so it doesn't try to size itself.
+			if(this._started && !widget._started){
+				widget.startup();
+			}
+		},
+
+		removeChild: function(/*Widget or int*/ widget){
+			// summary:
+			//		Removes the passed widget instance from this widget but does
+			//		not destroy it.  You can also pass in an integer indicating
+			//		the index within the container to remove
+			if(typeof widget == "number" && widget > 0){
+				widget = this.getChildren()[widget];
+			}
+			// If we cannot find the widget, just return
+			if(!widget || !widget.domNode){ return; }
+			
+			var node = widget.domNode;
+			node.parentNode.removeChild(node);	// detach but don't destroy
+		},
+
+		_nextElement: function(node){
+			// summary:
+			//      Find the next (non-text, non-comment etc) node
+			// tags:
+			//      private
+			do{
+				node = node.nextSibling;
+			}while(node && node.nodeType != 1);
+			return node;
+		},
+
+		_firstElement: function(node){
+			// summary:
+			//      Find the first (non-text, non-comment etc) node
+			// tags:
+			//      private
+			node = node.firstChild;
+			if(node && node.nodeType != 1){
+				node = this._nextElement(node);
+			}
+			return node;
+		},
+
+		getChildren: function(){
+			// summary:
+			//		Returns array of children widgets.
+			// description:
+			//		Returns the widgets that are directly under this.containerNode.
+			return dojo.query("> [widgetId]", this.containerNode).map(dijit.byNode); // Widget[]
+		},
+
+		hasChildren: function(){
+			// summary:
+			//		Returns true if widget has children, i.e. if this.containerNode contains something.
+			return !!this._firstElement(this.containerNode); // Boolean
+		},
+
+		destroyDescendants: function(/*Boolean*/ preserveDom){
+			// summary:
+			//      Destroys all the widgets inside this.containerNode,
+			//      but not this widget itself
+			dojo.forEach(this.getChildren(), function(child){ child.destroyRecursive(preserveDom); });
+		},
+	
+		_getSiblingOfChild: function(/*Widget*/ child, /*int*/ dir){
+			// summary:
+			//		Get the next or previous widget sibling of child
+			// dir:
+			//		if 1, get the next sibling
+			//		if -1, get the previous sibling
+			// tags:
+			//      private
+			var node = child.domNode;
+			var which = (dir>0 ? "nextSibling" : "previousSibling");
+			do{
+				node = node[which];
+			}while(node && (node.nodeType != 1 || !dijit.byNode(node)));
+			return node ? dijit.byNode(node) : null;
+		},
+		
+		getIndexOfChild: function(/*Widget*/ child){
+			// summary:
+			//		Gets the index of the child in this container or -1 if not found
+			var children = this.getChildren();
+			for(var i=0, c; c=children[i]; i++){
+				if(c == child){ 
+					return i; // int
+				}
+			}
+			return -1; // int
+		}
+	}
+);
+
+}
+
+if(!dojo._hasResource["dijit.layout._LayoutWidget"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.layout._LayoutWidget"] = true;
+dojo.provide("dijit.layout._LayoutWidget");
+
+
+
+
+
+dojo.declare("dijit.layout._LayoutWidget",
+	[dijit._Widget, dijit._Container, dijit._Contained],
+	{
+		// summary:
+		//		Base class for a _Container widget which is responsible for laying out its children.
+		//		Widgets which mixin this code must define layout() to lay out the children.
+
+		// baseClass: [protected extension] String
+		//		This class name is applied to the widget's domNode
+		//		and also may be used to generate names for sub nodes,
+		//		like for example dijitTabContainer-content.
+		baseClass: "dijitLayoutContainer",
+
+		// isLayoutContainer: [private deprecated] Boolean
+		//		TODO: this is unused, but maybe it *should* be used for a child to
+		//		detect whether the parent is going to call resize() on it or not
+		//		(see calls to getParent() and resize() in this file)
+		isLayoutContainer: true,
+
+		postCreate: function(){
+			dojo.addClass(this.domNode, "dijitContainer");
+			dojo.addClass(this.domNode, this.baseClass);
+			
+			// TODO: this.inherited()
+		},
+
+		startup: function(){
+			// summary:
+			//		Called after all the widgets have been instantiated and their
+			//		dom nodes have been inserted somewhere under dojo.doc.body.
+			//
+			//		Widgets should override this method to do any initialization
+			//		dependent on other widgets existing, and then call
+			//		this superclass method to finish things off.
+			//
+			//		startup() in subclasses shouldn't do anything
+			//		size related because the size of the widget hasn't been set yet.
+
+			if(this._started){ return; }
+
+			// TODO: seems like this code should be in _Container.startup().
+			// Then things that don't extend LayoutContainer (like GridContainer)
+			// would get the behavior for free.
+			dojo.forEach(this.getChildren(), function(child){ child.startup(); });
+
+			// If I am a top level widget
+			if(!this.getParent || !this.getParent()){
+				// Do recursive sizing and layout of all my descendants
+				// (passing in no argument to resize means that it has to glean the size itself)
+				this.resize();
+
+				// Since my parent isn't a layout container, and my style is width=height=100% (or something similar),
+				// then I need to watch when the window resizes, and size myself accordingly.
+				// (Passing in no arguments to resize means that it has to glean the size itself.)
+				// TODO: make one global listener to avoid getViewport() per widget.
+				this._viewport = dijit.getViewport();
+				this.connect(dojo.global, 'onresize', function(){
+					var newViewport = dijit.getViewport();
+					if(newViewport.w != this._viewport.w ||  newViewport.h != this._viewport.h){
+						this._viewport = newViewport;
+						this.resize();
+					}
+				});
+			}
+			
+			this.inherited(arguments);
+		},
+
+		resize: function(changeSize, resultSize){
+			// summary:
+			//		Call this to resize a widget, or after its size has changed.
+			// description:
+			//		Change size mode:
+			//			When changeSize is specified, changes the marginBox of this widget
+			//			 and forces it to relayout its contents accordingly.
+			//			changeSize may specify height, width, or both.
+			//
+			//			If resultSize is specified it indicates the size the widget will
+			//			become after changeSize has been applied.
+			//
+			//		Notification mode:
+			//			When changeSize is null, indicates that the caller has already changed
+			//			the size of the widget, or perhaps it changed because the browser
+			//			window was resized.  Tells widget to relayout it's contents accordingly.
+			//
+			//			If resultSize is also specified it indicates the size the widget has
+			//			become.
+			//
+			//		In either mode, this method also:
+			//			1. Sets this._borderBox and this._contentBox to the new size of
+			//				the widget.  Queries the current domNode size if necessary.
+			//			2. Calls layout() to resize contents (and maybe adjust child widgets).	
+			//
+			// changeSize: Object?
+			//		Sets the widget to this margin-box size and position.
+			//		May include any/all of the following properties:
+			//	|	{w: int, h: int, l: int, t: int}
+			//
+			// resultSize: Object?
+			//		The margin-box size of this widget after applying changeSize (if 
+			//		changeSize is specified).  If caller knows this size and
+			//		passes it in, we don't need to query the browser to get the size.
+			//	|	{w: int, h: int}
+
+			var node = this.domNode;
+
+			// set margin box size, unless it wasn't specified, in which case use current size
+			if(changeSize){
+				dojo.marginBox(node, changeSize);
+
+				// set offset of the node
+				if(changeSize.t){ node.style.top = changeSize.t + "px"; }
+				if(changeSize.l){ node.style.left = changeSize.l + "px"; }
+			}
+
+			// If either height or width wasn't specified by the user, then query node for it.
+			// But note that setting the margin box and then immediately querying dimensions may return
+			// inaccurate results, so try not to depend on it.
+			var mb = resultSize || {};
+			dojo.mixin(mb, changeSize || {});	// changeSize overrides resultSize
+			if ( !("h" in mb) || !("w" in mb) ){
+				mb = dojo.mixin(dojo.marginBox(node), mb);	// just use dojo.marginBox() to fill in missing values
+			}
+
+			// Compute and save the size of my border box and content box
+			// (w/out calling dojo.contentBox() since that may fail if size was recently set)
+			var cs = dojo.getComputedStyle(node);
+			var me = dojo._getMarginExtents(node, cs);
+			var be = dojo._getBorderExtents(node, cs);
+			var bb = (this._borderBox = {
+				w: mb.w - (me.w + be.w),
+				h: mb.h - (me.h + be.h)
+			});
+			var pe = dojo._getPadExtents(node, cs);
+			this._contentBox = {
+				l: dojo._toPixelValue(node, cs.paddingLeft),
+				t: dojo._toPixelValue(node, cs.paddingTop),
+				w: bb.w - pe.w,
+				h: bb.h - pe.h
+			};
+
+			// Callback for widget to adjust size of it's children
+			this.layout();
+		},
+
+		layout: function(){
+			// summary:
+			//		Widgets override this method to size and position their contents/children.
+			//		When this is called this._contentBox is guaranteed to be set (see resize()).
+			//
+			//		This is called after startup(), and also when the widget's size has been
+			//		changed.
+			// tags:
+			//		protected extension
+		},
+
+		_setupChild: function(/*Widget*/child){
+			// summary:
+			//		Common setup for initial children and children which are added after startup
+			// tags:
+			//		protected extension
+
+			dojo.addClass(child.domNode, this.baseClass+"-child");
+			if(child.baseClass){
+				dojo.addClass(child.domNode, this.baseClass+"-"+child.baseClass);
+			}
+		},
+
+		addChild: function(/*Widget*/ child, /*Integer?*/ insertIndex){
+			// Overrides _Container.addChild() to call _setupChild()
+			this.inherited(arguments);
+			if(this._started){
+				this._setupChild(child);
+			}
+		},
+
+		removeChild: function(/*Widget*/ child){
+			// Overrides _Container.removeChild() to remove class added by _setupChild()
+			dojo.removeClass(child.domNode, this.baseClass+"-child");
+			if(child.baseClass){
+				dojo.removeClass(child.domNode, this.baseClass+"-"+child.baseClass);
+			}
+			this.inherited(arguments);
+		}
+	}
+);
+
+dijit.layout.marginBox2contentBox = function(/*DomNode*/ node, /*Object*/ mb){
+	// summary:
+	//		Given the margin-box size of a node, return its content box size.
+	//		Functions like dojo.contentBox() but is more reliable since it doesn't have
+	//		to wait for the browser to compute sizes.
+	var cs = dojo.getComputedStyle(node);
+	var me = dojo._getMarginExtents(node, cs);
+	var pb = dojo._getPadBorderExtents(node, cs);
+	return {
+		l: dojo._toPixelValue(node, cs.paddingLeft),
+		t: dojo._toPixelValue(node, cs.paddingTop),
+		w: mb.w - (me.w + pb.w),
+		h: mb.h - (me.h + pb.h)
+	};
+};
+
+(function(){
+	var capitalize = function(word){
+		return word.substring(0,1).toUpperCase() + word.substring(1);
+	};
+
+	var size = function(widget, dim){
+		// size the child
+		widget.resize ? widget.resize(dim) : dojo.marginBox(widget.domNode, dim);
+
+		// record child's size, but favor our own numbers when we have them.
+		// the browser lies sometimes
+		dojo.mixin(widget, dojo.marginBox(widget.domNode));
+		dojo.mixin(widget, dim);
+	};
+
+	dijit.layout.layoutChildren = function(/*DomNode*/ container, /*Object*/ dim, /*Object[]*/ children){
+		// summary
+		//		Layout a bunch of child dom nodes within a parent dom node
+		// container:
+		//		parent node
+		// dim:
+		//		{l, t, w, h} object specifying dimensions of container into which to place children
+		// children:
+		//		an array like [ {domNode: foo, layoutAlign: "bottom" }, {domNode: bar, layoutAlign: "client"} ]
+
+		// copy dim because we are going to modify it
+		dim = dojo.mixin({}, dim);
+
+		dojo.addClass(container, "dijitLayoutContainer");
+
+		// Move "client" elements to the end of the array for layout.  a11y dictates that the author
+		// needs to be able to put them in the document in tab-order, but this algorithm requires that
+		// client be last.
+		children = dojo.filter(children, function(item){ return item.layoutAlign != "client"; })
+			.concat(dojo.filter(children, function(item){ return item.layoutAlign == "client"; }));
+
+		// set positions/sizes
+		dojo.forEach(children, function(child){
+			var elm = child.domNode,
+				pos = child.layoutAlign;
+
+			// set elem to upper left corner of unused space; may move it later
+			var elmStyle = elm.style;
+			elmStyle.left = dim.l+"px";
+			elmStyle.top = dim.t+"px";
+			elmStyle.bottom = elmStyle.right = "auto";
+
+			dojo.addClass(elm, "dijitAlign" + capitalize(pos));
+
+			// set size && adjust record of remaining space.
+			// note that setting the width of a <div> may affect it's height.
+			if(pos == "top" || pos == "bottom"){
+				size(child, { w: dim.w });
+				dim.h -= child.h;
+				if(pos=="top"){
+					dim.t += child.h;
+				}else{
+					elmStyle.top = dim.t + dim.h + "px";
+				}
+			}else if(pos == "left" || pos == "right"){
+				size(child, { h: dim.h });
+				dim.w -= child.w;
+				if(pos == "left"){
+					dim.l += child.w;
+				}else{
+					elmStyle.left = dim.l + dim.w + "px";
+				}
+			}else if(pos == "client"){
+				size(child, dim);
+			}
+		});
+	};
+
+})();
+
+}
+
+if(!dojo._hasResource["dojo.html"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.html"] = true;
+dojo.provide("dojo.html");
+
+// the parser might be needed..
+ 
+
+(function(){ // private scope, sort of a namespace
+
+	// idCounter is incremented with each instantiation to allow asignment of a unique id for tracking, logging purposes
+	var idCounter = 0; 
+
+	dojo.html._secureForInnerHtml = function(/*String*/ cont){
+		// summary:
+		//		removes !DOCTYPE and title elements from the html string.
+		// 
+		//		khtml is picky about dom faults, you can't attach a style or <title> node as child of body
+		//		must go into head, so we need to cut out those tags
+		//	cont:
+		//		An html string for insertion into the dom
+		//	
+		return cont.replace(/(?:\s*<!DOCTYPE\s[^>]+>|<title[^>]*>[\s\S]*?<\/title>)/ig, ""); // String
+	};
+
+/*====
+	dojo.html._emptyNode = function(node){
+		// summary:
+		//		removes all child nodes from the given node
+		//	node: DOMNode
+		//		the parent element
+	};
+=====*/
+	dojo.html._emptyNode = dojo.empty;
+
+	dojo.html._setNodeContent = function(/* DomNode */ node, /* String|DomNode|NodeList */ cont, /* Boolean? */ shouldEmptyFirst){
+		// summary:
+		//		inserts the given content into the given node
+		//		overlaps similiar functionality in dijit.layout.ContentPane._setContent
+		//	node:
+		//		the parent element
+		//	content:
+		//		the content to be set on the parent element. 
+		//		This can be an html string, a node reference or a NodeList, dojo.NodeList, Array or other enumerable list of nodes
+		// shouldEmptyFirst
+		//		if shouldEmptyFirst is true, the node will first be emptied of all content before the new content is inserted
+		//		defaults to false
+		if(shouldEmptyFirst){
+			dojo.html._emptyNode(node); 
+		}
+
+		if(typeof cont == "string"){
+			// there's some hoops to jump through before we can set innerHTML on the would-be parent element. 
+	
+			// rationale for this block:
+			// if node is a table derivate tag, some browsers dont allow innerHTML on those
+			// TODO: <select>, <dl>? what other elements will give surprises if you naively set innerHTML?
+			
+			var pre = '', post = '', walk = 0, name = node.nodeName.toLowerCase();
+			switch(name){
+				case 'tr':
+					pre = '<tr>'; post = '</tr>';
+					walk += 1;//fallthrough
+				case 'tbody': case 'thead':// children of THEAD is of same type as TBODY
+					pre = '<tbody>' + pre; post += '</tbody>';
+					walk += 1;// falltrough
+				case 'table':
+					pre = '<table>' + pre; post += '</table>';
+					walk += 1;
+					break;
+			}
+			if(walk){
+				var n = node.ownerDocument.createElement('div');
+				n.innerHTML = pre + cont + post;
+				do{
+					n = n.firstChild;
+				}while(--walk);
+				// now we can safely add the child nodes...
+				dojo.forEach(n.childNodes, function(n){
+					node.appendChild(n.cloneNode(true));
+				});
+			}else{
+				// innerHTML the content as-is into the node (element)
+				// should we ever support setting content on non-element node types? 
+				// e.g. text nodes, comments, etc.?
+				node.innerHTML = cont;
+			}
+
+		}else{
+			// DomNode or NodeList
+			if(cont.nodeType){ // domNode (htmlNode 1 or textNode 3)
+				node.appendChild(cont);
+			}else{// nodelist or array such as dojo.Nodelist
+				dojo.forEach(cont, function(n){
+					node.appendChild(n.cloneNode(true));
+				});
+			}
+		}
+		// return DomNode
+		return node;
+	};
+
+	// we wrap up the content-setting operation in a object
+	dojo.declare("dojo.html._ContentSetter", null, 
+		{
+			// node: DomNode|String
+			//		An node which will be the parent element that we set content into
+			node: "",
+
+			// content: String|DomNode|DomNode[]
+			//		The content to be placed in the node. Can be an HTML string, a node reference, or a enumerable list of nodes
+			content: "",
+			
+			// id: String?
+			//		Usually only used internally, and auto-generated with each instance 
+			id: "",
+
+			// cleanContent: Boolean
+			//		Should the content be treated as a full html document, 
+			//		and the real content stripped of <html>, <body> wrapper before injection
+			cleanContent: false,
+			
+			// extractContent: Boolean
+			//		Should the content be treated as a full html document, and the real content stripped of <html>, <body> wrapper before injection
+			extractContent: false,
+
+			// parseContent: Boolean
+			//		Should the node by passed to the parser after the new content is set
+			parseContent: false,
+			
+			// lifecyle methods
+			constructor: function(/* Object */params, /* String|DomNode */node){
+				//	summary:
+				//		Provides a configurable, extensible object to wrap the setting on content on a node
+				//		call the set() method to actually set the content..
+ 
+				// the original params are mixed directly into the instance "this"
+				dojo.mixin(this, params || {});
+
+				// give precedence to params.node vs. the node argument
+				// and ensure its a node, not an id string
+				node = this.node = dojo.byId( this.node || node );
+	
+				if(!this.id){
+					this.id = [
+						"Setter",
+						(node) ? node.id || node.tagName : "", 
+						idCounter++
+					].join("_");
+				}
+
+				if(! (this.node || node)){
+					new Error(this.declaredClass + ": no node provided to " + this.id);
+				}
+			},
+			set: function(/* String|DomNode|NodeList? */ cont, /* Object? */ params){
+				// summary:
+				//		front-end to the set-content sequence 
+				//	cont:
+				//		An html string, node or enumerable list of nodes for insertion into the dom
+				//		If not provided, the object's content property will be used
+				if(undefined !== cont){
+					this.content = cont;
+				}
+				// in the re-use scenario, set needs to be able to mixin new configuration
+				if(params){
+					this._mixin(params);
+				}
+
+				this.onBegin();
+				this.setContent();
+				this.onEnd();
+
+				return this.node;
+			},
+			setContent: function(){
+				// summary:
+				//		sets the content on the node 
+
+				var node = this.node; 
+				if(!node) {
+					console.error("setContent given no node");
+				}
+				try{
+					node = dojo.html._setNodeContent(node, this.content);
+				}catch(e){
+					// check if a domfault occurs when we are appending this.errorMessage
+					// like for instance if domNode is a UL and we try append a DIV
+	
+					// FIXME: need to allow the user to provide a content error message string
+					var errMess = this.onContentError(e); 
+					try{
+						node.innerHTML = errMess;
+					}catch(e){
+						console.error('Fatal ' + this.declaredClass + '.setContent could not change content due to '+e.message, e);
+					}
+				}
+				// always put back the node for the next method
+				this.node = node; // DomNode
+			},
+			
+			empty: function() {
+				// summary
+				//	cleanly empty out existing content
+
+				// destroy any widgets from a previous run
+				// NOTE: if you dont want this you'll need to empty 
+				// the parseResults array property yourself to avoid bad things happenning
+				if(this.parseResults && this.parseResults.length) {
+					dojo.forEach(this.parseResults, function(w) {
+						if(w.destroy){
+							w.destroy();
+						}
+					});
+					delete this.parseResults;
+				}
+				// this is fast, but if you know its already empty or safe, you could 
+				// override empty to skip this step
+				dojo.html._emptyNode(this.node);
+			},
+	
+			onBegin: function(){
+				// summary
+				//		Called after instantiation, but before set(); 
+				//		It allows modification of any of the object properties 
+				//		- including the node and content provided - before the set operation actually takes place
+				//		This default implementation checks for cleanContent and extractContent flags to 
+				//		optionally pre-process html string content
+				var cont = this.content;
+	
+				if(dojo.isString(cont)){
+					if(this.cleanContent){
+						cont = dojo.html._secureForInnerHtml(cont);
+					}
+  
+					if(this.extractContent){
+						var match = cont.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
+						if(match){ cont = match[1]; }
+					}
+				}
+
+				// clean out the node and any cruft associated with it - like widgets
+				this.empty();
+				
+				this.content = cont;
+				return this.node; /* DomNode */
+			},
+	
+			onEnd: function(){
+				// summary
+				//		Called after set(), when the new content has been pushed into the node
+				//		It provides an opportunity for post-processing before handing back the node to the caller
+				//		This default implementation checks a parseContent flag to optionally run the dojo parser over the new content
+				if(this.parseContent){
+					// populates this.parseResults if you need those..
+					this._parse();
+				}
+				return this.node; /* DomNode */
+			},
+	
+			tearDown: function(){
+				// summary
+				//		manually reset the Setter instance if its being re-used for example for another set()
+				// description
+				//		tearDown() is not called automatically. 
+				//		In normal use, the Setter instance properties are simply allowed to fall out of scope
+				//		but the tearDown method can be called to explicitly reset this instance.
+				delete this.parseResults; 
+				delete this.node; 
+				delete this.content; 
+			},
+  
+			onContentError: function(err){
+				return "Error occured setting content: " + err; 
+			},
+			
+			_mixin: function(params){
+				// mix properties/methods into the instance
+				// TODO: the intention with tearDown is to put the Setter's state 
+				// back to that of the original constructor (vs. deleting/resetting everything regardless of ctor params)
+				// so we could do something here to move the original properties aside for later restoration
+				var empty = {}, key;
+				for(key in params){
+					if(key in empty){ continue; }
+					// TODO: here's our opportunity to mask the properties we dont consider configurable/overridable
+					// .. but history shows we'll almost always guess wrong
+					this[key] = params[key]; 
+				}
+			},
+			_parse: function(){
+				// summary: 
+				//		runs the dojo parser over the node contents, storing any results in this.parseResults
+				//		Any errors resulting from parsing are passed to _onError for handling
+
+				var rootNode = this.node;
+				try{
+					// store the results (widgets, whatever) for potential retrieval
+					this.parseResults = dojo.parser.parse(rootNode, true);
+				}catch(e){
+					this._onError('Content', e, "Error parsing in _ContentSetter#"+this.id);
+				}
+			},
+  
+			_onError: function(type, err, consoleText){
+				// summary:
+				//		shows user the string that is returned by on[type]Error
+				//		overide/implement on[type]Error and return your own string to customize
+				var errText = this['on' + type + 'Error'].call(this, err);
+				if(consoleText){
+					console.error(consoleText, err);
+				}else if(errText){ // a empty string won't change current content
+					dojo.html._setNodeContent(this.node, errText, true);
+				}
+			}
+	}); // end dojo.declare()
+
+	dojo.html.set = function(/* DomNode */ node, /* String|DomNode|NodeList */ cont, /* Object? */ params){
+			// summary:
+			//		inserts (replaces) the given content into the given node. dojo.place(cont, node, "only")
+			//		may be a better choice for simple HTML insertion.
+			// description:
+			//		Unless you need to use the params capabilities of this method, you should use
+			//		dojo.place(cont, node, "only"). dojo.place() has more robust support for injecting
+			//		an HTML string into the DOM, but it only handles inserting an HTML string as DOM
+			//		elements, or inserting a DOM node. dojo.place does not handle NodeList insertions
+			//		or the other capabilities as defined by the params object for this method.
+			//	node:
+			//		the parent element that will receive the content
+			//	cont:
+			//		the content to be set on the parent element. 
+			//		This can be an html string, a node reference or a NodeList, dojo.NodeList, Array or other enumerable list of nodes
+			//	params: 
+			//		Optional flags/properties to configure the content-setting. See dojo.html._ContentSetter
+			//	example:
+			//		A safe string/node/nodelist content replacement/injection with hooks for extension
+			//		Example Usage: 
+			//		dojo.html.set(node, "some string"); 
+			//		dojo.html.set(node, contentNode, {options}); 
+			//		dojo.html.set(node, myNode.childNodes, {options}); 
+		if(undefined == cont){
+			console.warn("dojo.html.set: no cont argument provided, using empty string");
+			cont = "";
+		}	
+		if(!params){
+			// simple and fast
+			return dojo.html._setNodeContent(node, cont, true);
+		}else{ 
+			// more options but slower
+			// note the arguments are reversed in order, to match the convention for instantiation via the parser
+			var op = new dojo.html._ContentSetter(dojo.mixin( 
+					params, 
+					{ content: cont, node: node } 
+			));
+			return op.set();
+		}
+	};
+})();
+
+}
+
+if(!dojo._hasResource["dijit.layout.ContentPane"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.layout.ContentPane"] = true;
+dojo.provide("dijit.layout.ContentPane");
+
+
+
+	// for dijit.layout.marginBox2contentBox()
+
+
+
+
+
+
+dojo.declare(
+	"dijit.layout.ContentPane", dijit._Widget,
+{
+	// summary:
+	//		A widget that acts as a container for mixed HTML and widgets, and includes an Ajax interface
+	// description:
+	//		A widget that can be used as a standalone widget
+	//		or as a baseclass for other widgets
+	//		Handles replacement of document fragment using either external uri or javascript
+	//		generated markup or DOM content, instantiating widgets within that content.
+	//		Don't confuse it with an iframe, it only needs/wants document fragments.
+	//		It's useful as a child of LayoutContainer, SplitContainer, or TabContainer.
+	//		But note that those classes can contain any widget as a child.
+	// example:
+	//		Some quick samples:
+	//		To change the innerHTML use .attr('content', '<b>new content</b>')
+	//
+	//		Or you can send it a NodeList, .attr('content', dojo.query('div [class=selected]', userSelection))
+	//		please note that the nodes in NodeList will copied, not moved
+	//
+	//		To do a ajax update use .attr('href', url)
+
+	// href: String
+	//		The href of the content that displays now.
+	//		Set this at construction if you want to load data externally when the
+	//		pane is shown.	(Set preload=true to load it immediately.)
+	//		Changing href after creation doesn't have any effect; use attr('href', ...);
+	href: "",
+
+/*=====
+	// content: String || DomNode || NodeList || dijit._Widget
+	//		The innerHTML of the ContentPane.
+	//		Note that the initialization parameter / argument to attr("content", ...)
+	//		can be a String, DomNode, Nodelist, or _Widget.
+	content: "",
+=====*/
+
+	// extractContent: Boolean
+	//		Extract visible content from inside of <body> .... </body>.
+	//		I.e., strip <html> and <head> (and it's contents) from the href
+	extractContent: false,
+
+	// parseOnLoad: Boolean
+	//		Parse content and create the widgets, if any.
+	parseOnLoad:	true,
+
+	// preventCache: Boolean
+	//		Prevent caching of data from href's by appending a timestamp to the href.
+	preventCache:	false,
+
+	// preload: Boolean
+	//		Force load of data on initialization even if pane is hidden.
+	preload: false,
+
+	// refreshOnShow: Boolean
+	//		Refresh (re-download) content when pane goes from hidden to shown
+	refreshOnShow: false,
+
+	// loadingMessage: String
+	//		Message that shows while downloading
+	loadingMessage: "<span class='dijitContentPaneLoading'>${loadingState}</span>", 
+
+	// errorMessage: String
+	//		Message that shows if an error occurs
+	errorMessage: "<span class='dijitContentPaneError'>${errorState}</span>", 
+
+	// isLoaded: [readonly] Boolean
+	//		True if the ContentPane has data in it, either specified
+	//		during initialization (via href or inline content), or set
+	//		via attr('content', ...) / attr('href', ...)
+	//
+	//		False if it doesn't have any content, or if ContentPane is
+	//		still in the process of downloading href.
+	isLoaded: false,
+
+	baseClass: "dijitContentPane",
+
+	// doLayout: Boolean
+	//		- false - don't adjust size of children
+	//		- true - if there is a single visible child widget, set it's size to
+	//				however big the ContentPane is
+	doLayout: true,
+
+	// ioArgs: Object
+	//		Parameters to pass to xhrGet() request, for example:
+	// |	<div dojoType="dijit.layout.ContentPane" href="./bar" ioArgs="{timeout: 500}">
+	ioArgs: {},
+
+	// isContainer: [protected] Boolean
+	//		Just a flag indicating that this widget will call resize() on
+	//		its children.   _LayoutWidget based widgets check for
+	//
+	//	|		if(!this.getParent || !this.getParent()){
+	//
+	//		and if getParent() returns false because !parent.isContainer,
+	//		then they resize themselves on initialization.
+	isContainer: true,
+
+	postMixInProperties: function(){
+		this.inherited(arguments);
+		var messages = dojo.i18n.getLocalization("dijit", "loading", this.lang);
+		this.loadingMessage = dojo.string.substitute(this.loadingMessage, messages);
+		this.errorMessage = dojo.string.substitute(this.errorMessage, messages);
+		
+		// Detect if we were initialized with data
+		if(!this.href && this.srcNodeRef && this.srcNodeRef.innerHTML){
+			this.isLoaded = true;
+		}
+	},
+
+	buildRendering: function(){
+		// Overrides Widget.buildRendering().
+		// Since we have no template we need to set this.containerNode ourselves.
+		// For subclasses of ContentPane do have a template, does nothing.
+		this.inherited(arguments);
+		if(!this.containerNode){
+			// make getDescendants() work
+			this.containerNode = this.domNode;
+		}
+	},
+
+	postCreate: function(){
+		// remove the title attribute so it doesn't show up when hovering
+		// over a node
+		this.domNode.title = "";
+
+		if (!dojo.attr(this.domNode,"role")){
+			dijit.setWaiRole(this.domNode, "group");
+		}
+
+		dojo.addClass(this.domNode, this.baseClass);
+	},
+
+	startup: function(){
+		// summary:
+		//		See `dijit.layout._LayoutWidget.startup` for description.
+		//		Although ContentPane doesn't extend _LayoutWidget, it does implement
+		//		the same API.
+		if(this._started){ return; }
+
+		if(this.isLoaded){
+			dojo.forEach(this.getChildren(), function(child){
+				child.startup();
+			});
+
+			// If we have static content in the content pane (specified during
+			// initialization) then we need to do layout now... unless we are
+			// a child of a TabContainer etc. in which case wait until the TabContainer
+			// calls resize() on us.
+			if(this.doLayout){
+				this._checkIfSingleChild();
+			}
+			if(!this._singleChild || !dijit._Contained.prototype.getParent.call(this)){
+				this._scheduleLayout();
+			}
+		}
+		
+		// If we have an href then check if we should load it now
+		this._loadCheck();
+
+		this.inherited(arguments);
+	},
+
+	_checkIfSingleChild: function(){
+		// summary:
+		//		Test if we have exactly one visible widget as a child,
+		//		and if so assume that we are a container for that widget,
+		//		and should propogate startup() and resize() calls to it.
+		//		Skips over things like data stores since they aren't visible.
+
+		var childNodes = dojo.query(">", this.containerNode),
+			childWidgetNodes = childNodes.filter(function(node){
+				return dojo.hasAttr(node, "dojoType") || dojo.hasAttr(node, "widgetId");
+			}),
+			candidateWidgets = dojo.filter(childWidgetNodes.map(dijit.byNode), function(widget){
+				return widget && widget.domNode && widget.resize;
+			});
+
+		if(
+			// all child nodes are widgets
+			childNodes.length == childWidgetNodes.length &&
+
+			// all but one are invisible (like dojo.data)
+			candidateWidgets.length == 1
+		){
+			this._singleChild = candidateWidgets[0];
+		}else{
+			delete this._singleChild;
+		}
+	},
+
+	setHref: function(/*String|Uri*/ href){
+		// summary:
+		//		Deprecated.   Use attr('href', ...) instead.
+		dojo.deprecated("dijit.layout.ContentPane.setHref() is deprecated. Use attr('href', ...) instead.", "", "2.0");
+		return this.attr("href", href);
+	},
+	_setHrefAttr: function(/*String|Uri*/ href){
+		// summary:
+		//		Hook so attr("href", ...) works.
+		// description:
+		//		Reset the (external defined) content of this pane and replace with new url
+		//		Note: It delays the download until widget is shown if preload is false.
+		//	href:
+		//		url to the page you want to get, must be within the same domain as your mainpage
+
+		// Cancel any in-flight requests (an attr('href') will cancel any in-flight attr('href', ...))
+		this.cancel();
+
+		this.href = href;
+
+		// _setHrefAttr() is called during creation and by the user, after creation.
+		// only in the second case do we actually load the URL; otherwise it's done in startup()
+		if(this._created && (this.preload || this._isShown())){
+			// we return result of refresh() here to avoid code dup. in dojox.layout.ContentPane
+			return this.refresh();
+		}else{
+			// Set flag to indicate that href needs to be loaded the next time the
+			// ContentPane is made visible
+			this._hrefChanged = true;
+		}
+	},
+
+	setContent: function(/*String|DomNode|Nodelist*/data){
+		// summary:
+		//		Deprecated.   Use attr('content', ...) instead.
+		dojo.deprecated("dijit.layout.ContentPane.setContent() is deprecated.  Use attr('content', ...) instead.", "", "2.0");
+		this.attr("content", data);
+	},
+	_setContentAttr: function(/*String|DomNode|Nodelist*/data){
+		// summary:
+		//		Hook to make attr("content", ...) work.
+		//		Replaces old content with data content, include style classes from old content
+		//	data:
+		//		the new Content may be String, DomNode or NodeList
+		//
+		//		if data is a NodeList (or an array of nodes) nodes are copied
+		//		so you can import nodes from another document implicitly
+
+		// clear href so we can't run refresh and clear content
+		// refresh should only work if we downloaded the content
+		this.href = "";
+
+		// Cancel any in-flight requests (an attr('content') will cancel any in-flight attr('href', ...))
+		this.cancel();
+
+		this._setContent(data || "");
+
+		this._isDownloaded = false; // mark that content is from a attr('content') not an attr('href')
+	},
+	_getContentAttr: function(){
+		// summary:
+		//		Hook to make attr("content") work
+		return this.containerNode.innerHTML;
+	},
+
+	cancel: function(){
+		// summary:
+		//		Cancels an in-flight download of content
+		if(this._xhrDfd && (this._xhrDfd.fired == -1)){
+			this._xhrDfd.cancel();
+		}
+		delete this._xhrDfd; // garbage collect
+	},
+
+	uninitialize: function(){
+		if(this._beingDestroyed){
+			this.cancel();
+		}
+	},
+
+	destroyRecursive: function(/*Boolean*/ preserveDom){
+		// summary:
+		//		Destroy the ContentPane and its contents
+
+		// if we have multiple controllers destroying us, bail after the first
+		if(this._beingDestroyed){
+			return;
+		}
+		this._beingDestroyed = true;
+		this.inherited(arguments);
+	},
+
+	resize: function(size){
+		// summary:
+		//		See `dijit.layout._LayoutWidget.resize` for description.
+		//		Although ContentPane doesn't extend _LayoutWidget, it does implement
+		//		the same API.
+
+		dojo.marginBox(this.domNode, size);
+
+		// Compute content box size in case we [later] need to size child
+		// If either height or width wasn't specified by the user, then query node for it.
+		// But note that setting the margin box and then immediately querying dimensions may return
+		// inaccurate results, so try not to depend on it.
+		var node = this.containerNode,
+			mb = dojo.mixin(dojo.marginBox(node), size||{});
+
+		var cb = (this._contentBox = dijit.layout.marginBox2contentBox(node, mb));
+
+		// If we have a single widget child then size it to fit snugly within my borders
+		if(this._singleChild && this._singleChild.resize){
+			// note: if widget has padding this._contentBox will have l and t set,
+			// but don't pass them to resize() or it will doubly-offset the child
+			this._singleChild.resize({w: cb.w, h: cb.h});
+		}
+	},
+
+	_isShown: function(){
+		// summary:
+		//		Returns true if the content is currently shown
+		if("open" in this){
+			return this.open;		// for TitlePane, etc.
+		}else{
+			var node = this.domNode;
+			return (node.style.display != 'none')  && (node.style.visibility != 'hidden') && !dojo.hasClass(node, "dijitHidden");
+		}
+	},
+
+	_onShow: function(){
+		// summary:
+		//		Called when the ContentPane is made visible
+		// description:
+		//		For a plain ContentPane, this is called on initialization, from startup().
+		//		If the ContentPane is a hidden pane of a TabContainer etc., then it's
+		//		called whever the pane is made visible.
+		//
+		//		Does processing necessary, including href download and layout/resize of
+		//		child widget(s)
+
+		if(this._needLayout){
+			// If a layout has been scheduled for when we become visible, do it now
+			this._layoutChildren();
+		}
+
+		// Do lazy-load of URL
+		this._loadCheck();
+
+		// call onShow, if we have one
+		if(this.onShow){
+			this.onShow();
+		}
+	},
+
+	_loadCheck: function(){
+		// summary:
+		//		Call this to load href contents if necessary.
+		// description:
+		//		Call when !ContentPane has been made visible [from prior hidden state],
+		//		or href has been changed, or on startup, etc.
+
+		if(
+			(this.href && !this._xhrDfd) &&		// if there's an href that isn't already being loaded
+			(!this.isLoaded || this._hrefChanged || this.refreshOnShow) && 	// and we need a [re]load
+			(this.preload || this._isShown())	// and now is the time to [re]load
+		){
+			delete this._hrefChanged;
+			this.refresh();
+		}
+	},
+
+	refresh: function(){
+		// summary:
+		//		[Re]download contents of href and display
+		// description:
+		//		1. cancels any currently in-flight requests
+		//		2. posts "loading..." message
+		//		3. sends XHR to download new data
+
+		// cancel possible prior inflight request
+		this.cancel();
+
+		// display loading message
+		this._setContent(this.onDownloadStart(), true);
+
+		var self = this;
+		var getArgs = {
+			preventCache: (this.preventCache || this.refreshOnShow),
+			url: this.href,
+			handleAs: "text"
+		};
+		if(dojo.isObject(this.ioArgs)){
+			dojo.mixin(getArgs, this.ioArgs);
+		}
+
+		var hand = (this._xhrDfd = (this.ioMethod || dojo.xhrGet)(getArgs));
+
+		hand.addCallback(function(html){
+			try{
+				self._isDownloaded = true;
+				self._setContent(html, false);
+				self.onDownloadEnd();
+			}catch(err){
+				self._onError('Content', err); // onContentError
+			}
+			delete self._xhrDfd;
+			return html;
+		});
+
+		hand.addErrback(function(err){
+			if(!hand.canceled){
+				// show error message in the pane
+				self._onError('Download', err); // onDownloadError
+			}
+			delete self._xhrDfd;
+			return err;
+		});
+	},
+
+	_onLoadHandler: function(data){
+		// summary:
+		//		This is called whenever new content is being loaded
+		this.isLoaded = true;
+		try{
+			this.onLoad(data);			
+		}catch(e){
+			console.error('Error '+this.widgetId+' running custom onLoad code: ' + e.message);
+		}
+	},
+
+	_onUnloadHandler: function(){
+		// summary:
+		//		This is called whenever the content is being unloaded
+		this.isLoaded = false;
+		try{
+			this.onUnload();
+		}catch(e){
+			console.error('Error '+this.widgetId+' running custom onUnload code: ' + e.message);
+		}
+	},
+
+	destroyDescendants: function(){
+		// summary:
+		//		Destroy all the widgets inside the ContentPane and empty containerNode
+
+		// Make sure we call onUnload (but only when the ContentPane has real content)
+		if(this.isLoaded){
+			this._onUnloadHandler();
+		}
+
+		// Even if this.isLoaded == false there might still be a "Loading..." message
+		// to erase, so continue...
+
+		// For historical reasons we need to delete all widgets under this.containerNode,
+		// even ones that the user has created manually.
+		var setter = this._contentSetter;
+		dojo.forEach(this.getChildren(), function(widget){
+			if(widget.destroyRecursive){
+				widget.destroyRecursive();
+			}
+		});
+		if(setter){
+			// Most of the widgets in setter.parseResults have already been destroyed, but
+			// things like Menu that have been moved to <body> haven't yet
+			dojo.forEach(setter.parseResults, function(widget){
+				if(widget.destroyRecursive && widget.domNode && widget.domNode.parentNode == dojo.body()){
+					widget.destroyRecursive();
+				}
+			});
+			delete setter.parseResults;
+		}
+		
+		// And then clear away all the DOM nodes
+		dojo.html._emptyNode(this.containerNode);
+	},
+
+	_setContent: function(cont, isFakeContent){
+		// summary: 
+		//		Insert the content into the container node
+
+		// first get rid of child widgets
+		this.destroyDescendants();
+
+		// Delete any state information we have about current contents
+		delete this._singleChild;
+
+		// dojo.html.set will take care of the rest of the details
+		// we provide an overide for the error handling to ensure the widget gets the errors 
+		// configure the setter instance with only the relevant widget instance properties
+		// NOTE: unless we hook into attr, or provide property setters for each property, 
+		// we need to re-configure the ContentSetter with each use
+		var setter = this._contentSetter; 
+		if(! (setter && setter instanceof dojo.html._ContentSetter)) {
+			setter = this._contentSetter = new dojo.html._ContentSetter({
+				node: this.containerNode,
+				_onError: dojo.hitch(this, this._onError),
+				onContentError: dojo.hitch(this, function(e){
+					// fires if a domfault occurs when we are appending this.errorMessage
+					// like for instance if domNode is a UL and we try append a DIV
+					var errMess = this.onContentError(e);
+					try{
+						this.containerNode.innerHTML = errMess;
+					}catch(e){
+						console.error('Fatal '+this.id+' could not change content due to '+e.message, e);
+					}
+				})/*,
+				_onError */
+			});
+		};
+
+		var setterParams = dojo.mixin({
+			cleanContent: this.cleanContent, 
+			extractContent: this.extractContent, 
+			parseContent: this.parseOnLoad 
+		}, this._contentSetterParams || {});
+		
+		dojo.mixin(setter, setterParams); 
+
+		setter.set( (dojo.isObject(cont) && cont.domNode) ? cont.domNode : cont );
+
+		// setter params must be pulled afresh from the ContentPane each time
+		delete this._contentSetterParams;
+
+		if(!isFakeContent){
+			dojo.forEach(this.getChildren(), function(child){
+				child.startup();
+			});
+
+			if(this.doLayout){
+				this._checkIfSingleChild();
+			}
+
+			// Call resize() on each of my child layout widgets,
+			// or resize() on my single child layout widget...
+			// either now (if I'm currently visible)
+			// or when I become visible
+			this._scheduleLayout();
+			
+			this._onLoadHandler(cont);
+		}
+	},
+
+	_onError: function(type, err, consoleText){
+		// shows user the string that is returned by on[type]Error
+		// overide on[type]Error and return your own string to customize
+		var errText = this['on' + type + 'Error'].call(this, err);
+		if(consoleText){
+			console.error(consoleText, err);
+		}else if(errText){// a empty string won't change current content
+			this._setContent(errText, true);
+		}
+	},
+	
+	_scheduleLayout: function(){
+		// summary:
+		//		Call resize() on each of my child layout widgets, either now
+		//		(if I'm currently visible) or when I become visible
+		if(this._isShown()){
+			this._layoutChildren();
+		}else{
+			this._needLayout = true;
+		}
+	},
+
+	_layoutChildren: function(){
+		// summary:
+		//		Since I am a Container widget, each of my children expects me to
+		//		call resize() or layout() on them.
+		// description:
+		//		Should be called on initialization and also whenever we get new content
+		//		(from an href, or from attr('content', ...))... but deferred until
+		//		the ContentPane is visible
+
+		if(this._singleChild && this._singleChild.resize){
+			var cb = this._contentBox || dojo.contentBox(this.containerNode);
+			this._singleChild.resize({w: cb.w, h: cb.h});
+		}else{
+			// All my child widgets are independently sized (rather than matching my size),
+			// but I still need to call resize() on each child to make it layout.
+			dojo.forEach(this.getChildren(), function(widget){
+				if(widget.resize){
+					widget.resize();
+				}
+			});
+		}
+		delete this._needLayout;
+	},
+
+	// EVENT's, should be overide-able
+	onLoad: function(data){
+		// summary:
+		//		Event hook, is called after everything is loaded and widgetified
+		// tags:
+		//		callback
+	},
+
+	onUnload: function(){
+		// summary:
+		//		Event hook, is called before old content is cleared
+		// tags:
+		//		callback
+	},
+
+	onDownloadStart: function(){
+		// summary:
+		//		Called before download starts.
+		// description:
+		//		The string returned by this function will be the html
+		//		that tells the user we are loading something.
+		//		Override with your own function if you want to change text.
+		// tags:
+		//		extension
+		return this.loadingMessage;
+	},
+
+	onContentError: function(/*Error*/ error){
+		// summary:
+		//		Called on DOM faults, require faults etc. in content.
+		//
+		//		In order to display an error message in the pane, return
+		//		the error message from this method, as an HTML string.
+		//
+		//		By default (if this method is not overriden), it returns
+		//		nothing, so the error message is just printed to the console.
+		// tags:
+		//		extension
+	},
+
+	onDownloadError: function(/*Error*/ error){
+		// summary:
+		//		Called when download error occurs.
+		//
+		//		In order to display an error message in the pane, return
+		//		the error message from this method, as an HTML string.
+		//
+		//		Default behavior (if this method is not overriden) is to display
+		//		the error message inside the pane.
+		// tags:
+		//		extension
+		return this.errorMessage;
+	},
+
+	onDownloadEnd: function(){
+		// summary:
+		//		Called when download is finished.
+		// tags:
+		//		callback
+	}
+});
+
+}
+
+if(!dojo._hasResource["dijit.TooltipDialog"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.TooltipDialog"] = true;
+dojo.provide("dijit.TooltipDialog");
+
+
+
+
+
+
+dojo.declare(
+		"dijit.TooltipDialog",
+		[dijit.layout.ContentPane, dijit._Templated, dijit.form._FormMixin, dijit._DialogMixin],
+		{
+			// summary:
+			//		Pops up a dialog that appears like a Tooltip
+
+			// title: String
+			// 		Description of tooltip dialog (required for a11y)
+			title: "",
+
+			// doLayout: [protected] Boolean
+			//		Don't change this parameter from the default value.
+			//		This ContentPane parameter doesn't make sense for TooltipDialog, since TooltipDialog
+			//		is never a child of a layout container, nor can you specify the size of
+			//		TooltipDialog in order to control the size of an inner widget. 
+			doLayout: false,
+
+			// autofocus: Boolean
+			// 		A Toggle to modify the default focus behavior of a Dialog, which
+			// 		is to focus on the first dialog element after opening the dialog.
+			//		False will disable autofocusing. Default: true
+			autofocus: true,
+
+			// baseClass: [protected] String
+			//		The root className to use for the various states of this widget
+			baseClass: "dijitTooltipDialog",
+
+			// _firstFocusItem: [private] [readonly] DomNode
+			//		The pointer to the first focusable node in the dialog.
+			//		Set by `dijit._DialogMixin._getFocusItems`.
+			_firstFocusItem: null,
+
+			// _lastFocusItem: [private] [readonly] DomNode
+			//		The pointer to which node has focus prior to our dialog.
+			//		Set by `dijit._DialogMixin._getFocusItems`.
+			_lastFocusItem: null,
+
+			templateString: null,
+			templateString:"<div waiRole=\"presentation\">\n\t<div class=\"dijitTooltipContainer\" waiRole=\"presentation\">\n\t\t<div class =\"dijitTooltipContents dijitTooltipFocusNode\" dojoAttachPoint=\"containerNode\" tabindex=\"-1\" waiRole=\"dialog\"></div>\n\t</div>\n\t<div class=\"dijitTooltipConnector\" waiRole=\"presentation\"></div>\n</div>\n",
+
+			postCreate: function(){
+				this.inherited(arguments);
+				this.connect(this.containerNode, "onkeypress", "_onKey");
+				this.containerNode.title = this.title;
+			},
+
+			orient: function(/*DomNode*/ node, /*String*/ aroundCorner, /*String*/ corner){
+				// summary:
+				//		Configure widget to be displayed in given position relative to the button.
+				//		This is called from the dijit.popup code, and should not be called
+				//		directly.
+				// tags:
+				//		protected
+				var c = this._currentOrientClass;
+				if(c){
+					dojo.removeClass(this.domNode, c);
+				}
+				c = "dijitTooltipAB"+(corner.charAt(1)=='L'?"Left":"Right")+" dijitTooltip"+(corner.charAt(0)=='T' ? "Below" : "Above");
+				dojo.addClass(this.domNode, c);
+				this._currentOrientClass = c;
+			},
+
+			onOpen: function(/*Object*/ pos){
+				// summary:
+				//		Called when dialog is displayed.
+				//		This is called from the dijit.popup code, and should not be called directly.
+				// tags:
+				//		protected
+			
+				this.orient(this.domNode,pos.aroundCorner, pos.corner);
+				this._onShow(); // lazy load trigger
+				
+				if(this.autofocus){
+					this._getFocusItems(this.containerNode);
+					dijit.focus(this._firstFocusItem);
+				}
+			},
+			
+			_onKey: function(/*Event*/ evt){
+				// summary:
+				//		Handler for keyboard events
+				// description:
+				//		Keep keyboard focus in dialog; close dialog on escape key
+				// tags:
+				//		private
+
+				var node = evt.target;
+				var dk = dojo.keys;
+				if (evt.charOrCode === dk.TAB){
+					this._getFocusItems(this.containerNode);
+				}
+				var singleFocusItem = (this._firstFocusItem == this._lastFocusItem);
+				if(evt.charOrCode == dk.ESCAPE){
+					this.onCancel();
+					dojo.stopEvent(evt);
+				}else if(node == this._firstFocusItem && evt.shiftKey && evt.charOrCode === dk.TAB){
+					if(!singleFocusItem){
+						dijit.focus(this._lastFocusItem); // send focus to last item in dialog
+					}
+					dojo.stopEvent(evt);
+				}else if(node == this._lastFocusItem && evt.charOrCode === dk.TAB && !evt.shiftKey){
+					if(!singleFocusItem){
+						dijit.focus(this._firstFocusItem); // send focus to first item in dialog
+					}
+					dojo.stopEvent(evt);
+				}else if(evt.charOrCode === dk.TAB){
+					// we want the browser's default tab handling to move focus
+					// but we don't want the tab to propagate upwards
+					evt.stopPropagation();
+				}
+			}
+		}	
+	);
+
+}
+
+if(!dojo._hasResource["dijit.Dialog"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.Dialog"] = true;
+dojo.provide("dijit.Dialog");
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*=====
+dijit._underlay = function(kwArgs){
+	// summary:
+	//		A shared instance of a `dijit.DialogUnderlay`
+	//
+	// description: 
+	//		A shared instance of a `dijit.DialogUnderlay` created and
+	//		used by `dijit.Dialog`, though never created until some Dialog
+	//		or subclass thereof is shown.
+};
+=====*/
+
+dojo.declare(
+	"dijit.Dialog",
+	[dijit.layout.ContentPane, dijit._Templated, dijit.form._FormMixin, dijit._DialogMixin],
+	{
+		// summary:
+		//		A modal dialog Widget
+		//
+		// description:
+		//		Pops up a modal dialog window, blocking access to the screen
+		//		and also graying out the screen Dialog is extended from
+		//		ContentPane so it supports all the same parameters (href, etc.)
+		//
+		// example:
+		// |	<div dojoType="dijit.Dialog" href="test.html"></div>
+		//
+		// example:
+		// |	var foo = new dijit.Dialog({ title: "test dialog", content: "test content" };
+		// |	dojo.body().appendChild(foo.domNode);
+		// |	foo.startup();
+		
+		templateString: null,
+		templateString:"<div class=\"dijitDialog\" tabindex=\"-1\" waiRole=\"dialog\" waiState=\"labelledby-${id}_title\">\n\t<div dojoAttachPoint=\"titleBar\" class=\"dijitDialogTitleBar\">\n\t<span dojoAttachPoint=\"titleNode\" class=\"dijitDialogTitle\" id=\"${id}_title\"></span>\n\t<span dojoAttachPoint=\"closeButtonNode\" class=\"dijitDialogCloseIcon\" dojoAttachEvent=\"onclick: onCancel, onmouseenter: _onCloseEnter, onmouseleave: _onCloseLeave\" title=\"${buttonCancel}\">\n\t\t<span dojoAttachPoint=\"closeText\" class=\"closeText\" title=\"${buttonCancel}\">x</span>\n\t</span>\n\t</div>\n\t\t<div dojoAttachPoint=\"containerNode\" class=\"dijitDialogPaneContent\"></div>\n</div>\n",
+		attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
+			title: [
+				{ node: "titleNode", type: "innerHTML" }, 
+				{ node: "titleBar", type: "attribute" }
+			]
+		}),
+
+		// open: Boolean
+		//		True if Dialog is currently displayed on screen.
+		open: false,
+
+		// duration: Integer
+		//		The time in milliseconds it takes the dialog to fade in and out
+		duration: dijit.defaultDuration,
+
+		// refocus: Boolean
+		// 		A Toggle to modify the default focus behavior of a Dialog, which
+		// 		is to re-focus the element which had focus before being opened.
+		//		False will disable refocusing. Default: true
+		refocus: true,
+		
+		// autofocus: Boolean
+		// 		A Toggle to modify the default focus behavior of a Dialog, which
+		// 		is to focus on the first dialog element after opening the dialog.
+		//		False will disable autofocusing. Default: true
+		autofocus: true,
+
+		// _firstFocusItem: [private] [readonly] DomNode
+		//		The pointer to the first focusable node in the dialog.
+		//		Set by `dijit._DialogMixin._getFocusItems`.
+		_firstFocusItem: null,
+		
+		// _lastFocusItem: [private] [readonly] DomNode
+		//		The pointer to which node has focus prior to our dialog.
+		//		Set by `dijit._DialogMixin._getFocusItems`.
+		_lastFocusItem: null,
+
+		// doLayout: [protected] Boolean
+		//		Don't change this parameter from the default value.
+		//		This ContentPane parameter doesn't make sense for Dialog, since Dialog
+		//		is never a child of a layout container, nor can you specify the size of
+		//		Dialog in order to control the size of an inner widget. 
+		doLayout: false,
+
+		// draggable: Boolean
+		//		Toggles the moveable aspect of the Dialog. If true, Dialog
+		//		can be dragged by it's title. If false it will remain centered
+		//		in the viewport.
+		draggable: true,
+
+		// _fixSizes: Boolean
+		//		Does this Dialog attempt to restore the width and height after becoming too small?
+		_fixSizes: true,
+
+		postMixInProperties: function(){
+			var _nlsResources = dojo.i18n.getLocalization("dijit", "common");
+			dojo.mixin(this, _nlsResources);
+			this.inherited(arguments);
+		},
+
+		postCreate: function(){
+			dojo.style(this.domNode, {
+				visibility:"hidden",
+				position:"absolute",
+				display:"",
+				top:"-9999px"
+			});
+			dojo.body().appendChild(this.domNode);
+
+			this.inherited(arguments);
+
+			this.connect(this, "onExecute", "hide");
+			this.connect(this, "onCancel", "hide");
+			this._modalconnects = [];
+		},
+
+		onLoad: function(){
+			// summary:
+			//		Called when data has been loaded from an href.
+			//		Unlike most other callbacks, this function can be connected to (via `dojo.connect`)
+			//		but should *not* be overriden.
+			// tags:
+			//		callback
+			
+			// when href is specified we need to reposition the dialog after the data is loaded
+			this._position();
+			this.inherited(arguments);
+		},
+
+		_endDrag: function(e){
+			// summary:
+			//		Called after dragging the Dialog. Calculates the relative offset
+			//		of the Dialog in relation to the viewport.
+			// tags:
+			//		private
+			if(e && e.node && e.node === this.domNode){
+				var vp = dijit.getViewport(); 
+				var p = e._leftTop || dojo.coords(e.node,true);
+				this._relativePosition = {
+					t: p.t - vp.t,
+					l: p.l - vp.l
+				}			
+			}
+		},
+		
+		_setup: function(){
+			// summary: 
+			//		Stuff we need to do before showing the Dialog for the first
+			//		time (but we defer it until right beforehand, for
+			//		performance reasons).
+			// tags:
+			//		private
+
+			var node = this.domNode;
+
+			if(this.titleBar && this.draggable){
+				this._moveable = (dojo.isIE == 6) ?
+					new dojo.dnd.TimedMoveable(node, { handle: this.titleBar }) :	// prevent overload, see #5285
+					new dojo.dnd.Moveable(node, { handle: this.titleBar, timeout: 0 });
+				dojo.subscribe("/dnd/move/stop",this,"_endDrag");
+			}else{
+				dojo.addClass(node,"dijitDialogFixed"); 
+			}
+			
+			var underlayAttrs = {
+				dialogId: this.id,
+				"class": dojo.map(this["class"].split(/\s/), function(s){ return s+"_underlay"; }).join(" ")
+			};
+			
+			var underlay = dijit._underlay;
+			if(!underlay){ 
+				underlay = dijit._underlay = new dijit.DialogUnderlay(underlayAttrs); 
+			}
+			
+			this._fadeIn = dojo.fadeIn({
+				node: node,
+				duration: this.duration,
+				beforeBegin: function(){
+					underlay.attr(underlayAttrs);
+					underlay.show();
+				},
+				onEnd:	dojo.hitch(this, function(){
+					if(this.autofocus){
+						// find focusable Items each time dialog is shown since if dialog contains a widget the 
+						// first focusable items can change
+						this._getFocusItems(this.domNode);
+						dijit.focus(this._firstFocusItem);
+					}
+				})
+			 });
+
+			this._fadeOut = dojo.fadeOut({
+				node: node,
+				duration: this.duration,
+				onEnd: function(){
+					node.style.visibility="hidden";
+					node.style.top = "-9999px";
+					dijit._underlay.hide();
+				}
+			 });
+		},
+
+		uninitialize: function(){
+			var wasPlaying = false;
+			if(this._fadeIn && this._fadeIn.status() == "playing"){
+				wasPlaying = true;
+				this._fadeIn.stop();
+			}
+			if(this._fadeOut && this._fadeOut.status() == "playing"){
+				wasPlaying = true;
+				this._fadeOut.stop();
+			}
+			if(this.open || wasPlaying){
+				dijit._underlay.hide();
+			}
+			if(this._moveable){
+				this._moveable.destroy();
+			}
+		},
+
+		_size: function(){
+			// summary:
+			// 		Make sure the dialog is small enough to fit in viewport.
+			// tags:
+			//		private
+
+			var mb = dojo.marginBox(this.domNode);
+			var viewport = dijit.getViewport();
+			if(mb.w >= viewport.w || mb.h >= viewport.h){
+				dojo.style(this.containerNode, {
+					width: Math.min(mb.w, Math.floor(viewport.w * 0.75))+"px",
+					height: Math.min(mb.h, Math.floor(viewport.h * 0.75))+"px",
+					overflow: "auto",
+					position: "relative"	// workaround IE bug moving scrollbar or dragging dialog
+				});
+			}
+		},
+
+		_position: function(){
+			// summary:
+			//		Position modal dialog in the viewport. If no relative offset
+			//		in the viewport has been determined (by dragging, for instance),
+			//		center the node. Otherwise, use the Dialog's stored relative offset,
+			//		and position the node to top: left: values based on the viewport.
+			// tags:
+			//		private
+			if(!dojo.hasClass(dojo.body(),"dojoMove")){
+				var node = this.domNode;
+				var viewport = dijit.getViewport();
+					var p = this._relativePosition;
+					var mb = p ? null : dojo.marginBox(node);
+					dojo.style(node,{
+						left: Math.floor(viewport.l + (p ? p.l : (viewport.w - mb.w) / 2)) + "px",
+						top: Math.floor(viewport.t + (p ? p.t : (viewport.h - mb.h) / 2)) + "px"
+					});
+				}
+
+		},
+
+		_onKey: function(/*Event*/ evt){
+			// summary:
+			//		Handles the keyboard events for accessibility reasons
+			// tags:
+			//		private
+			if(evt.charOrCode){
+				var dk = dojo.keys;
+				var node = evt.target;
+				if (evt.charOrCode === dk.TAB){
+					this._getFocusItems(this.domNode);
+				}
+				var singleFocusItem = (this._firstFocusItem == this._lastFocusItem);
+				// see if we are shift-tabbing from first focusable item on dialog
+				if(node == this._firstFocusItem && evt.shiftKey && evt.charOrCode === dk.TAB){
+					if(!singleFocusItem){
+						dijit.focus(this._lastFocusItem); // send focus to last item in dialog
+					}
+					dojo.stopEvent(evt);
+				}else if(node == this._lastFocusItem && evt.charOrCode === dk.TAB && !evt.shiftKey){
+					if (!singleFocusItem){
+						dijit.focus(this._firstFocusItem); // send focus to first item in dialog
+					}
+					dojo.stopEvent(evt);
+				}else{
+					// see if the key is for the dialog
+					while(node){
+						if(node == this.domNode){
+							if(evt.charOrCode == dk.ESCAPE){
+								this.onCancel(); 
+							}else{
+								return; // just let it go
+							}
+						}
+						node = node.parentNode;
+					}
+					// this key is for the disabled document window
+					if(evt.charOrCode !== dk.TAB){ // allow tabbing into the dialog for a11y
+						dojo.stopEvent(evt);
+					// opera won't tab to a div
+					}else if(!dojo.isOpera){
+						try{
+							this._firstFocusItem.focus();
+						}catch(e){ /*squelch*/ }
+					}
+				}
+			}
+		},
+
+		show: function(){
+			// summary:
+			//		Display the dialog
+			if(this.open){ return; }
+			
+			// first time we show the dialog, there's some initialization stuff to do			
+			if(!this._alreadyInitialized){
+				this._setup();
+				this._alreadyInitialized=true;
+			}
+
+			if(this._fadeOut.status() == "playing"){
+				this._fadeOut.stop();
+			}
+
+			this._modalconnects.push(dojo.connect(window, "onscroll", this, "layout"));
+			this._modalconnects.push(dojo.connect(window, "onresize", this, function(){
+				// IE gives spurious resize events and can actually get stuck
+				// in an infinite loop if we don't ignore them
+				var viewport = dijit.getViewport();
+				if(!this._oldViewport ||
+						viewport.h != this._oldViewport.h ||
+						viewport.w != this._oldViewport.w){
+					this.layout();
+					this._oldViewport = viewport;
+				}
+			}));
+			this._modalconnects.push(dojo.connect(dojo.doc.documentElement, "onkeypress", this, "_onKey"));
+
+			dojo.style(this.domNode, {
+				opacity:0,
+				visibility:""
+			});
+			
+			if(this._fixSizes){
+				dojo.style(this.containerNode, { // reset width and height so that _size():marginBox works correctly
+					width:"auto",
+					height:"auto"
+				});
+			}
+			
+			this.open = true;
+			this._onShow(); // lazy load trigger
+
+			this._size();
+			this._position();
+
+			this._fadeIn.play();
+
+			this._savedFocus = dijit.getFocus(this);
+		},
+
+		hide: function(){
+			// summary:
+			//		Hide the dialog
+
+			// if we haven't been initialized yet then we aren't showing and we can just return		
+			if(!this._alreadyInitialized){
+				return;
+			}
+
+			if(this._fadeIn.status() == "playing"){
+				this._fadeIn.stop();
+			}
+			this._fadeOut.play();
+
+			if (this._scrollConnected){
+				this._scrollConnected = false;
+			}
+			dojo.forEach(this._modalconnects, dojo.disconnect);
+			this._modalconnects = [];
+			if(this.refocus){
+				this.connect(this._fadeOut,"onEnd",dojo.hitch(dijit,"focus",this._savedFocus));
+			}
+			if(this._relativePosition){
+				delete this._relativePosition;	
+			}
+			this.open = false;
+		},
+
+		layout: function() {
+			// summary:
+			//		Position the Dialog and the underlay
+			// tags:
+			//		private
+			if(this.domNode.style.visibility != "hidden"){
+				dijit._underlay.layout();
+				this._position();
+			}
+		},
+		
+		destroy: function(){
+			dojo.forEach(this._modalconnects, dojo.disconnect);
+			if(this.refocus && this.open){
+				setTimeout(dojo.hitch(dijit,"focus",this._savedFocus), 25);
+			}
+			this.inherited(arguments);			
+		},
+
+		_onCloseEnter: function(){
+			// summary:
+			//		Called when user hovers over close icon
+			// tags:
+			//		private
+			dojo.addClass(this.closeButtonNode, "dijitDialogCloseIcon-hover");
+		},
+
+		_onCloseLeave: function(){
+			// summary:
+			//		Called when user stops hovering over close icon
+			// tags:
+			//		private
+			dojo.removeClass(this.closeButtonNode, "dijitDialogCloseIcon-hover");
+		}
+	}
+);
+
+// For back-compat.  TODO: remove in 2.0
+
+
+
+}
+
+if(!dojo._hasResource["dijit._KeyNavContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._KeyNavContainer"] = true;
+dojo.provide("dijit._KeyNavContainer");
+
+
+dojo.declare("dijit._KeyNavContainer",
+	[dijit._Container],
+	{
+
+		// summary:
+		//		A _Container with keyboard navigation of its children.
+		// description:
+		//		To use this mixin, call connectKeyNavHandlers() in
+		//		postCreate() and call startupKeyNavChildren() in startup().
+		//		It provides normalized keyboard and focusing code for Container
+		//		widgets.
+/*=====
+		// focusedChild: [protected] Widget
+		//		The currently focused child widget, or null if there isn't one
+		focusedChild: null,
+=====*/
+
+		// tabIndex: Integer
+		//		Tab index of the container; same as HTML tabindex attribute.
+		//		Note then when user tabs into the container, focus is immediately
+		//		moved to the first item in the container.
+		tabIndex: "0",
+
+
+		_keyNavCodes: {},
+
+		connectKeyNavHandlers: function(/*dojo.keys[]*/ prevKeyCodes, /*dojo.keys[]*/ nextKeyCodes){
+			// summary:
+			//		Call in postCreate() to attach the keyboard handlers
+			//		to the container.
+			// preKeyCodes: dojo.keys[]
+			//		Key codes for navigating to the previous child.
+			// nextKeyCodes: dojo.keys[]
+			//		Key codes for navigating to the next child.
+			// tags:
+			//		protected
+
+			var keyCodes = this._keyNavCodes = {};
+			var prev = dojo.hitch(this, this.focusPrev);
+			var next = dojo.hitch(this, this.focusNext);
+			dojo.forEach(prevKeyCodes, function(code){ keyCodes[code] = prev; });
+			dojo.forEach(nextKeyCodes, function(code){ keyCodes[code] = next; });
+			this.connect(this.domNode, "onkeypress", "_onContainerKeypress");
+			this.connect(this.domNode, "onfocus", "_onContainerFocus");
+		},
+
+		startupKeyNavChildren: function(){
+			// summary:
+			//		Call in startup() to set child tabindexes to -1
+			// tags:
+			//		protected
+			dojo.forEach(this.getChildren(), dojo.hitch(this, "_startupChild"));
+		},
+
+		addChild: function(/*Widget*/ widget, /*int?*/ insertIndex){
+			// summary:
+			//		Add a child to our _Container
+			dijit._KeyNavContainer.superclass.addChild.apply(this, arguments);
+			this._startupChild(widget);
+		},
+
+		focus: function(){
+			// summary:
+			//		Default focus() implementation: focus the first child.
+			this.focusFirstChild();
+		},
+
+		focusFirstChild: function(){
+			// summary:
+			//		Focus the first focusable child in the container.
+			// tags:
+			//		protected
+			this.focusChild(this._getFirstFocusableChild());
+		},
+
+		focusNext: function(){
+			// summary:
+			//		Focus the next widget or focal node (for widgets
+			//		with multiple focal nodes) within this container.
+			// tags:
+			//		protected
+			if(this.focusedChild && this.focusedChild.hasNextFocalNode
+					&& this.focusedChild.hasNextFocalNode()){
+				this.focusedChild.focusNext();
+				return;
+			}
+			var child = this._getNextFocusableChild(this.focusedChild, 1);
+			if(child.getFocalNodes){
+				this.focusChild(child, child.getFocalNodes()[0]);
+			}else{
+				this.focusChild(child);
+			}
+		},
+
+		focusPrev: function(){
+			// summary:
+			//		Focus the previous widget or focal node (for widgets
+			//		with multiple focal nodes) within this container.
+			// tags:
+			//		protected
+			if(this.focusedChild && this.focusedChild.hasPrevFocalNode
+					&& this.focusedChild.hasPrevFocalNode()){
+				this.focusedChild.focusPrev();
+				return;
+			}
+			var child = this._getNextFocusableChild(this.focusedChild, -1);
+			if(child.getFocalNodes){
+				var nodes = child.getFocalNodes();
+				this.focusChild(child, nodes[nodes.length-1]);
+			}else{
+				this.focusChild(child);
+			}
+		},
+
+		focusChild: function(/*Widget*/ widget, /*Node?*/ node){
+			// summary:
+			//		Focus widget. Optionally focus 'node' within widget.
+			// tags:
+			//		protected
+			if(widget){
+				if(this.focusedChild && widget !== this.focusedChild){
+					this._onChildBlur(this.focusedChild);
+				}
+				this.focusedChild = widget;
+				if(node && widget.focusFocalNode){
+					widget.focusFocalNode(node);
+				}else{
+					widget.focus();
+				}
+			}
+		},
+
+		_startupChild: function(/*Widget*/ widget){
+			// summary:
+			//		Set tabindex="-1" on focusable widgets so that we
+			// 		can focus them programmatically and by clicking.
+			//		Connect focus and blur handlers.
+			// tags:
+			//		private
+			if(widget.getFocalNodes){
+				dojo.forEach(widget.getFocalNodes(), function(node){
+					dojo.attr(node, "tabindex", -1);
+					this._connectNode(node);
+				}, this);
+			}else{
+				var node = widget.focusNode || widget.domNode;
+				if(widget.isFocusable()){
+					dojo.attr(node, "tabindex", -1);
+				}
+				this._connectNode(node);
+			}
+		},
+
+		_connectNode: function(/*Element*/ node){
+			// summary:
+			//		Monitor focus and blur events on the node
+			// tags:
+			//		private
+			this.connect(node, "onfocus", "_onNodeFocus");
+			this.connect(node, "onblur", "_onNodeBlur");
+		},
+
+		_onContainerFocus: function(evt){
+			// summary:
+			//		Handler for when the container gets focus
+			// description:
+			//		Initially the container itself has a tabIndex, but when it gets
+			//		focus, switch focus to first child...
+			// tags:
+			//		private
+
+			// Note that we can't use _onFocus() because switching focus from the
+			// _onFocus() handler confuses the focus.js code
+			// (because it causes _onFocusNode() to be called recursively)
+
+			// focus bubbles on Firefox,
+			// so just make sure that focus has really gone to the container
+			if(evt.target !== this.domNode){ return; }
+
+			this.focusFirstChild();
+			
+			// and then remove the container's tabIndex,
+			// so that tab or shift-tab will go to the fields after/before
+			// the container, rather than the container itself
+			dojo.removeAttr(this.domNode, "tabIndex");
+		},
+
+		_onBlur: function(evt){
+			// When focus is moved away the container, and it's descendant (popup) widgets,
+			// then restore the container's tabIndex so that user can tab to it again.
+			// Note that using _onBlur() so that this doesn't happen when focus is shifted
+			// to one of my child widgets (typically a popup)
+			if(this.tabIndex){
+				dojo.attr(this.domNode, "tabindex", this.tabIndex);
+			}
+			// TODO: this.inherited(arguments);
+		},
+
+		_onContainerKeypress: function(evt){
+			// summary:
+			//		When a key is pressed, if it's an arrow key etc. then
+			//		it's handled here.
+			// tags:
+			//		private
+			if(evt.ctrlKey || evt.altKey){ return; }
+			var func = this._keyNavCodes[evt.charOrCode];
+			if(func){
+				func();
+				dojo.stopEvent(evt);
+			}
+		},
+
+		_onNodeFocus: function(evt){
+			// summary:
+			//		Handler for onfocus event on a child node
+			// tags:
+			//		private
+
+			// record the child that has been focused
+			var widget = dijit.getEnclosingWidget(evt.target);
+			if(widget && widget.isFocusable()){
+				this.focusedChild = widget;
+			}
+			dojo.stopEvent(evt);
+		},
+
+		_onNodeBlur: function(evt){
+			// summary:
+			//		Handler for onblur event on a child node
+			// tags:
+			//		private
+			dojo.stopEvent(evt);
+		},
+
+		_onChildBlur: function(/*Widget*/ widget){
+			// summary:
+			//		Called when focus leaves a child widget to go
+			//		to a sibling widget.
+			// tags:
+			//		protected
+		},
+
+		_getFirstFocusableChild: function(){
+			// summary:
+			//		Returns first child that can be focused
+			return this._getNextFocusableChild(null, 1);
+		},
+
+		_getNextFocusableChild: function(child, dir){
+			// summary:
+			//		Returns the next or previous focusable child, compared
+			//		to "child"
+			// child: Widget
+			//		The current widget
+			// dir: Integer
+			//		* 1 = after
+			//		* -1 = before
+			if(child){
+				child = this._getSiblingOfChild(child, dir);
+			}
+			var children = this.getChildren();
+			for(var i=0; i < children.length; i++){
+				if(!child){
+					child = children[(dir>0) ? 0 : (children.length-1)];
+				}
+				if(child.isFocusable()){
+					return child;
+				}
+				child = this._getSiblingOfChild(child, dir);
+			}
+			// no focusable child found
+			return null;
+		}
+	}
+);
+
+}
+
+if(!dojo._hasResource["dijit.MenuItem"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.MenuItem"] = true;
+dojo.provide("dijit.MenuItem");
+
+
+
+
+
+dojo.declare("dijit.MenuItem",
+		[dijit._Widget, dijit._Templated, dijit._Contained],
+		{
+		// summary:
+		//		A line item in a Menu Widget
+
+		// Make 3 columns
+		// icon, label, and expand arrow (BiDi-dependent) indicating sub-menu
+		templateString:"<tr class=\"dijitReset dijitMenuItem\" dojoAttachPoint=\"focusNode\" waiRole=\"menuitem\" tabIndex=\"-1\"\n\t\tdojoAttachEvent=\"onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick\">\n\t<td class=\"dijitReset\" waiRole=\"presentation\">\n\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitMenuItemIcon\" dojoAttachPoint=\"iconNode\">\n\t</td>\n\t<td class=\"dijitReset dijitMenuItemLabel\" colspan=\"2\" dojoAttachPoint=\"containerNode\"></td>\n\t<td class=\"dijitReset dijitMenuItemAccelKey\" style=\"display: none\" dojoAttachPoint=\"accelKeyNode\"></td>\n\t<td class=\"dijitReset dijitMenuArrowCell\" waiRole=\"presentation\">\n\t\t<div dojoAttachPoint=\"arrowWrapper\" style=\"visibility: hidden\">\n\t\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitMenuExpand\">\n\t\t\t<span class=\"dijitMenuExpandA11y\">+</span>\n\t\t</div>\n\t</td>\n</tr>\n",
+
+		attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
+			label: { node: "containerNode", type: "innerHTML" },
+			iconClass: { node: "iconNode", type: "class" }
+		}),
+
+		// label: String
+		//		Menu text
+		label: '',
+
+		// iconClass: String
+		//		Class to apply to DOMNode to make it display an icon.
+		iconClass: "",
+
+		// accelKey: String
+		//		Text for the accelerator (shortcut) key combination.
+		//		Note that although Menu can display accelerator keys there
+		//		is no infrastructure to actually catch and execute these
+		//		accelerators.
+		accelKey: "",
+
+		// disabled: Boolean
+		//		If true, the menu item is disabled.
+		//		If false, the menu item is enabled.
+		disabled: false,
+
+		_fillContent: function(/*DomNode*/ source){
+			// If button label is specified as srcNodeRef.innerHTML rather than
+			// this.params.label, handle it here.
+			if(source && !("label" in this.params)){
+				this.attr('label', source.innerHTML);
+			}
+		},
+
+		postCreate: function(){
+			dojo.setSelectable(this.domNode, false);
+			dojo.attr(this.containerNode, "id", this.id+"_text");
+			dijit.setWaiState(this.domNode, "labelledby", this.id+"_text");
+		},
+
+		_onHover: function(){
+			// summary:
+			//		Handler when mouse is moved onto menu item
+			// tags:
+			//		protected
+			dojo.addClass(this.domNode, 'dijitMenuItemHover');
+			this.getParent().onItemHover(this);
+		},
+
+		_onUnhover: function(){
+			// summary:
+			//		Handler when mouse is moved off of menu item,
+			//		possibly to a child menu, or maybe to a sibling
+			//		menuitem or somewhere else entirely.
+			// tags:
+			//		protected
+
+			// if we are unhovering the currently selected item
+			// then unselect it
+			dojo.removeClass(this.domNode, 'dijitMenuItemHover');
+			this.getParent().onItemUnhover(this);
+		},
+
+		_onClick: function(evt){
+			// summary:
+			//		Internal handler for click events on MenuItem.
+			// tags:
+			//		private
+			this.getParent().onItemClick(this, evt);
+			dojo.stopEvent(evt);
+		},
+
+		onClick: function(/*Event*/ evt){
+			// summary:
+			//		User defined function to handle clicks
+			// tags:
+			//		callback
+		},
+
+		focus: function(){
+			// summary:
+			//		Focus on this MenuItem
+			try{
+				dijit.focus(this.focusNode);
+			}catch(e){
+				// this throws on IE (at least) in some scenarios
+			}
+		},
+
+		_onFocus: function(){
+			// summary:
+			//		This is called by the focus manager when focus
+			//		goes to this MenuItem or a child menu.
+			// tags:
+			//		protected
+			this._setSelected(true);
+
+			// TODO: this.inherited(arguments);
+		},
+
+		_setSelected: function(selected){
+			// summary:
+			//		Indicate that this node is the currently selected one
+			// tags:
+			//		private
+
+			/***
+			 * TODO: remove this method and calls to it, when _onBlur() is working for MenuItem.
+			 * Currently _onBlur() gets called when focus is moved from the MenuItem to a child menu.
+			 * That's not supposed to happen, but the problem is:
+			 * In order to allow dijit.popup's getTopPopup() to work,a sub menu's popupParent
+			 * points to the parent Menu, bypassing the parent MenuItem... thus the
+			 * MenuItem is not in the chain of active widgets and gets a premature call to
+			 * _onBlur()
+			 */
+			
+			dojo.toggleClass(this.domNode, "dijitMenuItemSelected", selected);
+		},
+
+		setLabel: function(/*String*/ content){
+			// summary:
+			//		Deprecated.   Use attr('label', ...) instead.
+			// tags:
+			//		deprecated
+			dojo.deprecated("dijit.MenuItem.setLabel() is deprecated.  Use attr('label', ...) instead.", "", "2.0");
+			this.attr("label", content);
+		},
+
+		setDisabled: function(/*Boolean*/ disabled){
+			// summary:
+			//		Deprecated.   Use attr('disabled', bool) instead.
+			// tags:
+			//		deprecated
+			dojo.deprecated("dijit.Menu.setDisabled() is deprecated.  Use attr('disabled', bool) instead.", "", "2.0");
+			this.attr('disabled', disabled);
+		},
+		_setDisabledAttr: function(/*Boolean*/ value){
+			// summary:
+			//		Hook for attr('disabled', ...) to work.
+			//		Enable or disable this menu item.
+			this.disabled = value;
+			dojo[value ? "addClass" : "removeClass"](this.domNode, 'dijitMenuItemDisabled');
+			dijit.setWaiState(this.focusNode, 'disabled', value ? 'true' : 'false');
+		},
+		_setAccelKeyAttr: function(/*String*/ value){
+			// summary:
+			//		Hook for attr('accelKey', ...) to work.
+			//		Set accelKey on this menu item.
+			this.accelKey=value;
+
+			this.accelKeyNode.style.display=value?"":"none";
+			this.accelKeyNode.innerHTML=value;
+			//have to use colSpan to make it work in IE
+			dojo.attr(this.containerNode,'colSpan',value?"1":"2");
+		}
+	});
+
+}
+
+if(!dojo._hasResource["dijit.PopupMenuItem"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.PopupMenuItem"] = true;
+dojo.provide("dijit.PopupMenuItem");
+
+
+
+dojo.declare("dijit.PopupMenuItem",
+		dijit.MenuItem,
+		{
+		_fillContent: function(){
+			// summary: 
+			//		When Menu is declared in markup, this code gets the menu label and
+			//		the popup widget from the srcNodeRef.
+			// description:
+			//		srcNodeRefinnerHTML contains both the menu item text and a popup widget
+			//		The first part holds the menu item text and the second part is the popup
+			// example: 
+			// |	<div dojoType="dijit.PopupMenuItem">
+			// |		<span>pick me</span>
+			// |		<popup> ... </popup>
+			// |	</div>
+			// tags:
+			//		protected
+
+			if(this.srcNodeRef){
+				var nodes = dojo.query("*", this.srcNodeRef);
+				dijit.PopupMenuItem.superclass._fillContent.call(this, nodes[0]);
+
+				// save pointer to srcNode so we can grab the drop down widget after it's instantiated
+				this.dropDownContainer = this.srcNodeRef;
+			}
+		},
+
+		startup: function(){
+			if(this._started){ return; }
+			this.inherited(arguments);
+
+			// we didn't copy the dropdown widget from the this.srcNodeRef, so it's in no-man's
+			// land now.  move it to dojo.doc.body.
+			if(!this.popup){
+				var node = dojo.query("[widgetId]", this.dropDownContainer)[0];
+				this.popup = dijit.byNode(node);
+			}
+			dojo.body().appendChild(this.popup.domNode);
+
+			this.popup.domNode.style.display="none";
+			if(this.arrowWrapper){
+				dojo.style(this.arrowWrapper, "visibility", "");
+			}
+			dijit.setWaiState(this.focusNode, "haspopup", "true");
+		},
+		
+		destroyDescendants: function(){
+			if(this.popup){
+				this.popup.destroyRecursive();
+				delete this.popup;
+			}
+			this.inherited(arguments);
+		}
+	});
+
+
+}
+
+if(!dojo._hasResource["dijit.CheckedMenuItem"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.CheckedMenuItem"] = true;
+dojo.provide("dijit.CheckedMenuItem");
+
+
+
+dojo.declare("dijit.CheckedMenuItem",
+		dijit.MenuItem,
+		{
+		// summary:
+		//		A checkbox-like menu item for toggling on and off
+		
+		templateString:"<tr class=\"dijitReset dijitMenuItem\" dojoAttachPoint=\"focusNode\" waiRole=\"menuitemcheckbox\" tabIndex=\"-1\"\n\t\tdojoAttachEvent=\"onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick\">\n\t<td class=\"dijitReset\" waiRole=\"presentation\">\n\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitMenuItemIcon dijitCheckedMenuItemIcon\" dojoAttachPoint=\"iconNode\">\n\t\t<span class=\"dijitCheckedMenuItemIconChar\">&#10003;</span>\n\t</td>\n\t<td class=\"dijitReset dijitMenuItemLabel\" colspan=\"2\" dojoAttachPoint=\"containerNode,labelNode\"></td>\n\t<td class=\"dijitReset dijitMenuItemAccelKey\" style=\"display: none\" dojoAttachPoint=\"accelKeyNode\"></td>\n\t<td class=\"dijitReset dijitMenuArrowCell\" waiRole=\"presentation\">\n\t</td>\n</tr>\n",
+
+		// checked: Boolean
+		//		Our checked state
+		checked: false,
+		_setCheckedAttr: function(/*Boolean*/ checked){
+			// summary:
+			//		Hook so attr('checked', bool) works.
+			//		Sets the class and state for the check box.
+			dojo.toggleClass(this.domNode, "dijitCheckedMenuItemChecked", checked);
+			dijit.setWaiState(this.domNode, "checked", checked);
+			this.checked = checked;
+		},
+
+		onChange: function(/*Boolean*/ checked){
+			// summary:
+			//		User defined function to handle check/uncheck events
+			// tags:
+			//		callback
+		},
+
+		_onClick: function(/*Event*/ e){
+			// summary:
+			//		Clicking this item just toggles its state
+			// tags:
+			//		private
+			if(!this.disabled){
+				this.attr("checked", !this.checked);
+				this.onChange(this.checked);
+			}
+			this.inherited(arguments);
+		}
+	});
+
+}
+
+if(!dojo._hasResource["dijit.MenuSeparator"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.MenuSeparator"] = true;
+dojo.provide("dijit.MenuSeparator");
+
+
+
+
+
+dojo.declare("dijit.MenuSeparator",
+		[dijit._Widget, dijit._Templated, dijit._Contained],
+		{
+		// summary:
+		//		A line between two menu items
+
+		templateString:"<tr class=\"dijitMenuSeparator\">\n\t<td colspan=\"4\">\n\t\t<div class=\"dijitMenuSeparatorTop\"></div>\n\t\t<div class=\"dijitMenuSeparatorBottom\"></div>\n\t</td>\n</tr>\n",
+
+		postCreate: function(){
+			dojo.setSelectable(this.domNode, false);
+		},
+		
+		isFocusable: function(){
+			// summary:
+			//		Override to always return false
+			// tags:
+			//		protected
+
+			return false; // Boolean
+		}
+	});
+
+
+}
+
+if(!dojo._hasResource["dijit.Menu"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.Menu"] = true;
+dojo.provide("dijit.Menu");
+
+
+
+
+
+dojo.declare("dijit._MenuBase",
+	[dijit._Widget, dijit._Templated, dijit._KeyNavContainer],
+{
+	// summary:
+	//		Base class for Menu and MenuBar
+
+	// parentMenu: [readonly] Widget
+	//		pointer to menu that displayed me
+	parentMenu: null,
+
+	// popupDelay: Integer
+	//		number of milliseconds before hovering (without clicking) causes the popup to automatically open.
+	popupDelay: 500,
+
+	startup: function(){
+		if(this._started){ return; }
+
+		dojo.forEach(this.getChildren(), function(child){ child.startup(); });
+		this.startupKeyNavChildren();
+
+		this.inherited(arguments);
+	},
+
+	onExecute: function(){
+		// summary:
+		//		Attach point for notification about when a menu item has been executed.
+		//		This is an internal mechanism used for Menus to signal to their parent to
+		//		close them, because they are about to execute the onClick handler.   In
+		//		general developers should not attach to or override this method.
+		// tags:
+		//		protected
+	},
+
+	onCancel: function(/*Boolean*/ closeAll){
+		// summary:
+		//		Attach point for notification about when the user cancels the current menu
+		//		This is an internal mechanism used for Menus to signal to their parent to
+		//		close them.  In general developers should not attach to or override this method.
+		// tags:
+		//		protected
+	},
+
+	_moveToPopup: function(/*Event*/ evt){
+		// summary:
+		//		This handles the right arrow key (left arrow key on RTL systems),
+		//		which will either open a submenu, or move to the next item in the
+		//		ancestor MenuBar
+		// tags:
+		//		private
+
+		if(this.focusedChild && this.focusedChild.popup && !this.focusedChild.disabled){
+			this.focusedChild._onClick(evt);
+		}else{
+			var topMenu = this._getTopMenu();
+			if(topMenu && topMenu._isMenuBar){
+				topMenu.focusNext();
+			}
+		}
+	},
+
+	onItemHover: function(/*MenuItem*/ item){
+		// summary:
+		//		Called when cursor is over a MenuItem.
+		// tags:
+		//		protected
+
+		// Don't do anything unless user has "activated" the menu by:
+		//		1) clicking it
+		//		2) tabbing into it
+		//		3) opening it from a parent menu (which automatically focuses it)
+		if(this.isActive){
+			this.focusChild(item);
+	
+			if(this.focusedChild.popup && !this.focusedChild.disabled && !this.hover_timer){
+				this.hover_timer = setTimeout(dojo.hitch(this, "_openPopup"), this.popupDelay);
+			}
+		}
+	},
+
+	_onChildBlur: function(item){
+		// summary:
+		//		Called when a child MenuItem becomes inactive because focus
+		//		has been removed from the MenuItem *and* it's descendant menus.
+		// tags:
+		//		private
+
+		item._setSelected(false);
+
+		// Close all popups that are open and descendants of this menu
+		dijit.popup.close(item.popup);
+		this._stopPopupTimer();
+	},
+
+	onItemUnhover: function(/*MenuItem*/ item){
+		// summary:
+		//		Callback fires when mouse exits a MenuItem
+		// tags:
+		//		protected
+		if(this.isActive){
+			this._stopPopupTimer();
+		}
+	},
+
+	_stopPopupTimer: function(){
+		// summary:
+		//		Cancels the popup timer because the user has stop hovering
+		//		on the MenuItem, etc.
+		// tags:
+		//		private
+		if(this.hover_timer){
+			clearTimeout(this.hover_timer);
+			this.hover_timer = null;
+		}
+	},
+
+	_getTopMenu: function(){
+		// summary:
+		//		Returns the top menu in this chain of Menus
+		// tags:
+		//		private
+		for(var top=this; top.parentMenu; top=top.parentMenu);
+		return top;
+	},
+
+	onItemClick: function(/*Widget*/ item, /*Event*/ evt){
+		// summary:
+		//		Handle clicks on an item.
+		// tags:
+		//		private
+		if(item.disabled){ return false; }
+
+		this.focusChild(item);
+
+		if(item.popup){
+			if(!this.is_open){
+				this._openPopup();
+			}
+		}else{
+			// before calling user defined handler, close hierarchy of menus
+			// and restore focus to place it was when menu was opened
+			this.onExecute();
+
+			// user defined handler for click
+			item.onClick(evt);
+		}
+	},
+
+	_openPopup: function(){
+		// summary:
+		//		Open the popup to the side of/underneath the current menu item
+		// tags:
+		//		protected
+
+		this._stopPopupTimer();
+		var from_item = this.focusedChild;
+		var popup = from_item.popup;
+
+		if(popup.isShowingNow){ return; }
+		popup.parentMenu = this;
+		var self = this;
+		dijit.popup.open({
+			parent: this,
+			popup: popup,
+			around: from_item.domNode,
+			orient: this._orient || (this.isLeftToRight() ? {'TR': 'TL', 'TL': 'TR'} : {'TL': 'TR', 'TR': 'TL'}),
+			onCancel: function(){
+				// called when the child menu is canceled
+				dijit.popup.close(popup);
+				from_item.focus();	// put focus back on my node
+				self.currentPopup = null;
+			},
+			onExecute: dojo.hitch(this, "_onDescendantExecute")
+		});
+
+		this.currentPopup = popup;
+
+		if(popup.focus){
+			// If user is opening the popup via keyboard (right arrow, or down arrow for MenuBar),
+			// if the cursor happens to collide with the popup, it will generate an onmouseover event
+			// even though the mouse wasn't moved.   Use a setTimeout() to call popup.focus so that
+			// our focus() call overrides the onmouseover event, rather than vice-versa.  (#8742)
+			setTimeout(dojo.hitch(popup, "focus"), 0);
+		}
+	},
+
+	onOpen: function(/*Event*/ e){
+		// summary:
+		//		Callback when this menu is opened.
+		//		This is called by the popup manager as notification that the menu
+		//		was opened.
+		// tags:
+		//		private
+
+		this.isShowingNow = true;
+	},
+
+	onClose: function(){
+		// summary:
+		//		Callback when this menu is closed.
+		//		This is called by the popup manager as notification that the menu
+		//		was closed.
+		// tags:
+		//		private
+
+		this._stopPopupTimer();
+		this.parentMenu = null;
+		this.isShowingNow = false;
+		this.currentPopup = null;
+		if(this.focusedChild){
+			this._onChildBlur(this.focusedChild);
+			this.focusedChild = null;
+		}
+	},
+
+	_onFocus: function(){
+		// summary:
+		//		Called when this Menu gets focus from:
+		//			1) clicking it
+		//			2) tabbing into it
+		//			3) being opened by a parent menu.
+		//		This is not called just from mouse hover.
+		// tags:
+		//		protected
+		this.isActive = true;
+		dojo.addClass(this.domNode, "dijitMenuActive");
+		dojo.removeClass(this.domNode, "dijitMenuPassive");
+		this.inherited(arguments);
+	},
+	
+	_onBlur: function(){
+		// summary:
+		//		Called when focus is moved away from this Menu and it's submenus.
+		// tags:
+		//		protected
+		this.isActive = false;
+		dojo.removeClass(this.domNode, "dijitMenuActive");
+		dojo.addClass(this.domNode, "dijitMenuPassive");
+
+		// If user blurs/clicks away from a MenuBar (or always visible Menu), then close all popped up submenus etc.
+		this.onClose();
+
+		this.inherited(arguments);
+	},
+
+	_onDescendantExecute: function(){
+		// summary:
+		//		Called when submenu is clicked.  Close hierarchy of menus.
+		// tags:
+		//		private
+		this.onClose();
+	}
+});
+
+dojo.declare("dijit.Menu",
+	dijit._MenuBase,
+	{
+	// summary
+	//		A context menu you can assign to multiple elements
+
+	// TODO: most of the code in here is just for context menu (right-click menu)
+	// support.  In retrospect that should have been a separate class (dijit.ContextMenu).
+	// Split them for 2.0
+
+	constructor: function(){
+		this._bindings = [];
+	},
+
+	templateString:"<table class=\"dijit dijitMenu dijitMenuPassive dijitReset dijitMenuTable\" waiRole=\"menu\" tabIndex=\"${tabIndex}\" dojoAttachEvent=\"onkeypress:_onKeyPress\">\n\t<tbody class=\"dijitReset\" dojoAttachPoint=\"containerNode\"></tbody>\n</table>\n",
+
+	// targetNodeIds: [const] String[]
+	//		Array of dom node ids of nodes to attach to.
+	//		Fill this with nodeIds upon widget creation and it becomes context menu for those nodes.
+	targetNodeIds: [],
+
+	// contextMenuForWindow: [const] Boolean
+	//		If true, right clicking anywhere on the window will cause this context menu to open.
+	//		If false, must specify targetNodeIds.
+	contextMenuForWindow: false,
+
+	// leftClickToOpen: [const] Boolean
+	//		If true, menu will open on left click instead of right click, similiar to a file menu.
+	leftClickToOpen: false,
+	
+	// _contextMenuWithMouse: [private] Boolean
+	//		Used to record mouse and keyboard events to determine if a context
+	//		menu is being opened with the keyboard or the mouse.
+	_contextMenuWithMouse: false,
+
+	postCreate: function(){
+		if(this.contextMenuForWindow){
+			this.bindDomNode(dojo.body());
+		}else{
+			dojo.forEach(this.targetNodeIds, this.bindDomNode, this);
+		}
+		var k = dojo.keys, l = this.isLeftToRight();
+		this._openSubMenuKey = l ? k.RIGHT_ARROW : k.LEFT_ARROW;
+		this._closeSubMenuKey = l ? k.LEFT_ARROW : k.RIGHT_ARROW;
+		this.connectKeyNavHandlers([k.UP_ARROW], [k.DOWN_ARROW]);
+	},
+
+	_onKeyPress: function(/*Event*/ evt){
+		// summary:
+		//		Handle keyboard based menu navigation.
+		// tags:
+		//		protected
+
+		if(evt.ctrlKey || evt.altKey){ return; }
+
+		switch(evt.charOrCode){
+			case this._openSubMenuKey:
+				this._moveToPopup(evt);
+				dojo.stopEvent(evt);
+				break;
+			case this._closeSubMenuKey:
+				if(this.parentMenu){
+					if(this.parentMenu._isMenuBar){
+						this.parentMenu.focusPrev();
+					}else{
+						this.onCancel(false);
+					}
+				}else{
+					dojo.stopEvent(evt);
+				}
+				break;
+		}
+	},
+
+	// thanks burstlib!
+	_iframeContentWindow: function(/* HTMLIFrameElement */iframe_el){
+		// summary:
+		//		Returns the window reference of the passed iframe
+		// tags:
+		//		private
+		var win = dijit.getDocumentWindow(dijit.Menu._iframeContentDocument(iframe_el)) ||
+			// Moz. TODO: is this available when defaultView isn't?
+			dijit.Menu._iframeContentDocument(iframe_el)['__parent__'] ||
+			(iframe_el.name && dojo.doc.frames[iframe_el.name]) || null;
+		return win;	//	Window
+	},
+
+	_iframeContentDocument: function(/* HTMLIFrameElement */iframe_el){
+		// summary:
+		//		Returns a reference to the document object inside iframe_el
+		// tags:
+		//		protected
+		var doc = iframe_el.contentDocument // W3
+			|| (iframe_el.contentWindow && iframe_el.contentWindow.document) // IE
+			|| (iframe_el.name && dojo.doc.frames[iframe_el.name] && dojo.doc.frames[iframe_el.name].document)
+			|| null;
+		return doc;	//	HTMLDocument
+	},
+
+	bindDomNode: function(/*String|DomNode*/ node){
+		// summary:
+		//		Attach menu to given node
+		node = dojo.byId(node);
+
+		//TODO: this is to support context popups in Editor.  Maybe this shouldn't be in dijit.Menu
+		var win = dijit.getDocumentWindow(node.ownerDocument);
+		if(node.tagName.toLowerCase()=="iframe"){
+			win = this._iframeContentWindow(node);
+			node = dojo.withGlobal(win, dojo.body);
+		}
+
+		// to capture these events at the top level,
+		// attach to document, not body
+		var cn = (node == dojo.body() ? dojo.doc : node);
+
+		node[this.id] = this._bindings.push([
+			dojo.connect(cn, (this.leftClickToOpen)?"onclick":"oncontextmenu", this, "_openMyself"),
+			dojo.connect(cn, "onkeydown", this, "_contextKey"),
+			dojo.connect(cn, "onmousedown", this, "_contextMouse")
+		]);
+	},
+
+	unBindDomNode: function(/*String|DomNode*/ nodeName){
+		// summary:
+		//		Detach menu from given node
+		var node = dojo.byId(nodeName);
+		if(node){
+			var bid = node[this.id]-1, b = this._bindings[bid];
+			dojo.forEach(b, dojo.disconnect);
+			delete this._bindings[bid];
+		}
+	},
+
+	_contextKey: function(e){
+		// summary:
+		//		Code to handle popping up editor using F10 key rather than mouse
+		// tags:
+		//		private
+		this._contextMenuWithMouse = false;
+		if(e.keyCode == dojo.keys.F10){
+			dojo.stopEvent(e);
+			if(e.shiftKey && e.type=="keydown"){
+				// FF: copying the wrong property from e will cause the system
+				// context menu to appear in spite of stopEvent. Don't know
+				// exactly which properties cause this effect.
+				var _e = { target: e.target, pageX: e.pageX, pageY: e.pageY };
+				_e.preventDefault = _e.stopPropagation = function(){};
+				// IE: without the delay, focus work in "open" causes the system
+				// context menu to appear in spite of stopEvent.
+				window.setTimeout(dojo.hitch(this, function(){ this._openMyself(_e); }), 1);
+			}
+		}
+	},
+
+	_contextMouse: function(e){
+		// summary:
+		//		Helper to remember when we opened the context menu with the mouse instead
+		//		of with the keyboard
+		// tags:
+		//		private
+		this._contextMenuWithMouse = true;
+	},
+
+	_openMyself: function(/*Event*/ e){
+		// summary:
+		//		Internal function for opening myself when the user
+		//		does a right-click or something similar
+		// tags:
+		//		private
+
+		if(this.leftClickToOpen&&e.button>0){
+			return;
+		}
+		dojo.stopEvent(e);
+
+		// Get coordinates.
+		// if we are opening the menu with the mouse or on safari open
+		// the menu at the mouse cursor
+		// (Safari does not have a keyboard command to open the context menu
+		// and we don't currently have a reliable way to determine
+		// _contextMenuWithMouse on Safari)
+		var x,y;
+		if(dojo.isSafari || this._contextMenuWithMouse){
+			x=e.pageX;
+			y=e.pageY;
+		}else{
+			// otherwise open near e.target
+			var coords = dojo.coords(e.target, true);
+			x = coords.x + 10;
+			y = coords.y + 10;
+		}
+
+		var self=this;
+		var savedFocus = dijit.getFocus(this);
+		function closeAndRestoreFocus(){
+			// user has clicked on a menu or popup
+			dijit.focus(savedFocus);
+			dijit.popup.close(self);
+		}
+		dijit.popup.open({
+			popup: this,
+			x: x,
+			y: y,
+			onExecute: closeAndRestoreFocus,
+			onCancel: closeAndRestoreFocus,
+			orient: this.isLeftToRight() ? 'L' : 'R'
+		});
+		this.focus();
+
+		this._onBlur = function(){
+			this.inherited('_onBlur', arguments);
+			// Usually the parent closes the child widget but if this is a context
+			// menu then there is no parent
+			dijit.popup.close(this);
+			// don't try to restore focus; user has clicked another part of the screen
+			// and set focus there
+		};
+	},
+
+	uninitialize: function(){
+ 		dojo.forEach(this.targetNodeIds, this.unBindDomNode, this);
+ 		this.inherited(arguments);
+	}
+}
+);
+
+// Back-compat (TODO: remove in 2.0)
+
+
+
+
+
+
+}
+
+if(!dojo._hasResource["dijit.TitlePane"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.TitlePane"] = true;
+dojo.provide("dijit.TitlePane");
+
+
+
+
+
+
+dojo.declare(
+	"dijit.TitlePane",
+	[dijit.layout.ContentPane, dijit._Templated],
+{
+	// summary:
+	//		A pane with a title on top, that can be expanded or collapsed.
+	//
+	// description:
+	//		An accessible container with a Title Heading, and a content
+	//		section that slides open and closed. TitlePane is an extension to 
+	//		`dijit.layout.ContentPane`, providing all the usesful content-control aspects from it.
+	//
+	// example:
+	// | 	// load a TitlePane from remote file:
+	// |	var foo = new dijit.TitlePane({ href: "foobar.html", title:"Title" });
+	// |	foo.startup();
+	//
+	// example:
+	// |	<!-- markup href example: -->
+	// |	<div dojoType="dijit.TitlePane" href="foobar.html" title="Title"></div>
+	// 
+	// example:
+	// |	<!-- markup with inline data -->
+	// | 	<div dojoType="dijit.TitlePane" title="Title">
+	// |		<p>I am content</p>
+	// |	</div>
+
+	// title: String
+	//		Title of the pane
+	title: "",
+
+	// open: Boolean
+	//		Whether pane is opened or closed.
+	open: true,
+
+	// duration: Integer
+	//		Time in milliseconds to fade in/fade out
+	duration: dijit.defaultDuration,
+
+	// baseClass: [protected] String
+	//		The root className to use for the various states of this widget
+	baseClass: "dijitTitlePane",
+
+	templateString:"<div class=\"${baseClass}\">\n\t<div dojoAttachEvent=\"onclick:toggle, onkeypress:_onTitleKey, onfocus:_handleFocus, onblur:_handleFocus, onmouseenter:_onTitleEnter, onmouseleave:_onTitleLeave\" tabindex=\"0\"\n\t\t\twaiRole=\"button\" class=\"dijitTitlePaneTitle\" dojoAttachPoint=\"titleBarNode,focusNode\">\n\t\t<img src=\"${_blankGif}\" alt=\"\" dojoAttachPoint=\"arrowNode\" class=\"dijitArrowNode\" waiRole=\"presentation\"\n\t\t><span dojoAttachPoint=\"arrowNodeInner\" class=\"dijitArrowNodeInner\"></span\n\t\t><span dojoAttachPoint=\"titleNode\" class=\"dijitTitlePaneTextNode\"></span>\n\t</div>\n\t<div class=\"dijitTitlePaneContentOuter\" dojoAttachPoint=\"hideNode\">\n\t\t<div class=\"dijitReset\" dojoAttachPoint=\"wipeNode\">\n\t\t\t<div class=\"dijitTitlePaneContentInner\" dojoAttachPoint=\"containerNode\" waiRole=\"region\" tabindex=\"-1\">\n\t\t\t\t<!-- nested divs because wipeIn()/wipeOut() doesn't work right on node w/padding etc.  Put padding on inner div. -->\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n",
+
+	attributeMap: dojo.delegate(dijit.layout.ContentPane.prototype.attributeMap, {
+		title: { node: "titleNode", type: "innerHTML" }
+	}),
+
+	postCreate: function(){
+		if(!this.open){
+			this.hideNode.style.display = this.wipeNode.style.display = "none";
+		}
+		this._setCss();
+		dojo.setSelectable(this.titleNode, false);
+		dijit.setWaiState(this.containerNode, "labelledby", this.titleNode.id);
+		dijit.setWaiState(this.focusNode, "haspopup", "true");
+
+		// setup open/close animations
+		var hideNode = this.hideNode, wipeNode = this.wipeNode;
+		this._wipeIn = dojo.fx.wipeIn({
+			node: this.wipeNode,
+			duration: this.duration,
+			beforeBegin: function(){
+				hideNode.style.display="";
+			}
+		});
+		this._wipeOut = dojo.fx.wipeOut({
+			node: this.wipeNode,
+			duration: this.duration,
+			onEnd: function(){
+				hideNode.style.display="none";
+			}
+		});
+		this.inherited(arguments);
+	},
+
+	_setOpenAttr: function(/* Boolean */ open){
+		// summary:
+		//		Hook to make attr("open", boolean) control the open/closed state of the pane.
+		// open: Boolean
+		//		True if you want to open the pane, false if you want to close it.
+		if(this.open !== open){ this.toggle(); }
+	},
+
+	_setContentAttr: function(content){
+		// summary:
+		//		Hook to make attr("content", ...) work.
+		// 		Typically called when an href is loaded.  Our job is to make the animation smooth.
+
+		if(!this.open || !this._wipeOut || this._wipeOut.status() == "playing"){
+			// we are currently *closing* the pane (or the pane is closed), so just let that continue
+			this.inherited(arguments);
+		}else{
+			if(this._wipeIn && this._wipeIn.status() == "playing"){
+				this._wipeIn.stop();
+			}
+
+			// freeze container at current height so that adding new content doesn't make it jump
+			dojo.marginBox(this.wipeNode, { h: dojo.marginBox(this.wipeNode).h });
+
+			// add the new content (erasing the old content, if any)
+			this.inherited(arguments);
+
+			// call _wipeIn.play() to animate from current height to new height
+			if(this._wipeIn){
+				this._wipeIn.play();
+			}else{
+				this.hideNode.style.display = "";
+			}
+		}
+	},
+
+	toggle: function(){
+		// summary:
+		//		Switches between opened and closed state
+		// tags:
+		//		private
+
+		dojo.forEach([this._wipeIn, this._wipeOut], function(animation){
+			if(animation && animation.status() == "playing"){
+				animation.stop();
+			}
+		});
+
+		var anim = this[this.open ? "_wipeOut" : "_wipeIn"]
+		if(anim){
+			anim.play();
+		}else{
+			this.hideNode.style.display = this.open ? "" : "none";
+		}
+		this.open =! this.open;
+
+		// load content (if this is the first time we are opening the TitlePane
+		// and content is specified as an href, or href was set when hidden)
+		this._onShow();
+
+		this._setCss();
+	},
+
+	_setCss: function(){
+		// summary:
+		//		Set the open/close css state for the TitlePane
+		// tags:
+		//		private
+
+		var classes = ["dijitClosed", "dijitOpen"];
+		var boolIndex = this.open;
+		var node = this.titleBarNode || this.focusNode;
+		dojo.removeClass(node, classes[!boolIndex+0]);
+		node.className += " " + classes[boolIndex+0];
+
+		// provide a character based indicator for images-off mode
+		this.arrowNodeInner.innerHTML = this.open ? "-" : "+";
+	},
+
+	_onTitleKey: function(/*Event*/ e){
+		// summary:
+		//		Handler for when user hits a key
+		// tags:
+		//		private
+
+		if(e.charOrCode == dojo.keys.ENTER || e.charOrCode == ' '){
+			this.toggle();
+		}else if(e.charOrCode == dojo.keys.DOWN_ARROW && this.open){
+			this.containerNode.focus();
+			e.preventDefault();
+	 	}
+	},
+	
+	_onTitleEnter: function(){
+		// summary:
+		//		Handler for when someone hovers over my title
+		// tags:
+		//		private
+		dojo.addClass(this.focusNode, "dijitTitlePaneTitle-hover");
+	},
+
+	_onTitleLeave: function(){
+		// summary:
+		//		Handler when someone stops hovering over my title
+		// tags:
+		//		private
+		dojo.removeClass(this.focusNode, "dijitTitlePaneTitle-hover");
+	},
+
+	_handleFocus: function(/*Event*/ e){
+		// summary:
+		//		Handle blur and focus for this widget
+		// tags:
+		//		private
+		
+		// add/removeClass is safe to call without hasClass in this case
+		dojo[(e.type == "focus" ? "addClass" : "removeClass")](this.focusNode, this.baseClass + "Focused");
+	},
+
+	setTitle: function(/*String*/ title){
+		// summary:
+		//		Deprecated.  Use attr('title', ...) instead.
+		// tags:
+		//		deprecated
+		dojo.deprecated("dijit.TitlePane.setTitle() is deprecated.  Use attr('title', ...) instead.", "", "2.0");
+		this.titleNode.innerHTML = title;
+	}
+});
+
+}
+
+if(!dojo._hasResource["dijit.ToolbarSeparator"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.ToolbarSeparator"] = true;
+dojo.provide("dijit.ToolbarSeparator");
+
+
+
+
+dojo.declare("dijit.ToolbarSeparator",
+		[ dijit._Widget, dijit._Templated ],
+		{
+		// summary:
+		//		A spacer between two `dijit.Toolbar` items
+		templateString: '<div class="dijitToolbarSeparator dijitInline"></div>',
+		postCreate: function(){ dojo.setSelectable(this.domNode, false); },
+		isFocusable: function(){ 
+			// summary:
+			//		This widget isn't focusable, so pass along that fact.
+			// tags:
+			//		protected
+			return false; 
+		}
+
+	});
+
+
+
+}
+
+if(!dojo._hasResource["dijit.Toolbar"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.Toolbar"] = true;
+dojo.provide("dijit.Toolbar");
+
+
+
+
+
+dojo.declare("dijit.Toolbar",
+	[dijit._Widget, dijit._Templated, dijit._KeyNavContainer],
+	{
+	// summary:
+	//		A Toolbar widget, used to hold things like `dijit.Editor` buttons
+
+	templateString:
+		'<div class="dijit dijitToolbar" waiRole="toolbar" tabIndex="${tabIndex}" dojoAttachPoint="containerNode">' +
+		//	'<table style="table-layout: fixed" class="dijitReset dijitToolbarTable">' + // factor out style
+		//		'<tr class="dijitReset" dojoAttachPoint="containerNode"></tr>'+
+		//	'</table>' +
+		'</div>',
+
+	postCreate: function(){
+		this.connectKeyNavHandlers(
+			this.isLeftToRight() ? [dojo.keys.LEFT_ARROW] : [dojo.keys.RIGHT_ARROW],
+			this.isLeftToRight() ? [dojo.keys.RIGHT_ARROW] : [dojo.keys.LEFT_ARROW]
+		);
+	},
+
+	startup: function(){
+		if(this._started){ return; }
+
+		this.startupKeyNavChildren();
+
+		this.inherited(arguments);
+	}
+}
+);
+
+// For back-compat, remove for 2.0
+
+
+}
+
+if(!dojo._hasResource["dijit.Tooltip"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.Tooltip"] = true;
+dojo.provide("dijit.Tooltip");
+
+
+
+
+dojo.declare(
+	"dijit._MasterTooltip",
+	[dijit._Widget, dijit._Templated],
+	{
+		// summary:
+		//		Internal widget that holds the actual tooltip markup,
+		//		which occurs once per page.
+		//		Called by Tooltip widgets which are just containers to hold
+		//		the markup
+		// tags:
+		//		protected
+
+		// duration: Integer
+		//		Milliseconds to fade in/fade out
+		duration: dijit.defaultDuration,
+
+		templateString:"<div class=\"dijitTooltip dijitTooltipLeft\" id=\"dojoTooltip\">\n\t<div class=\"dijitTooltipContainer dijitTooltipContents\" dojoAttachPoint=\"containerNode\" waiRole='alert'></div>\n\t<div class=\"dijitTooltipConnector\"></div>\n</div>\n",
+
+		postCreate: function(){
+			dojo.body().appendChild(this.domNode);
+
+			this.bgIframe = new dijit.BackgroundIframe(this.domNode);
+
+			// Setup fade-in and fade-out functions.
+			this.fadeIn = dojo.fadeIn({ node: this.domNode, duration: this.duration, onEnd: dojo.hitch(this, "_onShow") });
+			this.fadeOut = dojo.fadeOut({ node: this.domNode, duration: this.duration, onEnd: dojo.hitch(this, "_onHide") });
+
+		},
+
+		show: function(/*String*/ innerHTML, /*DomNode*/ aroundNode, /*String[]?*/ position){
+			// summary:
+			//		Display tooltip w/specified contents to right of specified node
+			//		(To left if there's no space on the right, or if LTR==right)
+
+			if(this.aroundNode && this.aroundNode === aroundNode){
+				return;
+			}
+
+			if(this.fadeOut.status() == "playing"){
+				// previous tooltip is being hidden; wait until the hide completes then show new one
+				this._onDeck=arguments;
+				return;
+			}
+			this.containerNode.innerHTML=innerHTML;
+
+			// Firefox bug. when innerHTML changes to be shorter than previous
+			// one, the node size will not be updated until it moves.
+			this.domNode.style.top = (this.domNode.offsetTop + 1) + "px";
+
+			// position the element and change CSS according to position[] (a list of positions to try)
+			var align = {};
+			var ltr = this.isLeftToRight();
+			dojo.forEach( (position && position.length) ? position : dijit.Tooltip.defaultPosition, function(pos){
+				switch(pos){
+					case "after":				
+						align[ltr ? "BR" : "BL"] = ltr ? "BL" : "BR";
+						break;
+					case "before":
+						align[ltr ? "BL" : "BR"] = ltr ? "BR" : "BL";
+						break;
+					case "below":
+						// first try to align left borders, next try to align right borders (or reverse for RTL mode)
+						align[ltr ? "BL" : "BR"] = ltr ? "TL" : "TR";
+						align[ltr ? "BR" : "BL"] = ltr ? "TR" : "TL";
+						break;
+					case "above":
+					default:
+						// first try to align left borders, next try to align right borders (or reverse for RTL mode)
+						align[ltr ? "TL" : "TR"] = ltr ? "BL" : "BR";
+						align[ltr ? "TR" : "TL"] = ltr ? "BR" : "BL";
+						break;
+				}
+			});
+			var pos = dijit.placeOnScreenAroundElement(this.domNode, aroundNode, align, dojo.hitch(this, "orient"));
+
+			// show it
+			dojo.style(this.domNode, "opacity", 0);
+			this.fadeIn.play();
+			this.isShowingNow = true;
+			this.aroundNode = aroundNode;
+		},
+
+		orient: function(/* DomNode */ node, /* String */ aroundCorner, /* String */ tooltipCorner){
+			// summary:
+			//		Private function to set CSS for tooltip node based on which position it's in.
+			//		This is called by the dijit popup code.
+			// tags:
+			//		protected
+
+			node.className = "dijitTooltip " +
+				{
+					"BL-TL": "dijitTooltipBelow dijitTooltipABLeft",
+					"TL-BL": "dijitTooltipAbove dijitTooltipABLeft",
+					"BR-TR": "dijitTooltipBelow dijitTooltipABRight",
+					"TR-BR": "dijitTooltipAbove dijitTooltipABRight",
+					"BR-BL": "dijitTooltipRight",
+					"BL-BR": "dijitTooltipLeft"
+				}[aroundCorner + "-" + tooltipCorner];
+		},
+
+		_onShow: function(){
+			// summary:
+			//		Called at end of fade-in operation
+			// tags:
+			//		protected
+			if(dojo.isIE){
+				// the arrow won't show up on a node w/an opacity filter
+				this.domNode.style.filter="";
+			}
+		},
+
+		hide: function(aroundNode){
+			// summary:
+			//		Hide the tooltip
+			if(this._onDeck && this._onDeck[1] == aroundNode){
+				// this hide request is for a show() that hasn't even started yet;
+				// just cancel the pending show()
+				this._onDeck=null;
+			}else if(this.aroundNode === aroundNode){
+				// this hide request is for the currently displayed tooltip
+				this.fadeIn.stop();
+				this.isShowingNow = false;
+				this.aroundNode = null;
+				this.fadeOut.play();
+			}else{
+				// just ignore the call, it's for a tooltip that has already been erased
+			}
+		},
+
+		_onHide: function(){
+			// summary:
+			//		Called at end of fade-out operation
+			// tags:
+			//		protected
+
+			this.domNode.style.cssText="";	// to position offscreen again
+			if(this._onDeck){
+				// a show request has been queued up; do it now
+				this.show.apply(this, this._onDeck);
+				this._onDeck=null;
+			}
+		}
+
+	}
+);
+
+dijit.showTooltip = function(/*String*/ innerHTML, /*DomNode*/ aroundNode, /*String[]?*/ position){
+	// summary:
+	//		Display tooltip w/specified contents in specified position.
+	//		See description of dijit.Tooltip.defaultPosition for details on position parameter.
+	//		If position is not specified then dijit.Tooltip.defaultPosition is used.
+	if(!dijit._masterTT){ dijit._masterTT = new dijit._MasterTooltip(); }
+	return dijit._masterTT.show(innerHTML, aroundNode, position);
+};
+
+dijit.hideTooltip = function(aroundNode){
+	// summary:
+	//		Hide the tooltip
+	if(!dijit._masterTT){ dijit._masterTT = new dijit._MasterTooltip(); }
+	return dijit._masterTT.hide(aroundNode);
+};
+
+dojo.declare(
+	"dijit.Tooltip",
+	dijit._Widget,
+	{
+		// summary
+		//		Pops up a tooltip (a help message) when you hover over a node.
+
+		// label: String
+		//		Text to display in the tooltip.
+		//		Specified as innerHTML when creating the widget from markup.
+		label: "",
+
+		// showDelay: Integer
+		//		Number of milliseconds to wait after hovering over/focusing on the object, before
+		//		the tooltip is displayed.
+		showDelay: 400,
+
+		// connectId: [const] String[]
+		//		Id's of domNodes to attach the tooltip to.
+		//		When user hovers over any of the specified dom nodes, the tooltip will appear.
+		//
+		//		Note: Currently connectId can only be specified on initialization, it cannot
+		//		be changed via attr('connectId', ...)
+		//
+		//		Note: in 2.0 this will be renamed to connectIds for less confusion.
+		connectId: [],
+
+		// position: String[]
+		//		See description of `dijit.Tooltip.defaultPosition` for details on position parameter.
+		position: [],
+
+		_setConnectIdAttr: function(ids){
+			// TODO: erase old conections
+
+			this._connectNodes = [];
+
+			// TODO: rename connectId to connectIds for 2.0, and remove this code converting from string to array
+			this.connectId = dojo.isArrayLike(ids) ? ids : [ids];
+			
+			dojo.forEach(this.connectId, function(id) {
+				var node = dojo.byId(id);
+				if (node) {
+					this._connectNodes.push(node);
+					dojo.forEach(["onMouseEnter", "onMouseLeave", "onFocus", "onBlur"], function(event){
+						this.connect(node, event.toLowerCase(), "_"+event);
+					}, this);
+					if(dojo.isIE){
+						// BiDi workaround
+						node.style.zoom = 1;
+					}
+				}
+			}, this);
+		},
+
+		postCreate: function(){	
+			dojo.addClass(this.domNode,"dijitTooltipData");
+		},
+
+		_onMouseEnter: function(/*Event*/ e){
+			// summary:
+			//		Handler for mouseenter event on the target node
+			// tags:
+			//		private
+			this._onHover(e);
+		},
+
+		_onMouseLeave: function(/*Event*/ e){
+			// summary:
+			//		Handler for mouseleave event on the target node
+			// tags:
+			//		private
+			this._onUnHover(e);
+		},
+
+		_onFocus: function(/*Event*/ e){
+			// summary:
+			//		Handler for focus event on the target node
+			// tags:
+			//		private
+
+			// TODO: this is dangerously named, as the dijit focus manager calls
+			// _onFocus() on any widget that gets focus (whereas in this class we
+			// are connecting onfocus on the *target* DOM node to this method
+
+			this._focus = true;
+			this._onHover(e);
+			this.inherited(arguments);
+		},
+		
+		_onBlur: function(/*Event*/ e){
+			// summary:
+			//		Handler for blur event on the target node
+			// tags:
+			//		private
+
+			// TODO: rename; see above comment
+
+			this._focus = false;
+			this._onUnHover(e);
+			this.inherited(arguments);
+		},
+
+		_onHover: function(/*Event*/ e){
+			// summary:
+			//		Despite the name of this method, it actually handles both hover and focus
+			//		events on the target node, setting a timer to show the tooltip.
+			// tags:
+			//		private
+			if(!this._showTimer){
+				var target = e.target;
+				this._showTimer = setTimeout(dojo.hitch(this, function(){this.open(target)}), this.showDelay);
+			}
+		},
+
+		_onUnHover: function(/*Event*/ e){
+			// summary:
+			//		Despite the name of this method, it actually handles both mouseleave and blur
+			//		events on the target node, hiding the tooltip.
+			// tags:
+			//		private
+
+			// keep a tooltip open if the associated element still has focus (even though the
+			// mouse moved away)
+			if(this._focus){ return; }
+
+			if(this._showTimer){
+				clearTimeout(this._showTimer);
+				delete this._showTimer;
+			}
+			this.close();
+		},
+
+		open: function(/*DomNode*/ target){
+ 			// summary:
+			//		Display the tooltip; usually not called directly.
+			// tags:
+			//		private
+
+			target = target || this._connectNodes[0];
+			if(!target){ return; }
+
+			if(this._showTimer){
+				clearTimeout(this._showTimer);
+				delete this._showTimer;
+			}
+			dijit.showTooltip(this.label || this.domNode.innerHTML, target, this.position);
+			
+			this._connectNode = target;
+		},
+
+		close: function(){
+			// summary:
+			//		Hide the tooltip or cancel timer for show of tooltip
+			// tags:
+			//		private
+
+			if(this._connectNode){
+				// if tooltip is currently shown
+				dijit.hideTooltip(this._connectNode);
+				delete this._connectNode;
+			}
+			if(this._showTimer){
+				// if tooltip is scheduled to be shown (after a brief delay)
+				clearTimeout(this._showTimer);
+				delete this._showTimer;
+			}
+		},
+
+		uninitialize: function(){
+			this.close();
+		}
+	}
+);
+
+// dijit.Tooltip.defaultPosition: String[]
+//		This variable controls the position of tooltips, if the position is not specified to
+//		the Tooltip widget or *TextBox widget itself.  It's an array of strings with the following values:
+//
+//			* before: places tooltip to the left of the target node/widget, or to the right in
+//			  the case of RTL scripts like Hebrew and Arabic
+//			* after: places tooltip to the right of the target node/widget, or to the left in
+//			  the case of RTL scripts like Hebrew and Arabic
+//			* above: tooltip goes above target node
+//			* below: tooltip goes below target node
+//
+//		The list is positions is tried, in order, until a position is found where the tooltip fits
+//		within the viewport.
+//
+//		Be careful setting this parameter.  A value of "above" may work fine until the user scrolls
+//		the screen so that there's no room above the target node.   Nodes with drop downs, like
+//		DropDownButton or FilteringSelect, are especially problematic, in that you need to be sure
+//		that the drop down and tooltip don't overlap, even when the viewport is scrolled so that there
+//		is only room below (or above) the target node, but not both.
+dijit.Tooltip.defaultPosition = ["after", "before"];
+
+}
+
+if(!dojo._hasResource["dijit.form.Form"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.Form"] = true;
+dojo.provide("dijit.form.Form");
+
+
+
+
+
+dojo.declare(
+	"dijit.form.Form",
+	[dijit._Widget, dijit._Templated, dijit.form._FormMixin],
+	{
+		// summary:
+		//		Widget corresponding to HTML form tag, for validation and serialization
+		//
+		// example:
+		//	|	<form dojoType="dijit.form.Form" id="myForm">
+		//	|		Name: <input type="text" name="name" />
+		//	|	</form>
+		//	|	myObj = {name: "John Doe"};
+		//	|	dijit.byId('myForm').attr('value', myObj);
+		//	|
+		//	|	myObj=dijit.byId('myForm').attr('value');
+
+		// HTML <FORM> attributes
+
+		// name: String?
+		//		Name of form for scripting.
+		name: "",
+
+		// action: String?
+		//		Server-side form handler.
+		action: "",
+
+		// method: String?
+		//		HTTP method used to submit the form, either "GET" or "POST".
+		method: "",
+
+		// encType: String?
+		//		Encoding type for the form, ex: application/x-www-form-urlencoded.
+		encType: "",
+
+		// accept-charset: String?
+		//		List of supported charsets.
+		"accept-charset": "",
+
+		// accept: String?
+		//		List of MIME types for file upload.
+		accept: "",
+
+		// target: String?
+		//		Target frame for the document to be opened in.
+		target: "",
+
+		templateString: "<form dojoAttachPoint='containerNode' dojoAttachEvent='onreset:_onReset,onsubmit:_onSubmit' ${nameAttrSetting}></form>",
+
+		attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
+			action: "", 
+			method: "", 
+			encType: "", 
+			"accept-charset": "", 
+			accept: "", 
+			target: ""
+		}),
+
+		postMixInProperties: function(){
+			// Setup name=foo string to be referenced from the template (but only if a name has been specified)
+			// Unfortunately we can't use attributeMap to set the name due to IE limitations, see #8660
+			this.nameAttrSetting = this.name ? ("name='" + this.name + "'") : "";
+			this.inherited(arguments);
+		},
+
+		execute: function(/*Object*/ formContents){
+			// summary:
+			//		Deprecated: use submit()
+			// tags:
+			//		deprecated
+		},
+
+		onExecute: function(){
+			// summary:
+			//		Deprecated: use onSubmit()
+			// tags:
+			//		deprecated
+		},
+
+		_setEncTypeAttr: function(/*String*/ value){
+			this.encType = value;
+			dojo.attr(this.domNode, "encType", value);
+			if(dojo.isIE){ this.domNode.encoding = value; }
+		},
+
+		postCreate: function(){
+			// IE tries to hide encType
+			// TODO: this code should be in parser, not here.
+			if(dojo.isIE && this.srcNodeRef && this.srcNodeRef.attributes){
+				var item = this.srcNodeRef.attributes.getNamedItem('encType');
+				if(item && !item.specified && (typeof item.value == "string")){
+					this.attr('encType', item.value);
+				}
+			}
+			this.inherited(arguments);
+		},
+
+		onReset: function(/*Event?*/ e){
+			// summary:
+			//		Callback when user resets the form. This method is intended
+			//		to be over-ridden. When the `reset` method is called
+			//		programmatically, the return value from `onReset` is used
+			//		to compute whether or not resetting should proceed
+			// tags:
+			//		callback
+			return true; // Boolean
+		},
+
+		_onReset: function(e){
+			// create fake event so we can know if preventDefault() is called
+			var faux = {
+				returnValue: true, // the IE way
+				preventDefault: function(){  // not IE
+							this.returnValue = false;
+						},
+				stopPropagation: function(){}, currentTarget: e.currentTarget, target: e.target
+			};
+			// if return value is not exactly false, and haven't called preventDefault(), then reset
+			if(!(this.onReset(faux) === false) && faux.returnValue){
+				this.reset();
+			}
+			dojo.stopEvent(e);
+			return false;
+		},
+
+		_onSubmit: function(e){
+			var fp = dijit.form.Form.prototype;
+			// TODO: remove this if statement beginning with 2.0
+			if(this.execute != fp.execute || this.onExecute != fp.onExecute){
+				dojo.deprecated("dijit.form.Form:execute()/onExecute() are deprecated. Use onSubmit() instead.", "", "2.0");
+				this.onExecute();
+				this.execute(this.getValues());
+			}
+			if(this.onSubmit(e) === false){ // only exactly false stops submit
+				dojo.stopEvent(e);
+			}
+		},
+		
+		onSubmit: function(/*Event?*/e){ 
+			// summary:
+			//		Callback when user submits the form.
+			// description:
+			//		This method is intended to be over-ridden, but by default it checks and
+			//		returns the validity of form elements. When the `submit`
+			//		method is called programmatically, the return value from
+			//		`onSubmit` is used to compute whether or not submission
+			//		should proceed
+			// tags:
+			//		extension
+
+			return this.isValid(); // Boolean
+		},
+
+		submit: function(){
+			// summary:
+			//		programmatically submit form if and only if the `onSubmit` returns true
+			if(!(this.onSubmit() === false)){
+				this.containerNode.submit();
+			}
+		}
+	}
+);
+
+}
+
+if(!dojo._hasResource["dijit.form._FormWidget"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form._FormWidget"] = true;
+dojo.provide("dijit.form._FormWidget");
+
+
+
+
+dojo.declare("dijit.form._FormWidget", [dijit._Widget, dijit._Templated],
+	{
+	//
+	// summary:
+	//		Base class for widgets corresponding to native HTML elements such as <checkbox> or <button>,
+	//		which can be children of a <form> node or a `dijit.form.Form` widget.
+	//
+	// description:
+	//		Represents a single HTML element.
+	//		All these widgets should have these attributes just like native HTML input elements.
+	//		You can set them during widget construction or afterwards, via `dijit._Widget.attr`.
+	//
+	//	They also share some common methods.
+
+	// baseClass: [protected] String
+	//		Root CSS class of the widget (ex: dijitTextBox), used to add CSS classes of widget
+	//		(ex: "dijitTextBox dijitTextBoxInvalid dijitTextBoxFocused dijitTextBoxInvalidFocused")
+	//		See _setStateClass().
+	baseClass: "",
+
+	// name: String
+	//		Name used when submitting form; same as "name" attribute or plain HTML elements
+	name: "",
+
+	// alt: String
+	//		Corresponds to the native HTML <input> element's attribute.
+	alt: "",
+
+	// value: String
+	//		Corresponds to the native HTML <input> element's attribute.
+	value: "",
+
+	// type: String
+	//		Corresponds to the native HTML <input> element's attribute.
+	type: "text",
+
+	// tabIndex: Integer
+	//		Order fields are traversed when user hits the tab key
+	tabIndex: "0",
+
+	// disabled: Boolean
+	//		Should this widget respond to user input?
+	//		In markup, this is specified as "disabled='disabled'", or just "disabled".
+	disabled: false,
+
+	// readOnly: Boolean
+	//		Should this widget respond to user input?
+	//		In markup, this is specified as "readOnly".
+	//		Similar to disabled except readOnly form values are submitted.
+	readOnly: false,
+
+	// intermediateChanges: Boolean
+	//		Fires onChange for each value change or only on demand
+	intermediateChanges: false,
+
+	// scrollOnFocus: Boolean
+	//		On focus, should this widget scroll into view?
+	scrollOnFocus: true,
+
+	// These mixins assume that the focus node is an INPUT, as many but not all _FormWidgets are.
+	attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
+		value: "focusNode",
+		disabled: "focusNode",
+		readOnly: "focusNode",
+		id: "focusNode",
+		tabIndex: "focusNode",
+		alt: "focusNode"
+	}),
+
+	postMixInProperties: function(){
+		// Setup name=foo string to be referenced from the template (but only if a name has been specified)
+		// Unfortunately we can't use attributeMap to set the name due to IE limitations, see #8660
+		this.nameAttrSetting = this.name ? ("name='" + this.name + "'") : "";
+		this.inherited(arguments);
+	},
+
+	_setDisabledAttr: function(/*Boolean*/ value){
+		this.disabled = value;
+		dojo.attr(this.focusNode, 'disabled', value);
+		dijit.setWaiState(this.focusNode, "disabled", value);
+
+				if(value){
+					//reset those, because after the domNode is disabled, we can no longer receive
+					//mouse related events, see #4200
+					this._hovering = false;
+					this._active = false;
+					// remove the tabIndex, especially for FF
+					this.focusNode.removeAttribute('tabIndex');
+				}else{
+					this.focusNode.setAttribute('tabIndex', this.tabIndex);
+				}
+				this._setStateClass();
+	},
+
+	setDisabled: function(/*Boolean*/ disabled){
+		// summary:
+		//		Deprecated.   Use attr('disabled', ...) instead.
+		dojo.deprecated("setDisabled("+disabled+") is deprecated. Use attr('disabled',"+disabled+") instead.", "", "2.0");
+		this.attr('disabled', disabled);
+	},
+
+	_onFocus: function(e){
+		if(this.scrollOnFocus){
+			dijit.scrollIntoView(this.domNode);
+		}
+		this.inherited(arguments);
+	},
+
+	_onMouse : function(/*Event*/ event){
+		// summary:
+		//	Sets _hovering, _active, and stateModifier properties depending on mouse state,
+		//	then calls setStateClass() to set appropriate CSS classes for this.domNode.
+		//
+		//	To get a different CSS class for hover, send onmouseover and onmouseout events to this method.
+		//	To get a different CSS class while mouse button is depressed, send onmousedown to this method.
+
+		var mouseNode = event.currentTarget;
+		if(mouseNode && mouseNode.getAttribute){
+			this.stateModifier = mouseNode.getAttribute("stateModifier") || "";
+		}
+
+		if(!this.disabled){
+			switch(event.type){
+				case "mouseenter":
+				case "mouseover":
+					this._hovering = true;
+					this._active = this._mouseDown;
+					break;
+
+				case "mouseout":
+				case "mouseleave":
+					this._hovering = false;
+					this._active = false;
+					break;
+
+				case "mousedown" :
+					this._active = true;
+					this._mouseDown = true;
+					// set a global event to handle mouseup, so it fires properly
+					//	even if the cursor leaves the button
+					var mouseUpConnector = this.connect(dojo.body(), "onmouseup", function(){
+						//if user clicks on the button, even if the mouse is released outside of it,
+						//this button should get focus (which mimics native browser buttons)
+						if(this._mouseDown && this.isFocusable()){
+							this.focus();
+						}
+						this._active = false;
+						this._mouseDown = false;
+						this._setStateClass();
+						this.disconnect(mouseUpConnector);
+					});
+					break;
+			}
+			this._setStateClass();
+		}
+	},
+
+	isFocusable: function(){
+		// summary:
+		//		Tells if this widget is focusable or not.   Used internally by dijit.
+		// tags:
+		//		protected
+		return !this.disabled && !this.readOnly && this.focusNode && (dojo.style(this.domNode, "display") != "none");
+	},
+
+	focus: function(){
+		// summary:
+		//		Put focus on this widget
+		dijit.focus(this.focusNode);
+	},
+
+	_setStateClass: function(){
+		// summary:
+		//		Update the visual state of the widget by setting the css classes on this.domNode
+		//		(or this.stateNode if defined) by combining this.baseClass with
+		//		various suffixes that represent the current widget state(s).
+		//
+		// description:
+		//		In the case where a widget has multiple
+		//		states, it sets the class based on all possible
+		//	 	combinations.  For example, an invalid form widget that is being hovered
+		//		will be "dijitInput dijitInputInvalid dijitInputHover dijitInputInvalidHover".
+		//
+		//		For complex widgets with multiple regions, there can be various hover/active states,
+		//		such as "Hover" or "CloseButtonHover" (for tab buttons).
+		//		This is controlled by a stateModifier="CloseButton" attribute on the close button node.
+		//
+		//		The widget may have one or more of the following states, determined
+		//		by this.state, this.checked, this.valid, and this.selected:
+		//			- Error - ValidationTextBox sets this.state to "Error" if the current input value is invalid
+		//			- Checked - ex: a checkmark or a ToggleButton in a checked state, will have this.checked==true
+		//			- Selected - ex: currently selected tab will have this.selected==true
+		//
+		//		In addition, it may have one or more of the following states,
+		//		based on this.disabled and flags set in _onMouse (this._active, this._hovering, this._focused):
+		//			- Disabled	- if the widget is disabled
+		//			- Active		- if the mouse (or space/enter key?) is being pressed down
+		//			- Focused		- if the widget has focus
+		//			- Hover		- if the mouse is over the widget
+
+		// Compute new set of classes
+		var newStateClasses = this.baseClass.split(" ");
+
+		function multiply(modifier){
+			newStateClasses = newStateClasses.concat(dojo.map(newStateClasses, function(c){ return c+modifier; }), "dijit"+modifier);
+		}
+
+		if(this.checked){
+			multiply("Checked");
+		}
+		if(this.state){
+			multiply(this.state);
+		}
+		if(this.selected){
+			multiply("Selected");
+		}
+
+		if(this.disabled){
+			multiply("Disabled");
+		}else if(this.readOnly){
+			multiply("ReadOnly");
+		}else if(this._active){
+			multiply(this.stateModifier+"Active");
+		}else{
+			if(this._focused){
+				multiply("Focused");
+			}
+			if(this._hovering){
+				multiply(this.stateModifier+"Hover");
+			}
+		}
+
+		// Remove old state classes and add new ones.
+		// For performance concerns we only write into domNode.className once.
+		var tn = this.stateNode || this.domNode,
+			classHash = {};	// set of all classes (state and otherwise) for node
+
+		dojo.forEach(tn.className.split(" "), function(c){ classHash[c] = true; });
+
+		if("_stateClasses" in this){
+			dojo.forEach(this._stateClasses, function(c){ delete classHash[c]; });
+		}
+
+		dojo.forEach(newStateClasses, function(c){ classHash[c] = true; });
+
+		var newClasses = [];
+		for(var c in classHash){
+			newClasses.push(c);
+		}
+		tn.className = newClasses.join(" ");
+
+		this._stateClasses = newStateClasses;
+	},
+
+	compare: function(/*anything*/val1, /*anything*/val2){
+		// summary:
+		//		Compare 2 values (as returned by attr('value') for this widget).
+		// tags:
+		//		protected
+		if((typeof val1 == "number") && (typeof val2 == "number")){
+			return (isNaN(val1) && isNaN(val2))? 0 : (val1-val2);
+		}else if(val1 > val2){ return 1; }
+		else if(val1 < val2){ return -1; }
+		else { return 0; }
+	},
+
+	onChange: function(newValue){
+		// summary:
+		//		Callback when this widget's value is changed.
+		// tags:
+		//		callback
+	},
+
+	// _onChangeActive: [private] Boolean
+	//		Indicates that changes to the value should call onChange() callback.
+	//		This is false during widget initialization, to avoid calling onChange()
+	//		when the initial value is set.
+	_onChangeActive: false,
+
+	_handleOnChange: function(/*anything*/ newValue, /* Boolean? */ priorityChange){
+		// summary:
+		//		Called when the value of the widget is set.  Calls onChange() if appropriate
+		// newValue:
+		//		the new value
+		// priorityChange:
+		//		For a slider, for example, dragging the slider is priorityChange==false,
+		//		but on mouse up, it's priorityChange==true.  If intermediateChanges==true,
+		//		onChange is only called form priorityChange=true events.
+		// tags:
+		//		private
+		this._lastValue = newValue;
+		if(this._lastValueReported == undefined && (priorityChange === null || !this._onChangeActive)){
+			// this block executes not for a change, but during initialization,
+			// and is used to store away the original value (or for ToggleButton, the original checked state)
+			this._resetValue = this._lastValueReported = newValue;
+		}
+		if((this.intermediateChanges || priorityChange || priorityChange === undefined) &&
+			((typeof newValue != typeof this._lastValueReported) ||
+				this.compare(newValue, this._lastValueReported) != 0)){
+			this._lastValueReported = newValue;
+			if(this._onChangeActive){ this.onChange(newValue); }
+		}
+	},
+
+	create: function(){
+		// Overrides _Widget.create()
+		this.inherited(arguments);
+		this._onChangeActive = true;
+		this._setStateClass();
+	},
+
+	destroy: function(){
+		if(this._layoutHackHandle){
+			clearTimeout(this._layoutHackHandle);
+		}
+		this.inherited(arguments);
+	},
+
+	setValue: function(/*String*/ value){
+		// summary:
+		//		Deprecated.   Use attr('value', ...) instead.
+		dojo.deprecated("dijit.form._FormWidget:setValue("+value+") is deprecated.  Use attr('value',"+value+") instead.", "", "2.0");
+		this.attr('value', value);
+	},
+
+	getValue: function(){
+		// summary:
+		//		Deprecated.   Use attr('value') instead.
+		dojo.deprecated(this.declaredClass+"::getValue() is deprecated. Use attr('value') instead.", "", "2.0");
+		return this.attr('value');
+	},
+
+	_layoutHack: function(){
+		// summary:
+		//		Work around table sizing bugs on FF2 by forcing redraw
+
+		if(dojo.isFF == 2 && !this._layoutHackHandle){
+			var node=this.domNode;
+			var old = node.style.opacity;
+			node.style.opacity = "0.999";
+			this._layoutHackHandle = setTimeout(dojo.hitch(this, function(){
+				this._layoutHackHandle = null;
+				node.style.opacity = old;
+			}), 0);
+		}
+	}
+});
+
+dojo.declare("dijit.form._FormValueWidget", dijit.form._FormWidget,
+{
+	// summary:
+	//		Base class for widgets corresponding to native HTML elements such as <input> or <select> that have user changeable values.
+	// description:
+	//		Each _FormValueWidget represents a single input value, and has a (possibly hidden) <input> element,
+	//		to which it serializes it's input value, so that form submission (either normal submission or via FormBind?)
+	//		works as expected.
+
+	// Don't attempt to mixin the 'type', 'name' attributes here programatically -- they must be declared
+	// directly in the template as read by the parser in order to function. IE is known to specifically
+	// require the 'name' attribute at element creation time.   See #8484, #8660.
+	// TODO: unclear what that {value: ""} is for; FormWidget.attributeMap copies value to focusNode,
+	// so maybe {value: ""} is so the value *doesn't* get copied to focusNode?
+	// Seems like we really want value removed from attributeMap altogether
+	// (although there's no easy way to do that now)
+	attributeMap: dojo.delegate(dijit.form._FormWidget.prototype.attributeMap, { value: "" }),
+
+	postCreate: function(){
+		if(dojo.isIE || dojo.isWebKit){ // IE won't stop the event with keypress and Safari won't send an ESCAPE to keypress at all
+			this.connect(this.focusNode || this.domNode, "onkeydown", this._onKeyDown);
+		}
+		// Update our reset value if it hasn't yet been set (because this.attr
+		// is only called when there *is* a value
+		if(this._resetValue === undefined){
+			this._resetValue = this.value;
+		}
+	},
+
+	_setValueAttr: function(/*anything*/ newValue, /*Boolean, optional*/ priorityChange){
+		// summary:
+		//		Hook so attr('value', value) works.
+		// description:
+		//		Sets the value of the widget.
+		//		If the value has changed, then fire onChange event, unless priorityChange
+		//		is specified as null (or false?)
+		this.value = newValue;
+		this._handleOnChange(newValue, priorityChange);
+	},
+
+	_getValueAttr: function(/*String*/ value){
+		// summary:
+		//		Hook so attr('value') works.
+		return this._lastValue;
+	},
+
+	undo: function(){
+		// summary:
+		//		Restore the value to the last value passed to onChange
+		this._setValueAttr(this._lastValueReported, false);
+	},
+
+	reset: function(){
+		// summary:
+		//		Reset the widget's value to what it was at initialization time
+		this._hasBeenBlurred = false;
+		this._setValueAttr(this._resetValue, true);
+	},
+
+	_onKeyDown: function(e){
+		if(e.keyCode == dojo.keys.ESCAPE && !e.ctrlKey && !e.altKey){
+			var te;
+			if(dojo.isIE){ 
+				e.preventDefault(); // default behavior needs to be stopped here since keypress is too late
+				te = document.createEventObject();
+				te.keyCode = dojo.keys.ESCAPE;
+				te.shiftKey = e.shiftKey;
+				e.srcElement.fireEvent('onkeypress', te);
+			}else if(dojo.isWebKit){ // ESCAPE needs help making it into keypress
+				te = document.createEvent('Events');
+				te.initEvent('keypress', true, true);
+				te.keyCode = dojo.keys.ESCAPE;
+				te.shiftKey = e.shiftKey;
+				e.target.dispatchEvent(te);
+			}
+		}
+	}
+});
+
+}
+
+if(!dojo._hasResource["dijit.form.Button"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.Button"] = true;
+dojo.provide("dijit.form.Button");
+
+
+
+
+dojo.declare("dijit.form.Button",
+	dijit.form._FormWidget,
+	{
+	// summary:
+	//		Basically the same thing as a normal HTML button, but with special styling.
+	// description:
+	//		Buttons can display a label, an icon, or both.
+	//		A label should always be specified (through innerHTML) or the label
+	//		attribute.  It can be hidden via showLabel=false.
+	// example:
+	// |	<button dojoType="dijit.form.Button" onClick="...">Hello world</button>
+	// 
+	// example:
+	// |	var button1 = new dijit.form.Button({label: "hello world", onClick: foo});
+	// |	dojo.body().appendChild(button1.domNode);
+
+	// label: HTML String
+	//		Text to display in button.
+	//		If the label is hidden (showLabel=false) then and no title has
+	//		been specified, then label is also set as title attribute of icon.
+	label: "",
+
+	// showLabel: Boolean
+	//		Set this to true to hide the label text and display only the icon.
+	//		(If showLabel=false then iconClass must be specified.)
+	//		Especially useful for toolbars.  
+	//		If showLabel=true, the label will become the title (a.k.a. tooltip/hint) of the icon.
+	//
+	//		The exception case is for computers in high-contrast mode, where the label
+	//		will still be displayed, since the icon doesn't appear.
+	showLabel: true,
+
+	// iconClass: String
+	//		Class to apply to div in button to make it display an icon
+	iconClass: "",
+
+	// type: String
+	//		Defines the type of button.  "button", "submit", or "reset".
+	type: "button",
+
+	baseClass: "dijitButton",
+
+	templateString:"<span class=\"dijit dijitReset dijitLeft dijitInline\"\n\tdojoAttachEvent=\"ondijitclick:_onButtonClick,onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse\"\n\t><span class=\"dijitReset dijitRight dijitInline\"\n\t\t><span class=\"dijitReset dijitInline dijitButtonNode\"\n\t\t\t><button class=\"dijitReset dijitStretch dijitButtonContents\"\n\t\t\t\tdojoAttachPoint=\"titleNode,focusNode\" \n\t\t\t\t${nameAttrSetting} type=\"${type}\" value=\"${value}\" waiRole=\"button\" waiState=\"labelledby-${id}_label\"\n\t\t\t\t><span class=\"dijitReset dijitInline\" dojoAttachPoint=\"iconNode\" \n\t\t\t\t\t><span class=\"dijitReset dijitToggleButtonIconChar\">&#10003;</span \n\t\t\t\t></span \n\t\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\" \n\t\t\t\t\tid=\"${id}_label\"  \n\t\t\t\t\tdojoAttachPoint=\"containerNode\"\n\t\t\t\t></span\n\t\t\t></button\n\t\t></span\n\t></span\n></span>\n",
+
+	attributeMap: dojo.delegate(dijit.form._FormWidget.prototype.attributeMap, {
+		label: { node: "containerNode", type: "innerHTML" },
+		iconClass: { node: "iconNode", type: "class" }
+	}),
+		
+
+	_onClick: function(/*Event*/ e){
+		// summary:
+		//		Internal function to handle click actions
+		if(this.disabled || this.readOnly){
+			return false;
+		}
+		this._clicked(); // widget click actions
+		return this.onClick(e); // user click actions
+	},
+
+	_onButtonClick: function(/*Event*/ e){
+		// summary:
+		//		Handler when the user activates the button portion.
+		//		If is activated via a keystroke, stop the event unless is submit or reset.
+		if(e.type!='click' && !(this.type=="submit" || this.type=="reset")){
+			dojo.stopEvent(e);
+		}
+		if(this._onClick(e) === false){ // returning nothing is same as true
+			e.preventDefault(); // needed for checkbox
+		}else if(this.type=="submit" && !this.focusNode.form){ // see if a nonform widget needs to be signalled
+			for(var node=this.domNode; node.parentNode/*#5935*/; node=node.parentNode){
+				var widget=dijit.byNode(node);
+				if(widget && typeof widget._onSubmit == "function"){
+					widget._onSubmit(e);
+					break;
+				}
+			}
+		}
+	},
+
+	_setValueAttr: function(/*String*/ value){
+		// Verify that value cannot be set for BUTTON elements.
+		var attr = this.attributeMap.value || '';
+		if(this[attr.node||attr||'domNode'].tagName == 'BUTTON'){
+			// On IE, setting value actually overrides innerHTML, so disallow for everyone for consistency
+			if(value != this.value){
+				
+			}
+		}
+	},
+
+	_fillContent: function(/*DomNode*/ source){
+		// Overrides _Templated._fillcContent().
+		// If button label is specified as srcNodeRef.innerHTML rather than
+		// this.params.label, handle it here.
+		if(source && !("label" in this.params)){
+			this.attr('label', source.innerHTML);
+		}
+	},
+
+	postCreate: function(){
+		if (this.showLabel == false){
+			dojo.addClass(this.containerNode,"dijitDisplayNone");
+		}
+		dojo.setSelectable(this.focusNode, false);
+		this.inherited(arguments);
+	},
+
+	onClick: function(/*Event*/ e){
+		// summary:
+		//		Callback for when button is clicked.
+		//		If type="submit", return true to perform submit, or false to cancel it.
+		// type:
+		//		callback
+		return true;		// Boolean
+	},
+
+	_clicked: function(/*Event*/ e){
+		// summary:
+		//		Internal overridable function for when the button is clicked
+	},
+
+	setLabel: function(/*String*/ content){
+		// summary:
+		//		Deprecated.  Use attr('label', ...) instead.
+		dojo.deprecated("dijit.form.Button.setLabel() is deprecated.  Use attr('label', ...) instead.", "", "2.0");
+		this.attr("label", content);
+	},
+	_setLabelAttr: function(/*String*/ content){
+		// summary:
+		//		Hook for attr('label', ...) to work.
+		// description:
+		//		Set the label (text) of the button; takes an HTML string.
+		this.containerNode.innerHTML = this.label = content;
+		this._layoutHack();
+		if (this.showLabel == false && !this.params.title){
+			this.titleNode.title = dojo.trim(this.containerNode.innerText || this.containerNode.textContent || '');
+		}
+	}		
+});
+
+
+dojo.declare("dijit.form.DropDownButton", [dijit.form.Button, dijit._Container], {
+	// summary:
+	//		A button with a drop down
+	//
+	// example:
+	// |	<button dojoType="dijit.form.DropDownButton" label="Hello world">
+	// |		<div dojotype="dijit.Menu">...</div>
+	// |	</button>
+	//
+	// example:
+	// |	var button1 = new dijit.form.DropDownButton({ label: "hi", dropDown: new dijit.Menu(...) });
+	// |	dojo.body().appendChild(button1);
+	// 	
+	
+	baseClass : "dijitDropDownButton",
+
+	templateString:"<span class=\"dijit dijitReset dijitLeft dijitInline\"\n\tdojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse,onclick:_onDropDownClick,onkeydown:_onDropDownKeydown,onblur:_onDropDownBlur,onkeypress:_onKey\"\n\t><span class='dijitReset dijitRight dijitInline'\n\t\t><span class='dijitReset dijitInline dijitButtonNode'\n\t\t\t><button class=\"dijitReset dijitStretch dijitButtonContents\" \n\t\t\t\t${nameAttrSetting} type=\"${type}\" value=\"${value}\"\n\t\t\t\tdojoAttachPoint=\"focusNode,titleNode\" \n\t\t\t\twaiRole=\"button\" waiState=\"haspopup-true,labelledby-${id}_label\"\n\t\t\t\t><span class=\"dijitReset dijitInline\" \n\t\t\t\t\tdojoAttachPoint=\"iconNode\"\n\t\t\t\t></span\n\t\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"  \n\t\t\t\t\tdojoAttachPoint=\"containerNode,popupStateNode\" \n\t\t\t\t\tid=\"${id}_label\"\n\t\t\t\t></span\n\t\t\t\t><span class=\"dijitReset dijitInline dijitArrowButtonInner\">&thinsp;</span\n\t\t\t\t><span class=\"dijitReset dijitInline dijitArrowButtonChar\">&#9660;</span\n\t\t\t></button\n\t\t></span\n\t></span\n></span>\n",
+
+	_fillContent: function(){
+		// Overrides Button._fillContent().
+		//
+		// My inner HTML contains both the button contents and a drop down widget, like
+		// <DropDownButton>  <span>push me</span>  <Menu> ... </Menu> </DropDownButton>
+		// The first node is assumed to be the button content. The widget is the popup.
+
+		if(this.srcNodeRef){ // programatically created buttons might not define srcNodeRef
+			//FIXME: figure out how to filter out the widget and use all remaining nodes as button
+			//	content, not just nodes[0]
+			var nodes = dojo.query("*", this.srcNodeRef);
+			dijit.form.DropDownButton.superclass._fillContent.call(this, nodes[0]);
+
+			// save pointer to srcNode so we can grab the drop down widget after it's instantiated
+			this.dropDownContainer = this.srcNodeRef;
+		}
+	},
+
+	startup: function(){
+		if(this._started){ return; }
+
+		// the child widget from srcNodeRef is the dropdown widget.  Insert it in the page DOM,
+		// make it invisible, and store a reference to pass to the popup code.
+		if(!this.dropDown){
+			var dropDownNode = dojo.query("[widgetId]", this.dropDownContainer)[0];
+			this.dropDown = dijit.byNode(dropDownNode);
+			delete this.dropDownContainer;
+		}
+		dijit.popup.prepare(this.dropDown.domNode);
+
+		this.inherited(arguments);
+	},
+
+	destroyDescendants: function(){
+		if(this.dropDown){
+			this.dropDown.destroyRecursive();
+			delete this.dropDown;
+		}
+		this.inherited(arguments);
+	},
+
+	_onArrowClick: function(/*Event*/ e){
+		// summary:
+		//		Handler for when the user mouse clicks on menu popup node
+		if(this.disabled || this.readOnly){ return; }
+		this._toggleDropDown();
+	},
+
+	_onDropDownClick: function(/*Event*/ e){
+		// on Firefox 2 on the Mac it is possible to fire onclick
+		// by pressing enter down on a second element and transferring
+		// focus to the DropDownButton;
+		// we want to prevent opening our menu in this situation
+		// and only do so if we have seen a keydown on this button;
+		// e.detail != 0 means that we were fired by mouse
+		var isMacFFlessThan3 = dojo.isFF && dojo.isFF < 3
+			&& navigator.appVersion.indexOf("Macintosh") != -1;
+		if(!isMacFFlessThan3 || e.detail != 0 || this._seenKeydown){
+			this._onArrowClick(e);
+		}
+		this._seenKeydown = false;
+	},
+
+	_onDropDownKeydown: function(/*Event*/ e){
+		this._seenKeydown = true;
+	},
+
+	_onDropDownBlur: function(/*Event*/ e){
+		this._seenKeydown = false;
+	},
+
+	_onKey: function(/*Event*/ e){
+		// summary:
+		//		Handler when the user presses a key on drop down widget
+		if(this.disabled || this.readOnly){ return; }
+		if(e.charOrCode == dojo.keys.DOWN_ARROW){
+			if(!this.dropDown || this.dropDown.domNode.style.visibility=="hidden"){
+				dojo.stopEvent(e);
+				this._toggleDropDown();
+			}
+		}
+	},
+
+	_onBlur: function(){
+		// summary:
+		//		Called magically when focus has shifted away from this widget and it's dropdown
+		this._closeDropDown();
+		// don't focus on button.  the user has explicitly focused on something else.
+		this.inherited(arguments);
+	},
+
+	_toggleDropDown: function(){
+		// summary:
+		//		Toggle the drop-down widget; if it is up, close it; if not, open it.
+		if(this.disabled || this.readOnly){ return; }
+		dijit.focus(this.popupStateNode);
+		var dropDown = this.dropDown;
+		if(!dropDown){ return; }
+		if(!this._opened){
+			// If there's an href, then load that first, so we don't get a flicker
+			if(dropDown.href && !dropDown.isLoaded){
+				var self = this;
+				var handler = dojo.connect(dropDown, "onLoad", function(){
+					dojo.disconnect(handler);
+					self._openDropDown();
+				});
+				dropDown.refresh();
+				return;
+			}else{
+				this._openDropDown();
+			}
+		}else{
+			this._closeDropDown();
+		}
+	},
+
+	_openDropDown: function(){
+		var dropDown = this.dropDown;
+		var oldWidth=dropDown.domNode.style.width;
+		var self = this;
+
+		dijit.popup.open({
+			parent: this,
+			popup: dropDown,
+			around: this.domNode,
+			orient:
+				// TODO: add user-defined positioning option, like in Tooltip.js
+				this.isLeftToRight() ? {'BL':'TL', 'BR':'TR', 'TL':'BL', 'TR':'BR'}
+				: {'BR':'TR', 'BL':'TL', 'TR':'BR', 'TL':'BL'},
+			onExecute: function(){
+				self._closeDropDown(true);
+			},
+			onCancel: function(){
+				self._closeDropDown(true);
+			},
+			onClose: function(){
+				dropDown.domNode.style.width = oldWidth;
+				self.popupStateNode.removeAttribute("popupActive");
+				self._opened = false;
+			}
+		});
+		if(this.domNode.offsetWidth > dropDown.domNode.offsetWidth){
+			var adjustNode = null;
+			if(!this.isLeftToRight()){
+				adjustNode = dropDown.domNode.parentNode;
+				var oldRight = adjustNode.offsetLeft + adjustNode.offsetWidth;
+			}
+			// make menu at least as wide as the button
+			dojo.marginBox(dropDown.domNode, {w: this.domNode.offsetWidth});
+			if(adjustNode){
+				adjustNode.style.left = oldRight - this.domNode.offsetWidth + "px";
+			}
+		}
+		this.popupStateNode.setAttribute("popupActive", "true");
+		this._opened=true;
+		if(dropDown.focus){
+			dropDown.focus();
+		}
+		// TODO: set this.checked and call setStateClass(), to affect button look while drop down is shown
+	},
+	
+	_closeDropDown: function(/*Boolean*/ focus){
+		if(this._opened){
+			dijit.popup.close(this.dropDown);
+			if(focus){ this.focus(); }
+			this._opened = false;			
+		}
+	}
+});
+
+dojo.declare("dijit.form.ComboButton", dijit.form.DropDownButton, {
+	// summary:
+	//		A combination button and drop-down button.
+	//		Users can click one side to "press" the button, or click an arrow
+	//		icon to display the drop down.
+	//
+	// example:
+	// |	<button dojoType="dijit.form.ComboButton" onClick="...">
+	// |		<span>Hello world</span>
+	// |		<div dojoType="dijit.Menu">...</div>
+	// |	</button>
+	//
+	// example:
+	// |	var button1 = new dijit.form.ComboButton({label: "hello world", onClick: foo, dropDown: "myMenu"});
+	// |	dojo.body().appendChild(button1.domNode);
+	// 
+
+	templateString:"<table class='dijit dijitReset dijitInline dijitLeft'\n\tcellspacing='0' cellpadding='0' waiRole=\"presentation\"\n\t><tbody waiRole=\"presentation\"><tr waiRole=\"presentation\"\n\t\t><td class=\"dijitReset dijitStretch dijitButtonContents dijitButtonNode\"\n\t\t\tdojoAttachEvent=\"ondijitclick:_onButtonClick,onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse\"  dojoAttachPoint=\"titleNode\"\n\t\t\twaiRole=\"button\" waiState=\"labelledby-${id}_label\"\n\t\t\t><div class=\"dijitReset dijitInline\" dojoAttachPoint=\"iconNode\" waiRole=\"presentation\"></div\n\t\t\t><div class=\"dijitReset dijitInline dijitButtonText\" id=\"${id}_label\" dojoAttachPoint=\"containerNode\" waiRole=\"presentation\"></div\n\t\t></td\n\t\t><td class='dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton'\n\t\t\tdojoAttachPoint=\"popupStateNode,focusNode\"\n\t\t\tdojoAttachEvent=\"ondijitclick:_onArrowClick, onkeypress:_onKey,onmouseenter:_onMouse,onmouseleave:_onMouse\"\n\t\t\tstateModifier=\"DownArrow\"\n\t\t\ttitle=\"${optionsTitle}\" ${nameAttrSetting}\n\t\t\twaiRole=\"button\" waiState=\"haspopup-true\"\n\t\t\t><div class=\"dijitReset dijitArrowButtonInner\" waiRole=\"presentation\">&thinsp;</div\n\t\t\t><div class=\"dijitReset dijitArrowButtonChar\" waiRole=\"presentation\">&#9660;</div\n\t\t></td\n\t></tr></tbody\n></table>\n",
+
+	attributeMap: dojo.mixin(dojo.clone(dijit.form.Button.prototype.attributeMap), {
+		id:"",
+		tabIndex: ["focusNode", "titleNode"]
+	}),
+
+	// optionsTitle: String
+	//		Text that describes the options menu (accessibility)
+	optionsTitle: "",
+
+	baseClass: "dijitComboButton",
+
+	_focusedNode: null,
+
+	postCreate: function(){
+		this.inherited(arguments);
+		this._focalNodes = [this.titleNode, this.popupStateNode];
+		dojo.forEach(this._focalNodes, dojo.hitch(this, function(node){
+			if(dojo.isIE){
+				this.connect(node, "onactivate", this._onNodeFocus);
+				this.connect(node, "ondeactivate", this._onNodeBlur);
+			}else{
+				this.connect(node, "onfocus", this._onNodeFocus);
+				this.connect(node, "onblur", this._onNodeBlur);
+			}
+		}));
+	},
+
+	focusFocalNode: function(node){
+		// summary:
+		//		Focus the focal node node.
+		// description:
+		//		Called by _KeyNavContainer for (when example) this button is in a toolbar.
+		// tags:
+		//		protected
+		this._focusedNode = node;
+		dijit.focus(node);
+	},
+
+	hasNextFocalNode: function(){
+		// summary:
+		//		Returns true if this widget has no node currently
+		//		focused or if there is a node following the focused one.
+		//		False is returned if the last node has focus.
+		// description:
+		//		Called by _KeyNavContainer for (when example) this button is in a toolbar.
+		// tags:
+		//		protected
+		return this._focusedNode !== this.getFocalNodes()[1];
+	},
+
+	focusNext: function(){
+		// summary:
+		//		Focus the focal node following the current node with focus,
+		//		or the first one if no node currently has focus.
+		// description:
+		//		Called by _KeyNavContainer for (when example) this button is in a toolbar.
+		// tags:
+		//		protected
+		this._focusedNode = this.getFocalNodes()[this._focusedNode ? 1 : 0];
+		dijit.focus(this._focusedNode);
+	},
+
+	hasPrevFocalNode: function(){
+		// summary:
+		//		Returns true if this widget has no node currently
+		//		focused or if there is a node before the focused one.
+		//		False is returned if the first node has focus.
+		// description:
+		//		Called by _KeyNavContainer for (when example) this button is in a toolbar.
+		// tags:
+		//		protected
+		return this._focusedNode !== this.getFocalNodes()[0];
+	},
+
+	focusPrev: function(){
+		// summary:
+		//		Focus the focal node before the current node with focus
+		//		or the last one if no node currently has focus.
+		// description:
+		//		Called by _KeyNavContainer for (when example) this button is in a toolbar.
+		// tags:
+		//		protected
+		this._focusedNode = this.getFocalNodes()[this._focusedNode ? 0 : 1];
+		dijit.focus(this._focusedNode);
+	},
+
+	getFocalNodes: function(){
+		// summary:
+		//		Returns an array of focal nodes for this widget.
+		// description:
+		//		Called by _KeyNavContainer for (when example) this button is in a toolbar.
+		// tags:
+		//		protected
+		return this._focalNodes;
+	},
+
+	_onNodeFocus: function(evt){
+		this._focusedNode = evt.currentTarget;
+		var fnc = this._focusedNode == this.focusNode ? "dijitDownArrowButtonFocused" : "dijitButtonContentsFocused";
+		dojo.addClass(this._focusedNode, fnc);
+	},
+
+	_onNodeBlur: function(evt){
+		var fnc = evt.currentTarget == this.focusNode ? "dijitDownArrowButtonFocused" : "dijitButtonContentsFocused";
+		dojo.removeClass(evt.currentTarget, fnc);
+	},
+
+	_onBlur: function(){
+		this.inherited(arguments);
+		this._focusedNode = null;
+	}
+});
+
+dojo.declare("dijit.form.ToggleButton", dijit.form.Button, {
+	// summary:
+	//		A button that can be in two states (checked or not).
+	//		Can be base class for things like tabs or checkbox or radio buttons
+
+	baseClass: "dijitToggleButton",
+
+	// checked: Boolean
+	//		Corresponds to the native HTML <input> element's attribute.
+	//		In markup, specified as "checked='checked'" or just "checked".
+	//		True if the button is depressed, or the checkbox is checked,
+	//		or the radio button is selected, etc.
+	checked: false,
+
+	attributeMap: dojo.mixin(dojo.clone(dijit.form.Button.prototype.attributeMap),
+		{checked:"focusNode"}),
+
+	_clicked: function(/*Event*/ evt){
+		this.attr('checked', !this.checked);
+	},
+
+	_setCheckedAttr: function(/*Boolean*/ value){
+		this.checked = value;
+		dojo.attr(this.focusNode || this.domNode, "checked", value);
+		dijit.setWaiState(this.focusNode || this.domNode, "pressed", value);
+		this._setStateClass();		
+		this._handleOnChange(value, true);
+	},
+
+	setChecked: function(/*Boolean*/ checked){
+		// summary:
+		//		Deprecated.   Use attr('checked', true/false) instead.
+		dojo.deprecated("setChecked("+checked+") is deprecated. Use attr('checked',"+checked+") instead.", "", "2.0");
+		this.attr('checked', checked);
+	},
+	
+	reset: function(){
+		// summary:
+		//		Reset the widget's value to what it was at initialization time
+
+		this._hasBeenBlurred = false;
+
+		// set checked state to original setting
+		this.attr('checked', this.params.checked || false);
+	}
+});
+
+}
+
+if(!dojo._hasResource["dijit.form.CheckBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.CheckBox"] = true;
+dojo.provide("dijit.form.CheckBox");
+
+
+
+dojo.declare(
+	"dijit.form.CheckBox",
+	dijit.form.ToggleButton,
+	{
+		// summary:
+		// 		Same as an HTML checkbox, but with fancy styling.
+		//
+		// description:
+		// User interacts with real html inputs.
+		// On onclick (which occurs by mouse click, space-bar, or
+		// using the arrow keys to switch the selected radio button),
+		// we update the state of the checkbox/radio.
+		//
+		// There are two modes:
+		//   1. High contrast mode
+		//   2. Normal mode
+		// In case 1, the regular html inputs are shown and used by the user.
+		// In case 2, the regular html inputs are invisible but still used by
+		// the user. They are turned quasi-invisible and overlay the background-image.
+
+		templateString:"<div class=\"dijitReset dijitInline\" waiRole=\"presentation\"\n\t><input\n\t \t${nameAttrSetting} type=\"${type}\" ${checkedAttrSetting}\n\t\tclass=\"dijitReset dijitCheckBoxInput\"\n\t\tdojoAttachPoint=\"focusNode\"\n\t \tdojoAttachEvent=\"onmouseover:_onMouse,onmouseout:_onMouse,onclick:_onClick\"\n/></div>\n",
+
+		baseClass: "dijitCheckBox",
+
+		// type: [private] String
+		//		type attribute on <input> node.
+		//		Overrides `dijit.form.Button.type`.   Users should not change this value.
+		type: "checkbox",
+
+		// value: String
+		//		As an initialization parameter, equivalent to value field on normal checkbox
+		//		(if checked, the value is passed as the value when form is submitted).
+		//
+		//		However, attr('value') will return either the string or false depending on
+		//		whether or not the checkbox is checked.
+		//
+		//		attr('value', string) will check the checkbox and change the value to the
+		//		specified string
+		//
+		//		attr('value', boolean) will change the checked state.
+		value: "on",
+
+		_setValueAttr: function(/*String or Boolean*/ newValue){
+			// summary:
+			//		Handler for value= attribute to constructor, and also calls to
+			//		attr('value', val).
+			// description:
+			//		During initialization, just saves as attribute to the <input type=checkbox>.
+			//		
+			//		After initialization,
+			//		when passed a boolean, controls whether or not the CheckBox is checked.
+			//		If passed a string, changes the value attribute of the CheckBox (the one
+			//		specified as "value" when the CheckBox was constructed (ex: <input
+			//		dojoType="dijit.CheckBox" value="chicken">)
+			if(typeof newValue == "string"){
+				this.value = newValue;
+				dojo.attr(this.focusNode, 'value', newValue);
+				newValue = true;
+			}
+			if(this._created){
+				this.attr('checked', newValue);
+			}
+		},
+		_getValueAttr: function(){
+			// summary:
+			//		Hook so attr('value') works.
+			// description:
+			//		If the CheckBox is checked, returns the value attribute.
+			//		Otherwise returns false.
+			return (this.checked ? this.value : false);
+		},
+
+		postMixInProperties: function(){
+			if(this.value == ""){
+				this.value = "on";
+			}
+
+			// Need to set initial checked state as part of template, so that form submit works.
+			// dojo.attr(node, "checked", bool) doesn't work on IEuntil node has been attached
+			// to <body>, see #8666
+			this.checkedAttrSetting = this.checked ? "checked" : "";
+
+			this.inherited(arguments);
+		},
+		
+		 _fillContent: function(/*DomNode*/ source){
+			// Override Button::_fillContent() since it doesn't make sense for CheckBox,
+			// since CheckBox doesn't even have a container
+		},
+
+		reset: function(){
+			// Override ToggleButton.reset()
+
+			this._hasBeenBlurred = false;
+
+			this.attr('checked', this.params.checked || false);
+
+			// Handle unlikely event that the <input type=checkbox> value attribute has changed
+			this.value = this.params.value || "on";
+			dojo.attr(this.focusNode, 'value', this.value);
+		},
+		
+		_onFocus: function(){
+			if(this.id){
+				dojo.query("label[for='"+this.id+"']").addClass("dijitFocusedLabel");
+			}
+		},
+
+		_onBlur: function(){
+			if(this.id){
+				dojo.query("label[for='"+this.id+"']").removeClass("dijitFocusedLabel");
+			}
+		}
+	}
+);
+
+dojo.declare(
+	"dijit.form.RadioButton",
+	dijit.form.CheckBox,
+	{
+		// summary:
+		// 		Same as an HTML radio, but with fancy styling.
+
+		type: "radio",
+		baseClass: "dijitRadio",
+
+		_setCheckedAttr: function(/*Boolean*/ value){
+			// If I am being checked then have to deselect currently checked radio button
+			this.inherited(arguments);
+			if(!this._created){ return; }
+			if(value){
+				var _this = this;
+				// search for radio buttons with the same name that need to be unchecked
+				dojo.query("INPUT[type=radio]", this.focusNode.form||dojo.doc).forEach( // can't use name= since dojo.query doesn't support [] in the name
+					function(inputNode){
+						if(inputNode.name == _this.name && inputNode != _this.focusNode && inputNode.form == _this.focusNode.form){
+							var widget = dijit.getEnclosingWidget(inputNode);
+							if(widget && widget.checked){
+								widget.attr('checked', false);
+							}
+						}
+					}
+				);
+			}
+		},
+
+		_clicked: function(/*Event*/ e){
+			if(!this.checked){
+				this.attr('checked', true);
+			}
+		}
+	}
+);
+
+}
+
+if(!dojo._hasResource["dijit.form.TextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.TextBox"] = true;
+dojo.provide("dijit.form.TextBox");
+
+
+
+dojo.declare(
+	"dijit.form.TextBox",
+	dijit.form._FormValueWidget,
+	{
+		//	summary:
+		//		A base class for textbox form inputs
+
+		//	trim: Boolean
+		//		Removes leading and trailing whitespace if true.  Default is false.
+		trim: false,
+
+		//	uppercase: Boolean
+		//		Converts all characters to uppercase if true.  Default is false.
+		uppercase: false,
+
+		//	lowercase: Boolean
+		//		Converts all characters to lowercase if true.  Default is false.
+		lowercase: false,
+
+		//	propercase: Boolean
+		//		Converts the first character of each word to uppercase if true.
+		propercase: false,
+
+		//	maxLength: String
+		//		HTML INPUT tag maxLength declaration.
+		maxLength: "",
+
+		templateString:"<input class=\"dijit dijitReset dijitLeft\" dojoAttachPoint='textbox,focusNode'\n\tdojoAttachEvent='onmouseenter:_onMouse,onmouseleave:_onMouse'\n\tautocomplete=\"off\" type=\"${type}\" ${nameAttrSetting}\n\t/>\n",
+		baseClass: "dijitTextBox",
+
+		attributeMap: dojo.delegate(dijit.form._FormValueWidget.prototype.attributeMap, {
+			maxLength: "focusNode" 
+		}),
+
+		_getValueAttr: function(){
+			// summary:
+			//		Hook so attr('value') works as we like.
+			// description:
+			//		For `dijit.form.TextBox` this basically returns the value of the <input>.
+			//
+			//		For `dijit.form.MappedTextBox` subclasses, which have both
+			//		a "displayed value" and a separate "submit value",
+			//		This treats the "displayed value" as the master value, computing the
+			//		submit value from it via this.parse().
+			return this.parse(this.attr('displayedValue'), this.constraints);
+		},
+
+		_setValueAttr: function(value, /*Boolean?*/ priorityChange, /*String?*/ formattedValue){
+			// summary:
+			//		Hook so attr('value', ...) works.
+			//
+			// description: 
+			//		Sets the value of the widget to "value" which can be of
+			//		any type as determined by the widget.
+			//
+			// value:
+			//		The visual element value is also set to a corresponding,
+			//		but not necessarily the same, value.
+			//
+			// formattedValue:
+			//		If specified, used to set the visual element value,
+			//		otherwise a computed visual value is used.
+			//
+			// priorityChange:
+			//		If true, an onChange event is fired immediately instead of 
+			//		waiting for the next blur event.
+
+			var filteredValue;
+			if(value !== undefined){
+				// TODO: this is calling filter() on both the display value and the actual value.
+				// I added a comment to the filter() definition about this, but it should be changed.
+				filteredValue = this.filter(value);
+				if(typeof formattedValue != "string"){
+					if(filteredValue !== null && ((typeof filteredValue != "number") || !isNaN(filteredValue))){
+						formattedValue = this.filter(this.format(filteredValue, this.constraints));
+					}else{ formattedValue = ''; }
+				}
+			}
+			if(formattedValue != null && formattedValue != undefined && ((typeof formattedValue) != "number" || !isNaN(formattedValue)) && this.textbox.value != formattedValue){
+				this.textbox.value = formattedValue;
+			}
+			this.inherited(arguments, [filteredValue, priorityChange]);
+		},
+
+		// displayedValue: String
+		//		For subclasses like ComboBox where the displayed value
+		//		(ex: Kentucky) and the serialized value (ex: KY) are different,
+		//		this represents the displayed value.
+		//
+		//		Setting 'displayedValue' through attr('displayedValue', ...)
+		//		updates 'value', and vice-versa.  Othewise 'value' is updated
+		//		from 'displayedValue' periodically, like onBlur etc.
+		//
+		//		TODO: move declaration to MappedTextBox?
+		//		Problem is that ComboBox references displayedValue,
+		//		for benefit of FilteringSelect.
+		displayedValue: "",
+
+		getDisplayedValue: function(){
+			// summary:
+			//		Deprecated.   Use attr('displayedValue') instead.
+			// tags:
+			//		deprecated
+			dojo.deprecated(this.declaredClass+"::getDisplayedValue() is deprecated. Use attr('displayedValue') instead.", "", "2.0");
+			return this.attr('displayedValue');
+		},
+
+		_getDisplayedValueAttr: function(){
+			// summary:
+			//		Hook so attr('displayedValue') works.
+			// description:
+			//		Returns the displayed value (what the user sees on the screen),
+			// 		after filtering (ie, trimming spaces etc.).
+			//
+			//		For some subclasses of TextBox (like ComboBox), the displayed value
+			//		is different from the serialized value that's actually 
+			//		sent to the server (see dijit.form.ValidationTextBox.serialize)
+			
+			return this.filter(this.textbox.value);
+		},
+
+		setDisplayedValue: function(/*String*/value){
+			// summary:
+			//		Deprecated.   Use attr('displayedValue', ...) instead.
+			// tags:
+			//		deprecated
+			dojo.deprecated(this.declaredClass+"::setDisplayedValue() is deprecated. Use attr('displayedValue', ...) instead.", "", "2.0");
+			this.attr('displayedValue', value);
+		},
+			
+		_setDisplayedValueAttr: function(/*String*/value){
+			// summary:
+			//		Hook so attr('displayedValue', ...) works.
+			//	description: 
+			//		Sets the value of the visual element to the string "value".
+			//		The widget value is also set to a corresponding,
+			//		but not necessarily the same, value.
+
+			if(value === null || value === undefined){ value = '' }
+			else if(typeof value != "string"){ value = String(value) }
+			this.textbox.value = value;
+			this._setValueAttr(this.attr('value'), undefined, value);
+		},
+
+		format: function(/* String */ value, /* Object */ constraints){
+			// summary:
+			//		Replacable function to convert a value to a properly formatted string.
+			// tags:
+			//		protected extension
+			return ((value == null || value == undefined) ? "" : (value.toString ? value.toString() : value));
+		},
+
+		parse: function(/* String */ value, /* Object */ constraints){
+			// summary:
+			//		Replacable function to convert a formatted string to a value
+			// tags:
+			//		protected extension
+
+			return value;	// String
+		},
+
+		_refreshState: function(){
+			// summary:
+			//		After the user types some characters, etc., this method is
+			//		called to check the field for validity etc.  The base method
+			//		in `dijit.form.TextBox` does nothing, but subclasses override.
+			// tags:
+			//		protected
+		},
+
+		_onInput: function(e){
+			if(e && e.type && /key/i.test(e.type) && e.keyCode){
+				switch(e.keyCode){
+					case dojo.keys.SHIFT:
+					case dojo.keys.ALT:
+					case dojo.keys.CTRL:
+					case dojo.keys.TAB:
+						return;
+				}
+			}
+			if(this.intermediateChanges){
+				var _this = this;
+				// the setTimeout allows the key to post to the widget input box
+				setTimeout(function(){ _this._handleOnChange(_this.attr('value'), false); }, 0);
+			}
+			this._refreshState();
+		},
+
+		postCreate: function(){
+			// setting the value here is needed since value="" in the template causes "undefined"
+			// and setting in the DOM (instead of the JS object) helps with form reset actions
+			this.textbox.setAttribute("value", this.textbox.value); // DOM and JS values shuld be the same
+			this.inherited(arguments);
+			if(dojo.isMoz || dojo.isOpera){
+				this.connect(this.textbox, "oninput", this._onInput);
+			}else{
+				this.connect(this.textbox, "onkeydown", this._onInput);
+				this.connect(this.textbox, "onkeyup", this._onInput);
+				this.connect(this.textbox, "onpaste", this._onInput);
+				this.connect(this.textbox, "oncut", this._onInput);
+			}
+
+			/*#5297:if(this.srcNodeRef){
+				dojo.style(this.textbox, "cssText", this.style);
+				this.textbox.className += " " + this["class"];
+			}*/
+			this._layoutHack();
+		},
+
+		_blankValue: '', // if the textbox is blank, what value should be reported
+		filter: function(val){
+			// summary:
+			//		Auto-corrections (such as trimming) that are applied to textbox
+			//		value on blur or form submit.
+			// description:
+			//		For MappedTextBox subclasses, this is called twice
+			// 			- once with the display value
+			//			- once the value as set/returned by attr('value', ...)
+			//		and attr('value'), ex: a Number for NumberTextBox.
+			//
+			//		In the latter case it does corrections like converting null to NaN.  In
+			//		the former case the NumberTextBox.filter() method calls this.inherited()
+			//		to execute standard trimming code in TextBox.filter().
+			//
+			//		TODO: break this into two methods in 2.0
+			//
+			// tags:
+			//		protected extension
+			if(val === null){ return this._blankValue; }
+			if(typeof val != "string"){ return val; }
+			if(this.trim){
+				val = dojo.trim(val);
+			}
+			if(this.uppercase){
+				val = val.toUpperCase();
+			}
+			if(this.lowercase){
+				val = val.toLowerCase();
+			}
+			if(this.propercase){
+				val = val.replace(/[^\s]+/g, function(word){
+					return word.substring(0,1).toUpperCase() + word.substring(1);
+				});
+			}
+			return val;
+		},
+
+		_setBlurValue: function(){
+			this._setValueAttr(this.attr('value'), true);
+		},
+
+		_onBlur: function(e){
+			if(this.disabled){ return; }
+			this._setBlurValue();
+			this.inherited(arguments);
+		},
+
+		_onFocus: function(e){
+			if(this.disabled){ return; }
+			this._refreshState();
+			this.inherited(arguments);
+		},
+
+		reset: function(){
+			// Overrides dijit._FormWidget.reset().
+			// Additionally resets the displayed textbox value to ''
+			this.textbox.value = '';
+			this.inherited(arguments);
+		}
+	}
+);
+
+dijit.selectInputText = function(/*DomNode*/element, /*Number?*/ start, /*Number?*/ stop){
+	// summary:
+	//		Select text in the input element argument, from start (default 0), to stop (default end).
+
+	// TODO: use functions in _editor/selection.js?
+	var _window = dojo.global;
+	var _document = dojo.doc;
+	element = dojo.byId(element);
+	if(isNaN(start)){ start = 0; }
+	if(isNaN(stop)){ stop = element.value ? element.value.length : 0; }
+	element.focus();
+	if(_document["selection"] && dojo.body()["createTextRange"]){ // IE
+		if(element.createTextRange){
+			var range = element.createTextRange();
+			with(range){
+				collapse(true);
+				moveStart("character", start);
+				moveEnd("character", stop);
+				select();
+			}
+		}
+	}else if(_window["getSelection"]){
+		var selection = _window.getSelection();	// TODO: unused, remove
+		// FIXME: does this work on Safari?
+		if(element.setSelectionRange){
+			element.setSelectionRange(start, stop);
+		}
+	}
+};
+
+}
+
+if(!dojo._hasResource["dijit.form.ValidationTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.ValidationTextBox"] = true;
+dojo.provide("dijit.form.ValidationTextBox");
+
+
+
+
+
+
+
+
+/*=====
+	dijit.form.ValidationTextBox.__Constraints = function(){
+		// locale: String
+		//		locale used for validation, picks up value from this widget's lang attribute
+		// _flags_: anything
+		//		various flags passed to regExpGen function
+		this.locale = "";
+		this._flags_ = "";
+	}
+=====*/
+
+dojo.declare(
+	"dijit.form.ValidationTextBox",
+	dijit.form.TextBox,
+	{
+		// summary:
+		//		Base class for textbox widgets with the ability to validate content of various types and provide user feedback.
+		// tags:
+		//		protected
+
+		templateString:"<div class=\"dijit dijitReset dijitInlineTable dijitLeft\"\n\tid=\"widget_${id}\"\n\tdojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse\" waiRole=\"presentation\"\n\t><div style=\"overflow:hidden;\"\n\t\t><div class=\"dijitReset dijitValidationIcon\"><br></div\n\t\t><div class=\"dijitReset dijitValidationIconText\">&Chi;</div\n\t\t><div class=\"dijitReset dijitInputField\"\n\t\t\t><input class=\"dijitReset\" dojoAttachPoint='textbox,focusNode' autocomplete=\"off\"\n\t\t\t${nameAttrSetting} type='${type}'\n\t\t/></div\n\t></div\n></div>\n",
+		baseClass: "dijitTextBox",
+
+		// required: Boolean
+		//		User is required to enter data into this field.
+		required: false,
+
+		// promptMessage: String
+		//		If defined, display this hint string immediately on focus to the textbox, if empty.
+		//		Think of this like a tooltip that tells the user what to do, not an error message
+		//		that tells the user what they've done wrong.
+		//
+		//		Message disappears when user starts typing.
+		promptMessage: "",
+
+		// invalidMessage: String
+		// 		The message to display if value is invalid.
+		invalidMessage: "$_unset_$", // read from the message file if not overridden
+
+		// constraints: dijit.form.ValidationTextBox.__Constraints
+		//		user-defined object needed to pass parameters to the validator functions
+		constraints: {},
+
+		// regExp: [extension protected] String
+		//		regular expression string used to validate the input
+		//		Do not specify both regExp and regExpGen
+		regExp: ".*",
+
+		regExpGen: function(/*dijit.form.ValidationTextBox.__Constraints*/constraints){
+			// summary:
+			//		Overridable function used to generate regExp when dependent on constraints.
+			//		Do not specify both regExp and regExpGen.
+			// tags:
+			//		extension protected
+			return this.regExp;     // String
+		},
+
+		// state: [readonly] String
+		//		Shows current state (ie, validation result) of input (Normal, Warning, or Error)
+		state: "",
+
+		// tooltipPosition: String[]
+		//		See description of `dijit.Tooltip.defaultPosition` for details on this parameter.
+		tooltipPosition: [],
+
+		_setValueAttr: function(){
+			// summary:
+			//		Hook so attr('value', ...) works.
+			this.inherited(arguments);
+			this.validate(this._focused);
+		},
+
+		validator: function(/*anything*/value, /*dijit.form.ValidationTextBox.__Constraints*/constraints){
+			// summary:
+			//		Overridable function used to validate the text input against the regular expression.
+			// tags:
+			//		protected
+			return (new RegExp("^(?:" + this.regExpGen(constraints) + ")"+(this.required?"":"?")+"$")).test(value) &&
+				(!this.required || !this._isEmpty(value)) &&
+				(this._isEmpty(value) || this.parse(value, constraints) !== undefined); // Boolean
+		},
+
+		_isValidSubset: function(){
+			// summary:
+			//		Returns true if the value is either already valid or could be made valid by appending characters.
+			//		This is used for validation while the user [may be] still typing.
+			return this.textbox.value.search(this._partialre) == 0;
+		},
+
+		isValid: function(/*Boolean*/ isFocused){
+			// summary:
+			//		Tests if value is valid.
+			//		Can override with your own routine in a subclass.
+			// tags:
+			//		protected
+			return this.validator(this.textbox.value, this.constraints);
+		},
+
+		_isEmpty: function(value){
+			// summary:
+			//		Checks for whitespace
+			return /^\s*$/.test(value); // Boolean
+		},
+
+		getErrorMessage: function(/*Boolean*/ isFocused){
+			// summary:
+			//		Return an error message to show if appropriate
+			// tags:
+			//		protected
+			return this.invalidMessage; // String
+		},
+
+		getPromptMessage: function(/*Boolean*/ isFocused){
+			// summary:
+			//		Return a hint message to show when widget is first focused
+			// tags:
+			//		protected
+			return this.promptMessage; // String
+		},
+
+		_maskValidSubsetError: true,
+		validate: function(/*Boolean*/ isFocused){
+			// summary:
+			//		Called by oninit, onblur, and onkeypress.
+			// description:
+			//		Show missing or invalid messages if appropriate, and highlight textbox field.
+			// tags:
+			//		protected
+			var message = "";
+			var isValid = this.disabled || this.isValid(isFocused);
+			if(isValid){ this._maskValidSubsetError = true; }
+			var isValidSubset = !isValid && isFocused && this._isValidSubset();
+			var isEmpty = this._isEmpty(this.textbox.value);
+			this.state = (isValid || (!this._hasBeenBlurred && isEmpty) || isValidSubset) ? "" : "Error";
+			if(this.state == "Error"){ this._maskValidSubsetError = false; }
+			this._setStateClass();
+			dijit.setWaiState(this.focusNode, "invalid", isValid ? "false" : "true");
+			if(isFocused){
+				if(isEmpty){
+					message = this.getPromptMessage(true);
+				}
+				if(!message && (this.state == "Error" || (isValidSubset && !this._maskValidSubsetError))){
+					message = this.getErrorMessage(true);
+				}
+			}
+			this.displayMessage(message);
+			return isValid;
+		},
+
+		// _message: String
+		//		Currently displayed message
+		_message: "",
+
+		displayMessage: function(/*String*/ message){
+			// summary:
+			//		Overridable method to display validation errors/hints.
+			//		By default uses a tooltip.
+			// tags:
+			//		extension
+			if(this._message == message){ return; }
+			this._message = message;
+			dijit.hideTooltip(this.domNode);
+			if(message){
+				dijit.showTooltip(message, this.domNode, this.tooltipPosition);
+			}
+		},
+
+		_refreshState: function(){
+			// Overrides TextBox._refreshState()
+			this.validate(this._focused);
+			this.inherited(arguments);
+		},
+
+		//////////// INITIALIZATION METHODS ///////////////////////////////////////
+
+		constructor: function(){
+			this.constraints = {};
+		},
+
+		postMixInProperties: function(){
+			this.inherited(arguments);
+			this.constraints.locale = this.lang;
+			this.messages = dojo.i18n.getLocalization("dijit.form", "validate", this.lang);
+			if(this.invalidMessage == "$_unset_$"){ this.invalidMessage = this.messages.invalidMessage; }
+			var p = this.regExpGen(this.constraints);
+			this.regExp = p;
+			var partialre = "";
+			// parse the regexp and produce a new regexp that matches valid subsets
+			// if the regexp is .* then there's no use in matching subsets since everything is valid
+			if(p != ".*"){ this.regExp.replace(/\\.|\[\]|\[.*?[^\\]{1}\]|\{.*?\}|\(\?[=:!]|./g,
+				function (re){
+					switch(re.charAt(0)){
+						case '{':
+						case '+':
+						case '?':
+						case '*':
+						case '^':
+						case '$':
+						case '|':
+						case '(': partialre += re; break;
+						case ")": partialre += "|$)"; break;
+						 default: partialre += "(?:"+re+"|$)"; break;
+					}
+				}
+			);}
+			try{ // this is needed for now since the above regexp parsing needs more test verification
+				"".search(partialre);
+			}catch(e){ // should never be here unless the original RE is bad or the parsing is bad
+				partialre = this.regExp;
+				console.warn('RegExp error in ' + this.declaredClass + ': ' + this.regExp);
+			} // should never be here unless the original RE is bad or the parsing is bad
+			this._partialre = "^(?:" + partialre + ")$";
+		},
+
+		_setDisabledAttr: function(/*Boolean*/ value){
+			this.inherited(arguments);	// call FormValueWidget._setDisabledAttr()
+			if(this.valueNode){
+				this.valueNode.disabled = value;
+			}
+			this._refreshState();
+		},
+		
+		_setRequiredAttr: function(/*Boolean*/ value){
+			this.required = value;
+			dijit.setWaiState(this.focusNode,"required", value);
+			this._refreshState();				
+		},
+
+		postCreate: function(){
+			if(dojo.isIE){ // IE INPUT tag fontFamily has to be set directly using STYLE
+				var s = dojo.getComputedStyle(this.focusNode);
+				if(s){
+					var ff = s.fontFamily;
+					if(ff){
+						this.focusNode.style.fontFamily = ff;
+					}
+				}
+			}
+			this.inherited(arguments);
+		},
+
+		reset:function(){
+			// Overrides dijit.form.TextBox.reset() by also
+			// hiding errors about partial matches
+			this._maskValidSubsetError = true;
+			this.inherited(arguments);
+		}
+	}
+);
+
+dojo.declare(
+	"dijit.form.MappedTextBox",
+	dijit.form.ValidationTextBox,
+	{
+		// summary:
+		//		A dijit.form.ValidationTextBox subclass which provides a base class for widgets that have
+		//		a visible formatted display value, and a serializable
+		//		value in a hidden input field which is actually sent to the server.
+		// description:
+		//		The visible display may
+		//		be locale-dependent and interactive.  The value sent to the server is stored in a hidden
+		//		input field which uses the `name` attribute declared by the original widget.  That value sent
+		//		to the server is defined by the dijit.form.MappedTextBox.serialize method and is typically
+		//		locale-neutral.
+		// tags:
+		//		protected
+
+		postMixInProperties: function(){
+			this.inherited(arguments);
+			
+			// we want the name attribute to go to the hidden <input>, not the displayed <input>,
+			// so override _FormWidget.postMixInProperties() setting of nameAttrSetting
+			this.nameAttrSetting = "";
+		},
+
+		serialize: function(/*anything*/val, /*Object?*/options){
+			// summary:
+			//		Overridable function used to convert the attr('value') result to a canonical
+			//		(non-localized) string.  For example, will print dates in ISO format, and
+			//		numbers the same way as they are represented in javascript.
+			// tags:
+			//		protected extension
+			return val.toString ? val.toString() : ""; // String
+		},
+
+		toString: function(){
+			// summary:
+			//		Returns widget as a printable string using the widget's value
+			// tags:
+			//		protected
+			var val = this.filter(this.attr('value')); // call filter in case value is nonstring and filter has been customized
+			return val != null ? (typeof val == "string" ? val : this.serialize(val, this.constraints)) : ""; // String
+		},
+
+		validate: function(){
+			// Overrides `dijit.form.TextBox.validate`
+			this.valueNode.value = this.toString();
+			return this.inherited(arguments);
+		},
+
+		buildRendering: function(){
+			// Overrides `dijit._Templated.buildRendering`
+
+			this.inherited(arguments);
+
+			// Create a hidden <input> node with the serialized value used for submit
+			// (as opposed to the displayed value)
+			this.valueNode = dojo.create("input", {
+				style: { display: "none" },
+				type: this.type,
+				name: this.name
+			}, this.textbox, "after");
+		},
+
+		_setDisabledAttr: function(/*Boolean*/ value){
+			this.inherited(arguments);
+			dojo.attr(this.valueNode, 'disabled', value);
+		},
+
+		reset:function(){
+			// Overrides `dijit.form.ValidationTextBox.reset` to
+			// reset the hidden textbox value to ''
+			this.valueNode.value = '';
+			this.inherited(arguments);
+		}
+	}
+);
+
+/*=====
+	dijit.form.RangeBoundTextBox.__Constraints = function(){
+		// min: Number
+		//		Minimum signed value.  Default is -Infinity
+		// max: Number
+		//		Maximum signed value.  Default is +Infinity
+		this.min = min;
+		this.max = max;
+	}
+=====*/
+
+dojo.declare(
+	"dijit.form.RangeBoundTextBox",
+	dijit.form.MappedTextBox,
+	{
+		// summary:
+		//		Base class for textbox form widgets which defines a range of valid values.
+
+		// rangeMessage: String
+		//		The message to display if value is out-of-range
+		rangeMessage: "",
+
+		/*=====
+		// constraints: dijit.form.RangeBoundTextBox.__Constraints
+		constraints: {},
+		======*/
+
+		rangeCheck: function(/*Number*/ primitive, /*dijit.form.RangeBoundTextBox.__Constraints*/ constraints){
+			// summary:
+			//		Overridable function used to validate the range of the numeric input value.
+			// tags:
+			//		protected
+			var isMin = "min" in constraints;
+			var isMax = "max" in constraints;
+			if(isMin || isMax){
+				return (!isMin || this.compare(primitive,constraints.min) >= 0) &&
+					(!isMax || this.compare(primitive,constraints.max) <= 0);
+			}
+			return true; // Boolean
+		},
+
+		isInRange: function(/*Boolean*/ isFocused){
+			// summary:
+			//		Tests if the value is in the min/max range specified in constraints
+			// tags:
+			//		protected
+			return this.rangeCheck(this.attr('value'), this.constraints);
+		},
+
+		_isDefinitelyOutOfRange: function(){
+			// summary:
+			//		Returns true if the value is out of range and will remain
+			//		out of range even if the user types more characters
+			var val = this.attr('value');
+			var isTooLittle = false;
+			var isTooMuch = false;
+			if("min" in this.constraints){
+				var min = this.constraints.min;
+				val = this.compare(val, ((typeof min == "number") && min >= 0 && val !=0)? 0 : min);
+				isTooLittle = (typeof val == "number") && val < 0;
+			}
+			if("max" in this.constraints){
+				var max = this.constraints.max;
+				val = this.compare(val, ((typeof max != "number") || max > 0)? max : 0);
+				isTooMuch = (typeof val == "number") && val > 0;
+			}
+			return isTooLittle || isTooMuch;
+		},
+
+		_isValidSubset: function(){
+			// summary:
+			//		Overrides `dijit.form.ValidationTextBox._isValidSubset`.
+			//		Returns true if the input is syntactically valid, and either within
+			//		range or could be made in range by more typing.
+			return this.inherited(arguments) && !this._isDefinitelyOutOfRange();
+		},
+
+		isValid: function(/*Boolean*/ isFocused){
+			// Overrides dijit.form.ValidationTextBox.isValid to check that the value is also in range.
+			return this.inherited(arguments) &&
+				((this._isEmpty(this.textbox.value) && !this.required) || this.isInRange(isFocused)); // Boolean
+		},
+
+		getErrorMessage: function(/*Boolean*/ isFocused){
+			// Overrides dijit.form.ValidationTextBox.getErrorMessage to print "out of range" message if appropriate
+			if(dijit.form.RangeBoundTextBox.superclass.isValid.call(this, false) && !this.isInRange(isFocused)){ return this.rangeMessage; } // String
+			return this.inherited(arguments);
+		},
+
+		postMixInProperties: function(){
+			this.inherited(arguments);
+			if(!this.rangeMessage){
+				this.messages = dojo.i18n.getLocalization("dijit.form", "validate", this.lang);
+				this.rangeMessage = this.messages.rangeMessage;
+			}
+		},
+
+		postCreate: function(){
+			this.inherited(arguments);
+			if(this.constraints.min !== undefined){
+				dijit.setWaiState(this.focusNode, "valuemin", this.constraints.min);
+			}
+			if(this.constraints.max !== undefined){
+				dijit.setWaiState(this.focusNode, "valuemax", this.constraints.max);
+			}
+		},
+		
+		_setValueAttr: function(/*Number*/ value, /*Boolean?*/ priorityChange){
+			// summary:
+			//		Hook so attr('value', ...) works.
+
+			dijit.setWaiState(this.focusNode, "valuenow", value);
+			this.inherited(arguments);
+		}
+	}
+);
+
+}
+
+if(!dojo._hasResource["dojo.number"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.number"] = true;
+dojo.provide("dojo.number");
+
+
+
+
+
+
+
+/*=====
+dojo.number = {
+	// summary: localized formatting and parsing routines for Number
+}
+
+dojo.number.__FormatOptions = function(){
+	//	pattern: String?
+	//		override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
+	//		with this string
+	//	type: String?
+	//		choose a format type based on the locale from the following:
+	//		decimal, scientific, percent, currency. decimal by default.
+	//	places: Number?
+	//		fixed number of decimal places to show.  This overrides any
+	//		information in the provided pattern.
+	//	round: Number?
+	//		5 rounds to nearest .5; 0 rounds to nearest whole (default). -1
+	//		means do not round.
+	//	currency: String?
+	//		an [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code, a three letter sequence like "USD"
+	//	symbol: String?
+	//		localized currency symbol
+	//	locale: String?
+	//		override the locale used to determine formatting rules
+	this.pattern = pattern;
+	this.type = type;
+	this.places = places;
+	this.round = round;
+	this.currency = currency;
+	this.symbol = symbol;
+	this.locale = locale;
+}
+=====*/
+
+dojo.number.format = function(/*Number*/value, /*dojo.number.__FormatOptions?*/options){
+	// summary:
+	//		Format a Number as a String, using locale-specific settings
+	// description:
+	//		Create a string from a Number using a known localized pattern.
+	//		Formatting patterns appropriate to the locale are chosen from the
+	//		[CLDR](http://unicode.org/cldr) as well as the appropriate symbols and
+	//		delimiters.  See <http://www.unicode.org/reports/tr35/#Number_Elements>
+	//		If value is Infinity, -Infinity, or is not a valid JavaScript number, return null.
+	// value:
+	//		the number to be formatted
+
+	options = dojo.mixin({}, options || {});
+	var locale = dojo.i18n.normalizeLocale(options.locale);
+	var bundle = dojo.i18n.getLocalization("dojo.cldr", "number", locale);
+	options.customs = bundle;
+	var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"];
+	if(isNaN(value) || Math.abs(value) == Infinity){ return null; } // null
+	return dojo.number._applyPattern(value, pattern, options); // String
+};
+
+//dojo.number._numberPatternRE = /(?:[#0]*,?)*[#0](?:\.0*#*)?/; // not precise, but good enough
+dojo.number._numberPatternRE = /[#0,]*[#0](?:\.0*#*)?/; // not precise, but good enough
+
+dojo.number._applyPattern = function(/*Number*/value, /*String*/pattern, /*dojo.number.__FormatOptions?*/options){
+	// summary:
+	//		Apply pattern to format value as a string using options. Gives no
+	//		consideration to local customs.
+	// value:
+	//		the number to be formatted.
+	// pattern:
+	//		a pattern string as described by
+	//		[unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
+	// options: dojo.number.__FormatOptions?
+	//		_applyPattern is usually called via `dojo.number.format()` which
+	//		populates an extra property in the options parameter, "customs".
+	//		The customs object specifies group and decimal parameters if set.
+
+	//TODO: support escapes
+	options = options || {};
+	var group = options.customs.group;
+	var decimal = options.customs.decimal;
+
+	var patternList = pattern.split(';');
+	var positivePattern = patternList[0];
+	pattern = patternList[(value < 0) ? 1 : 0] || ("-" + positivePattern);
+
+	//TODO: only test against unescaped
+	if(pattern.indexOf('%') != -1){
+		value *= 100;
+	}else if(pattern.indexOf('\u2030') != -1){
+		value *= 1000; // per mille
+	}else if(pattern.indexOf('\u00a4') != -1){
+		group = options.customs.currencyGroup || group;//mixins instead?
+		decimal = options.customs.currencyDecimal || decimal;// Should these be mixins instead?
+		pattern = pattern.replace(/\u00a4{1,3}/, function(match){
+			var prop = ["symbol", "currency", "displayName"][match.length-1];
+			return options[prop] || options.currency || "";
+		});
+	}else if(pattern.indexOf('E') != -1){
+		throw new Error("exponential notation not supported");
+	}
+	
+	//TODO: support @ sig figs?
+	var numberPatternRE = dojo.number._numberPatternRE;
+	var numberPattern = positivePattern.match(numberPatternRE);
+	if(!numberPattern){
+		throw new Error("unable to find a number expression in pattern: "+pattern);
+	}
+	if(options.fractional === false){ options.places = 0; }
+	return pattern.replace(numberPatternRE,
+		dojo.number._formatAbsolute(value, numberPattern[0], {decimal: decimal, group: group, places: options.places, round: options.round}));
+}
+
+dojo.number.round = function(/*Number*/value, /*Number?*/places, /*Number?*/increment){
+	//	summary:
+	//		Rounds to the nearest value with the given number of decimal places, away from zero
+	//	description:
+	//		Rounds to the nearest value with the given number of decimal places, away from zero if equal.
+	//		Similar to Number.toFixed(), but compensates for browser quirks. Rounding can be done by
+	//		fractional increments also, such as the nearest quarter.
+	//		NOTE: Subject to floating point errors.  See dojox.math.round for experimental workaround.
+	//	value:
+	//		The number to round
+	//	places:
+	//		The number of decimal places where rounding takes place.  Defaults to 0 for whole rounding.
+	//		Must be non-negative.
+	//	increment:
+	//		Rounds next place to nearest value of increment/10.  10 by default.
+	//	example:
+	//		>>> dojo.number.round(-0.5)
+	//		-1
+	//		>>> dojo.number.round(162.295, 2)
+	//		162.29  // note floating point error.  Should be 162.3
+	//		>>> dojo.number.round(10.71, 0, 2.5)
+	//		10.75
+	var factor = 10 / (increment || 10);
+	return (factor * +value).toFixed(places) / factor; // Number
+}
+
+if((0.9).toFixed() == 0){
+	// (isIE) toFixed() bug workaround: Rounding fails on IE when most significant digit
+	// is just after the rounding place and is >=5
+	(function(){
+		var round = dojo.number.round;
+		dojo.number.round = function(v, p, m){
+			var d = Math.pow(10, -p || 0), a = Math.abs(v);
+			if(!v || a >= d || a * Math.pow(10, p + 1) < 5){
+				d = 0;
+			}
+			return round(v, p, m) + (v > 0 ? d : -d);
+		}
+	})();
+}
+
+/*=====
+dojo.number.__FormatAbsoluteOptions = function(){
+	//	decimal: String?
+	//		the decimal separator
+	//	group: String?
+	//		the group separator
+	//	places: Integer?|String?
+	//		number of decimal places.  the range "n,m" will format to m places.
+	//	round: Number?
+	//		5 rounds to nearest .5; 0 rounds to nearest whole (default). -1
+	//		means don't round.
+	this.decimal = decimal;
+	this.group = group;
+	this.places = places;
+	this.round = round;
+}
+=====*/
+
+dojo.number._formatAbsolute = function(/*Number*/value, /*String*/pattern, /*dojo.number.__FormatAbsoluteOptions?*/options){
+	// summary: 
+	//		Apply numeric pattern to absolute value using options. Gives no
+	//		consideration to local customs.
+	// value:
+	//		the number to be formatted, ignores sign
+	// pattern:
+	//		the number portion of a pattern (e.g. `#,##0.00`)
+	options = options || {};
+	if(options.places === true){options.places=0;}
+	if(options.places === Infinity){options.places=6;} // avoid a loop; pick a limit
+
+	var patternParts = pattern.split(".");
+	var maxPlaces = (options.places >= 0) ? options.places : (patternParts[1] && patternParts[1].length) || 0;
+	if(!(options.round < 0)){
+		value = dojo.number.round(value, maxPlaces, options.round);
+	}
+
+	var valueParts = String(Math.abs(value)).split(".");
+	var fractional = valueParts[1] || "";
+	if(options.places){
+		var comma = dojo.isString(options.places) && options.places.indexOf(",");
+		if(comma){
+			options.places = options.places.substring(comma+1);
+		}
+		valueParts[1] = dojo.string.pad(fractional.substr(0, options.places), options.places, '0', true);
+	}else if(patternParts[1] && options.places !== 0){
+		// Pad fractional with trailing zeros
+		var pad = patternParts[1].lastIndexOf("0") + 1;
+		if(pad > fractional.length){
+			valueParts[1] = dojo.string.pad(fractional, pad, '0', true);
+		}
+
+		// Truncate fractional
+		var places = patternParts[1].length;
+		if(places < fractional.length){
+			valueParts[1] = fractional.substr(0, places);
+		}
+	}else{
+		if(valueParts[1]){ valueParts.pop(); }
+	}
+
+	// Pad whole with leading zeros
+	var patternDigits = patternParts[0].replace(',', '');
+	pad = patternDigits.indexOf("0");
+	if(pad != -1){
+		pad = patternDigits.length - pad;
+		if(pad > valueParts[0].length){
+			valueParts[0] = dojo.string.pad(valueParts[0], pad);
+		}
+
+		// Truncate whole
+		if(patternDigits.indexOf("#") == -1){
+			valueParts[0] = valueParts[0].substr(valueParts[0].length - pad);
+		}
+	}
+
+	// Add group separators
+	var index = patternParts[0].lastIndexOf(',');
+	var groupSize, groupSize2;
+	if(index != -1){
+		groupSize = patternParts[0].length - index - 1;
+		var remainder = patternParts[0].substr(0, index);
+		index = remainder.lastIndexOf(',');
+		if(index != -1){
+			groupSize2 = remainder.length - index - 1;
+		}
+	}
+	var pieces = [];
+	for(var whole = valueParts[0]; whole;){
+		var off = whole.length - groupSize;
+		pieces.push((off > 0) ? whole.substr(off) : whole);
+		whole = (off > 0) ? whole.slice(0, off) : "";
+		if(groupSize2){
+			groupSize = groupSize2;
+			delete groupSize2;
+		}
+	}
+	valueParts[0] = pieces.reverse().join(options.group || ",");
+
+	return valueParts.join(options.decimal || ".");
+};
+
+/*=====
+dojo.number.__RegexpOptions = function(){
+	//	pattern: String?
+	//		override pattern with this string.  Default is provided based on
+	//		locale.
+	//	type: String?
+	//		choose a format type based on the locale from the following:
+	//		decimal, scientific, percent, currency. decimal by default.
+	//	locale: String?
+	//		override the locale used to determine formatting rules
+	//	strict: Boolean?
+	//		strict parsing, false by default
+	//	places: Number|String?
+	//		number of decimal places to accept: Infinity, a positive number, or
+	//		a range "n,m".  Defined by pattern or Infinity if pattern not provided.
+	this.pattern = pattern;
+	this.type = type;
+	this.locale = locale;
+	this.strict = strict;
+	this.places = places;
+}
+=====*/
+dojo.number.regexp = function(/*dojo.number.__RegexpOptions?*/options){
+	//	summary:
+	//		Builds the regular needed to parse a number
+	//	description:
+	//		Returns regular expression with positive and negative match, group
+	//		and decimal separators
+	return dojo.number._parseInfo(options).regexp; // String
+}
+
+dojo.number._parseInfo = function(/*Object?*/options){
+	options = options || {};
+	var locale = dojo.i18n.normalizeLocale(options.locale);
+	var bundle = dojo.i18n.getLocalization("dojo.cldr", "number", locale);
+	var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"];
+//TODO: memoize?
+	var group = bundle.group;
+	var decimal = bundle.decimal;
+	var factor = 1;
+
+	if(pattern.indexOf('%') != -1){
+		factor /= 100;
+	}else if(pattern.indexOf('\u2030') != -1){
+		factor /= 1000; // per mille
+	}else{
+		var isCurrency = pattern.indexOf('\u00a4') != -1;
+		if(isCurrency){
+			group = bundle.currencyGroup || group;
+			decimal = bundle.currencyDecimal || decimal;
+		}
+	}
+
+	//TODO: handle quoted escapes
+	var patternList = pattern.split(';');
+	if(patternList.length == 1){
+		patternList.push("-" + patternList[0]);
+	}
+
+	var re = dojo.regexp.buildGroupRE(patternList, function(pattern){
+		pattern = "(?:"+dojo.regexp.escapeString(pattern, '.')+")";
+		return pattern.replace(dojo.number._numberPatternRE, function(format){
+			var flags = {
+				signed: false,
+				separator: options.strict ? group : [group,""],
+				fractional: options.fractional,
+				decimal: decimal,
+				exponent: false};
+			var parts = format.split('.');
+			var places = options.places;
+			if(parts.length == 1 || places === 0){flags.fractional = false;}
+			else{
+				if(places === undefined){ places = options.pattern ? parts[1].lastIndexOf('0')+1 : Infinity; }
+				if(places && options.fractional == undefined){flags.fractional = true;} // required fractional, unless otherwise specified
+				if(!options.places && (places < parts[1].length)){ places += "," + parts[1].length; }
+				flags.places = places;
+			}
+			var groups = parts[0].split(',');
+			if(groups.length>1){
+				flags.groupSize = groups.pop().length;
+				if(groups.length>1){
+					flags.groupSize2 = groups.pop().length;
+				}
+			}
+			return "("+dojo.number._realNumberRegexp(flags)+")";
+		});
+	}, true);
+
+	if(isCurrency){
+		// substitute the currency symbol for the placeholder in the pattern
+		re = re.replace(/([\s\xa0]*)(\u00a4{1,3})([\s\xa0]*)/g, function(match, before, target, after){
+			var prop = ["symbol", "currency", "displayName"][target.length-1];
+			var symbol = dojo.regexp.escapeString(options[prop] || options.currency || "");
+			before = before ? "[\\s\\xa0]" : "";
+			after = after ? "[\\s\\xa0]" : "";
+			if(!options.strict){
+				if(before){before += "*";}
+				if(after){after += "*";}
+				return "(?:"+before+symbol+after+")?";
+			}
+			return before+symbol+after;
+		});
+	}
+
+//TODO: substitute localized sign/percent/permille/etc.?
+
+	// normalize whitespace and return
+	return {regexp: re.replace(/[\xa0 ]/g, "[\\s\\xa0]"), group: group, decimal: decimal, factor: factor}; // Object
+}
+
+/*=====
+dojo.number.__ParseOptions = function(){
+	//	pattern: String
+	//		override pattern with this string.  Default is provided based on
+	//		locale.
+	//	type: String?
+	//		choose a format type based on the locale from the following:
+	//		decimal, scientific, percent, currency. decimal by default.
+	//	locale: String
+	//		override the locale used to determine formatting rules
+	//	strict: Boolean?
+	//		strict parsing, false by default
+	//	currency: Object
+	//		object with currency information
+	this.pattern = pattern;
+	this.type = type;
+	this.locale = locale;
+	this.strict = strict;
+	this.currency = currency;
+}
+=====*/
+dojo.number.parse = function(/*String*/expression, /*dojo.number.__ParseOptions?*/options){
+	// summary:
+	//		Convert a properly formatted string to a primitive Number, using
+	//		locale-specific settings.
+	// description:
+	//		Create a Number from a string using a known localized pattern.
+	//		Formatting patterns are chosen appropriate to the locale
+	//		and follow the syntax described by
+	//		[unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
+	// expression:
+	//		A string representation of a Number
+	var info = dojo.number._parseInfo(options);
+	var results = (new RegExp("^"+info.regexp+"$")).exec(expression);
+	if(!results){
+		return NaN; //NaN
+	}
+	var absoluteMatch = results[1]; // match for the positive expression
+	if(!results[1]){
+		if(!results[2]){
+			return NaN; //NaN
+		}
+		// matched the negative pattern
+		absoluteMatch =results[2];
+		info.factor *= -1;
+	}
+
+	// Transform it to something Javascript can parse as a number.  Normalize
+	// decimal point and strip out group separators or alternate forms of whitespace
+	absoluteMatch = absoluteMatch.
+		replace(new RegExp("["+info.group + "\\s\\xa0"+"]", "g"), "").
+		replace(info.decimal, ".");
+	// Adjust for negative sign, percent, etc. as necessary
+	return absoluteMatch * info.factor; //Number
+};
+
+/*=====
+dojo.number.__RealNumberRegexpFlags = function(){
+	//	places: Number?
+	//		The integer number of decimal places or a range given as "n,m".  If
+	//		not given, the decimal part is optional and the number of places is
+	//		unlimited.
+	//	decimal: String?
+	//		A string for the character used as the decimal point.  Default
+	//		is ".".
+	//	fractional: Boolean|Array?
+	//		Whether decimal places are allowed.  Can be true, false, or [true,
+	//		false].  Default is [true, false]
+	//	exponent: Boolean|Array?
+	//		Express in exponential notation.  Can be true, false, or [true,
+	//		false]. Default is [true, false], (i.e. will match if the
+	//		exponential part is present are not).
+	//	eSigned: Boolean|Array?
+	//		The leading plus-or-minus sign on the exponent.  Can be true,
+	//		false, or [true, false].  Default is [true, false], (i.e. will
+	//		match if it is signed or unsigned).  flags in regexp.integer can be
+	//		applied.
+	this.places = places;
+	this.decimal = decimal;
+	this.fractional = fractional;
+	this.exponent = exponent;
+	this.eSigned = eSigned;
+}
+=====*/
+
+dojo.number._realNumberRegexp = function(/*dojo.number.__RealNumberRegexpFlags?*/flags){
+	// summary:
+	//		Builds a regular expression to match a real number in exponential
+	//		notation
+
+	// assign default values to missing paramters
+	flags = flags || {};
+	//TODO: use mixin instead?
+	if(!("places" in flags)){ flags.places = Infinity; }
+	if(typeof flags.decimal != "string"){ flags.decimal = "."; }
+	if(!("fractional" in flags) || /^0/.test(flags.places)){ flags.fractional = [true, false]; }
+	if(!("exponent" in flags)){ flags.exponent = [true, false]; }
+	if(!("eSigned" in flags)){ flags.eSigned = [true, false]; }
+
+	// integer RE
+	var integerRE = dojo.number._integerRegexp(flags);
+
+	// decimal RE
+	var decimalRE = dojo.regexp.buildGroupRE(flags.fractional,
+		function(q){
+			var re = "";
+			if(q && (flags.places!==0)){
+				re = "\\" + flags.decimal;
+				if(flags.places == Infinity){ 
+					re = "(?:" + re + "\\d+)?"; 
+				}else{
+					re += "\\d{" + flags.places + "}"; 
+				}
+			}
+			return re;
+		},
+		true
+	);
+
+	// exponent RE
+	var exponentRE = dojo.regexp.buildGroupRE(flags.exponent,
+		function(q){ 
+			if(q){ return "([eE]" + dojo.number._integerRegexp({ signed: flags.eSigned}) + ")"; }
+			return ""; 
+		}
+	);
+
+	// real number RE
+	var realRE = integerRE + decimalRE;
+	// allow for decimals without integers, e.g. .25
+	if(decimalRE){realRE = "(?:(?:"+ realRE + ")|(?:" + decimalRE + "))";}
+	return realRE + exponentRE; // String
+};
+
+/*=====
+dojo.number.__IntegerRegexpFlags = function(){
+	//	signed: Boolean?
+	//		The leading plus-or-minus sign. Can be true, false, or `[true,false]`.
+	//		Default is `[true, false]`, (i.e. will match if it is signed
+	//		or unsigned).
+	//	separator: String?
+	//		The character used as the thousands separator. Default is no
+	//		separator. For more than one symbol use an array, e.g. `[",", ""]`,
+	//		makes ',' optional.
+	//	groupSize: Number?
+	//		group size between separators
+	//	groupSize2: Number?
+	//		second grouping, where separators 2..n have a different interval than the first separator (for India)
+	this.signed = signed;
+	this.separator = separator;
+	this.groupSize = groupSize;
+	this.groupSize2 = groupSize2;
+}
+=====*/
+
+dojo.number._integerRegexp = function(/*dojo.number.__IntegerRegexpFlags?*/flags){
+	// summary: 
+	//		Builds a regular expression that matches an integer
+
+	// assign default values to missing paramters
+	flags = flags || {};
+	if(!("signed" in flags)){ flags.signed = [true, false]; }
+	if(!("separator" in flags)){
+		flags.separator = "";
+	}else if(!("groupSize" in flags)){
+		flags.groupSize = 3;
+	}
+	// build sign RE
+	var signRE = dojo.regexp.buildGroupRE(flags.signed,
+		function(q){ return q ? "[-+]" : ""; },
+		true
+	);
+
+	// number RE
+	var numberRE = dojo.regexp.buildGroupRE(flags.separator,
+		function(sep){
+			if(!sep){
+				return "(?:\\d+)";
+			}
+
+			sep = dojo.regexp.escapeString(sep);
+			if(sep == " "){ sep = "\\s"; }
+			else if(sep == "\xa0"){ sep = "\\s\\xa0"; }
+
+			var grp = flags.groupSize, grp2 = flags.groupSize2;
+			//TODO: should we continue to enforce that numbers with separators begin with 1-9?  See #6933
+			if(grp2){
+				var grp2RE = "(?:0|[1-9]\\d{0," + (grp2-1) + "}(?:[" + sep + "]\\d{" + grp2 + "})*[" + sep + "]\\d{" + grp + "})";
+				return ((grp-grp2) > 0) ? "(?:" + grp2RE + "|(?:0|[1-9]\\d{0," + (grp-1) + "}))" : grp2RE;
+			}
+			return "(?:0|[1-9]\\d{0," + (grp-1) + "}(?:[" + sep + "]\\d{" + grp + "})*)";
+		},
+		true
+	);
+
+	// integer RE
+	return signRE + numberRE; // String
+}
+
+}
+
+if(!dojo._hasResource["dijit.form.NumberTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.NumberTextBox"] = true;
+dojo.provide("dijit.form.NumberTextBox");
+
+
+
+
+/*=====
+dojo.declare(
+	"dijit.form.NumberTextBox.__Constraints",
+	[dijit.form.RangeBoundTextBox.__Constraints, dojo.number.__FormatOptions, dojo.number.__ParseOptions]
+);
+=====*/
+
+dojo.declare("dijit.form.NumberTextBoxMixin",
+	null,
+	{
+		// summary:
+		//		A mixin for all number textboxes
+		// tags:
+		//		protected
+
+		// Override ValidationTextBox.regExpGen().... we use a reg-ex generating function rather
+		// than a straight regexp to deal with locale (plus formatting options too?)
+		regExpGen: dojo.number.regexp,
+
+		/*=====
+		// constraints: dijit.form.NumberTextBox.__Constraints
+		//		Minimum/maximum allowed values.
+		constraints: {},
+		======*/
+
+		// value: Number
+		//		The value of this NumberTextBox as a javascript Number (ie, not a String).
+		//		If the displayed value is blank, the value is NaN, and if the user types in
+		//		an gibberish value (like "hello world"), the value is undefined
+		//		(i.e. attr('value') returns undefined).
+		//
+		//		Symetrically, attr('value', NaN) will clear the displayed value,
+		//		whereas attr('value', undefined) will have no effect.
+		value: NaN,
+
+		// editOptions: [protected] Object
+		//		Properties to mix into constraints when the value is being edited.
+		//		This is here because we edit the number in the format "12345", which is
+		//		different than the display value (ex: "12,345")
+		editOptions: { pattern: '#.######' },
+
+		/*=====
+		_formatter: function(value, options){
+			// summary:
+			//		_formatter() is called by format().   It's the base routine for formatting a number,
+			//		as a string, for example converting 12345 into "12,345".
+			// value: Number
+			//		The number to be converted into a string.
+			// options: dojo.number.__FormatOptions?
+			//		Formatting options
+			// tags:
+			//		protected extension
+
+			return "12345";		// String
+		},
+		 =====*/
+		_formatter: dojo.number.format,
+
+		postMixInProperties: function(){
+			if(typeof this.constraints.max != "number"){
+				this.constraints.max = 9e+15;
+			}
+			this.inherited(arguments);
+		},
+
+		_onFocus: function(){
+			if(this.disabled){ return; }
+			var val = this.attr('value');
+			if(typeof val == "number" && !isNaN(val)){
+				var formattedValue = this.format(val, this.constraints);
+				if(formattedValue !== undefined){
+					this.textbox.value = formattedValue;
+				}
+			}
+			this.inherited(arguments);
+		},
+
+		format: function(/*Number*/ value, /*dojo.number.__FormatOptions*/ constraints){
+			// summary:
+			//		Formats the value as a Number, according to constraints.
+			// tags:
+			//		protected
+
+			if(typeof value != "number") { return String(value) }
+			if(isNaN(value)){ return ""; }
+			if(("rangeCheck" in this) && !this.rangeCheck(value, constraints)){ return String(value) }
+			if(this.editOptions && this._focused){
+				constraints = dojo.mixin(dojo.mixin({}, this.editOptions), constraints);
+			}
+			return this._formatter(value, constraints);
+		},
+
+		/*=====
+		parse: function(value, constraints){
+			// summary:
+			//		Parses the string value as a Number, according to constraints.
+			// value: String
+			//		String representing a number
+			// constraints: dojo.number.__ParseOptions
+			//		Formatting options
+			// tags:
+			//		protected
+
+			return 123.45;		// Number
+		},
+		=====*/
+		parse: dojo.number.parse,
+
+		_getDisplayedValueAttr: function(){
+			var v = this.inherited(arguments); 
+			return isNaN(v) ? this.textbox.value : v;
+		},
+
+		filter: function(/*Number*/ value){
+			// summary:
+			//		This is called with both the display value (string), and the actual value (a number).
+			//		When called with the actual value it does corrections so that '' etc. are represented as NaN.
+			//		Otherwise it dispatches to the superclass's filter() method.
+			//
+			//		See `dijit.form.TextBox.filter` for more details.
+			return (value === null || value === '' || value === undefined) ? NaN : this.inherited(arguments); // attr('value', null||''||undefined) should fire onChange(NaN)
+		},
+
+		serialize: function(/*Number*/ value, /*Object?*/options){
+			// summary:
+			//		Convert value (a Number) into a canonical string (ie, how the number literal is written in javascript/java/C/etc.)
+			// tags:
+			//		protected
+			return (typeof value != "number" || isNaN(value))? '' : this.inherited(arguments);
+		},
+
+		_setValueAttr: function(/*Number*/ value, /*Boolean?*/ priorityChange, /*String?*/formattedValue){
+			// summary:
+			//		Hook so attr('value', ...) works.
+			if(value !== undefined && formattedValue === undefined){
+				if(typeof value == "number"){
+					if(isNaN(value)){ formattedValue = '' }
+					else if(("rangeCheck" in this) && !this.rangeCheck(value, this.constraints)){
+						formattedValue = String(value);
+					}
+				}else if(!value){ // 0 processed in if branch above, ''|null|undefined flow thru here
+					formattedValue = '';
+					value = NaN;
+				}else{ // non-numeric values
+					formattedValue = String(value);
+					value = undefined;
+				}
+			}
+			this.inherited(arguments, [value, priorityChange, formattedValue]);
+		},
+
+
+		_getValueAttr: function(){
+			// summary:
+			//		Hook so attr('value') works.
+			//		Returns Number, NaN for '', or undefined for unparsable text
+			var v = this.inherited(arguments); // returns Number for all values accepted by parse() or NaN for all other displayed values
+
+			// If the displayed value of the textbox is gibberish (ex: "hello world"), this.inherited() above
+			// returns NaN; this if() branch converts the return value to undefined.
+			// Returning undefined prevents user text from being overwritten when doing _setValueAttr(_getValueAttr()).
+			// A blank displayed value is still returned as NaN.
+			if(isNaN(v) && this.textbox.value !== ''){ // if displayed value other than ''
+				var n = Number(this.textbox.value); // check for exponential notation that parse() rejected (erroneously?)
+				return (String(n)===this.textbox.value)? n : undefined; // return exponential Number or undefined for random text
+			}else{ return v } // Number or NaN for ''
+		}
+	}
+);
+
+dojo.declare("dijit.form.NumberTextBox",
+	[dijit.form.RangeBoundTextBox,dijit.form.NumberTextBoxMixin],
+	{
+		// summary:
+		//		A validating, serializable, range-bound text box.
+	}
+);
+
+}
+
+if(!dojo._hasResource["dijit.form._DateTimeTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form._DateTimeTextBox"] = true;
+dojo.provide("dijit.form._DateTimeTextBox");
+
+
+
+
+
+
+/*=====
+dojo.declare(
+	"dijit.form._DateTimeTextBox.__Constraints",
+	[dijit.form.RangeBoundTextBox.__Constraints, dojo.date.locale.__FormatOptions]
+);
+=====*/
+
+dojo.declare(
+	"dijit.form._DateTimeTextBox",
+	dijit.form.RangeBoundTextBox,
+	{
+		// summary:
+		//		Base class for validating, serializable, range-bound date or time text box.
+
+		/*=====
+		// constraints: dijit.form._DateTimeTextBox.__Constraints
+		//		Starting / ending dates or times allowed
+		constraints: {},
+		======*/
+
+		// Override ValidationTextBox.regExpGen().... we use a reg-ex generating function rather
+		// than a straight regexp to deal with locale  (plus formatting options too?)
+		regExpGen: dojo.date.locale.regexp,
+
+		// Override _FormWidget.compare() to work for dates/times
+		compare: dojo.date.compare,
+
+		format: function(/*Date*/ value, /*dojo.date.locale.__FormatOptions*/ constraints){
+			// summary:
+			//		Formats the value as a Date, according to specified locale (second argument)
+			// tags:
+			//		protected
+			if(!value){ return ''; }
+			return dojo.date.locale.format(value, constraints);
+		},
+
+		parse: function(/*String*/ value, /*dojo.date.locale.__FormatOptions*/ constraints){
+			// summary:
+			//		Parses as string as a Date, according to constraints
+			// tags:
+			//		protected
+
+			return dojo.date.locale.parse(value, constraints) || (this._isEmpty(value)? null : undefined);	 // Date
+		},
+
+		// Overrides ValidationTextBox.serialize() to serialize a date in canonical ISO format.
+		serialize: dojo.date.stamp.toISOString,
+
+		//	value: Date
+		//		The value of this widget as a JavaScript Date object.  Use attr("value") / attr("value", val) to manipulate.
+		//		When passed to the parser in markup, must be specified according to `dojo.date.stamp.fromISOString`
+		value: new Date(""),	// value.toString()="NaN"
+		_blankValue: null,    // used by filter() when the textbox is blank
+
+		//	popupClass: [protected extension] String
+		//		Name of the popup widget class used to select a date/time.
+		//		Subclasses should specify this.
+		popupClass: "", // default is no popup = text only
+
+
+		// _selector: [protected extension] String
+		//		Specifies constraints.selector passed to dojo.date functions, should be either
+		//		"date" or "time".
+		//		Subclass must specify this.
+		_selector: "",
+
+		postMixInProperties: function(){
+			//dijit.form.RangeBoundTextBox.prototype.postMixInProperties.apply(this, arguments);
+			this.inherited(arguments);
+			if(!this.value || this.value.toString() == dijit.form._DateTimeTextBox.prototype.value.toString()){
+				this.value = null;
+			}
+			var constraints = this.constraints;
+			constraints.selector = this._selector;
+			constraints.fullYear = true; // see #5465 - always format with 4-digit years
+			var fromISO = dojo.date.stamp.fromISOString;
+			if(typeof constraints.min == "string"){ constraints.min = fromISO(constraints.min); }
+ 			if(typeof constraints.max == "string"){ constraints.max = fromISO(constraints.max); }
+		},
+		
+		_onFocus: function(/*Event*/ evt){
+			// summary:
+			//		open the TimePicker popup
+			this._open();
+		},
+
+		_setValueAttr: function(/*Date*/ value, /*Boolean?*/ priorityChange, /*String?*/ formattedValue){
+			// summary:
+			//		Sets the date on this textbox.  Note that `value` must be a Javascript Date object.
+			this.inherited(arguments);
+			if(this._picker){
+				// #3948: fix blank date on popup only
+				if(!value){value=new Date();}
+				this._picker.attr('value', value);
+			}
+		},
+
+		_open: function(){
+			// summary:
+			//		opens the TimePicker, and sets the onValueSelected value
+
+			if(this.disabled || this.readOnly || !this.popupClass){return;}
+
+			var textBox = this;
+
+			if(!this._picker){
+				var PopupProto=dojo.getObject(this.popupClass, false);
+				this._picker = new PopupProto({
+					onValueSelected: function(value){
+						if(textBox._tabbingAway){
+							delete textBox._tabbingAway;
+						}else{
+							textBox.focus(); // focus the textbox before the popup closes to avoid reopening the popup
+						}
+						setTimeout(dojo.hitch(textBox, "_close"), 1); // allow focus time to take
+
+						// this will cause InlineEditBox and other handlers to do stuff so make sure it's last
+						dijit.form._DateTimeTextBox.superclass._setValueAttr.call(textBox, value, true);
+					},
+					lang: textBox.lang,
+					constraints: textBox.constraints,
+					isDisabledDate: function(/*Date*/ date){
+						// summary:
+						// 	disables dates outside of the min/max of the _DateTimeTextBox
+						var compare = dojo.date.compare;
+						var constraints = textBox.constraints;
+						return constraints && (constraints.min && (compare(constraints.min, date, "date") > 0) || 
+							(constraints.max && compare(constraints.max, date, "date") < 0));
+					}
+				});
+				this._picker.attr('value', this.attr('value') || new Date());
+			}
+			if(!this._opened){
+				dijit.popup.open({
+					parent: this,
+					popup: this._picker,
+					around: this.domNode,
+					onCancel: dojo.hitch(this, this._close),
+					onClose: function(){ textBox._opened=false; }
+				});
+				this._opened=true;
+			}
+			
+			dojo.marginBox(this._picker.domNode,{ w:this.domNode.offsetWidth });
+		},
+
+		_close: function(){
+			if(this._opened){
+				dijit.popup.close(this._picker);
+				this._opened=false;
+			}			
+		},
+
+		_onBlur: function(){
+			// summary:
+			//		Called magically when focus has shifted away from this widget and it's dropdown
+			this._close();
+			if(this._picker){
+				// teardown so that constraints will be rebuilt next time (redundant reference: #6002)
+				this._picker.destroy();
+				delete this._picker;
+			}
+			this.inherited(arguments);
+			// don't focus on <input>.  the user has explicitly focused on something else.
+		},
+
+		_getDisplayedValueAttr: function(){
+			return this.textbox.value;
+		},
+
+		_setDisplayedValueAttr: function(/*String*/ value, /*Boolean?*/ priorityChange){
+			this._setValueAttr(this.parse(value, this.constraints), priorityChange, value);
+		},
+
+		destroy: function(){
+			if(this._picker){
+				this._picker.destroy();
+				delete this._picker;
+			}
+			this.inherited(arguments);
+		},
+
+		postCreate: function(){
+			this.inherited(arguments);
+			this.connect(this.focusNode, 'onkeypress', this._onKeyPress);
+		},
+
+		_onKeyPress: function(/*Event*/ e){
+			// summary:
+			//		Handler for keypress events
+
+			var p = this._picker, dk = dojo.keys;
+			// Handle the key in the picker, if it has a handler.  If the handler
+			// returns false, then don't handle any other keys.
+			if(p && this._opened && p.handleKey){
+				if(p.handleKey(e) === false){ return; }
+			}
+			if(this._opened && e.charOrCode == dk.ESCAPE && !e.shiftKey && !e.ctrlKey && !e.altKey){
+				this._close();
+				dojo.stopEvent(e);
+			}else if(!this._opened && e.charOrCode == dk.DOWN_ARROW){
+				this._open();
+				dojo.stopEvent(e);
+			}else if(e.charOrCode === dk.TAB){
+				this._tabbingAway = true;
+			}else if(this._opened && (e.keyChar || e.charOrCode === dk.BACKSPACE || e.charOrCode == dk.DELETE)){
+				// Replace the element - but do it after a delay to allow for 
+				// filtering to occur
+				setTimeout(dojo.hitch(this, function(){
+					dijit.placeOnScreenAroundElement(p.domNode.parentNode, this.domNode, {'BL':'TL', 'TL':'BL'}, p.orient ? dojo.hitch(p, "orient") : null);
+				}), 1);
+			}
+		}
+	}
+);
+
+}
+
+if(!dojo._hasResource["dijit.form.DateTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.DateTextBox"] = true;
+dojo.provide("dijit.form.DateTextBox");
+
+
+
+
+dojo.declare(
+	"dijit.form.DateTextBox",
+	dijit.form._DateTimeTextBox,
+	{
+		// summary:
+		//		A validating, serializable, range-bound date text box with a drop down calendar
+
+		baseClass: "dijitTextBox dijitDateTextBox",
+		popupClass: "dijit._Calendar",
+		_selector: "date",
+
+		//	value: Date
+		//		The value of this widget as a JavaScript Date object, with only year/month/day specified.
+		//
+		//		Example:
+		// |	new dijit.form.DateTextBox({value: new Date(2009,1,20)})
+		//
+		//		When passed to the parser in markup, must be specified according to locale-independent
+		//		`dojo.date.stamp.fromISOString` format.
+		//
+		//		Example:
+		// |	<input dojotype='dijit.form.DateTextBox' value='2009-01-20'>
+		value: new Date("")	// value.toString()="NaN"
+
+	}
+);
+
+}
+
+if(!dojo._hasResource["dijit.form.ComboBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.ComboBox"] = true;
+dojo.provide("dijit.form.ComboBox");
+
+
+
+
+
+
+
+
+dojo.declare(
+	"dijit.form.ComboBoxMixin",
+	null,
+	{
+		// summary:
+		//		Implements the base functionality for ComboBox/FilteringSelect
+		// description:
+		//		All widgets that mix in dijit.form.ComboBoxMixin must extend dijit.form._FormValueWidget
+		// tags:
+		//		protected
+
+		// item: Object
+		//		This is the item returned by the dojo.data.store implementation that
+		//		provides the data for this cobobox, it's the currently selected item.
+		item: null,
+
+		// pageSize: Integer
+		//		Argument to data provider.
+		//		Specifies number of search results per page (before hitting "next" button)
+		pageSize: Infinity,
+
+		// store: Object
+		//		Reference to data provider object used by this ComboBox
+		store: null,
+
+		// fetchProperties: Object
+		//		Mixin to the dojo.data store's fetch.
+		//		For example, to set the sort order of the ComboBox menu, pass:
+		//		{sort:{attribute:"name",descending: true}}
+		fetchProperties:{},
+
+		// query: Object
+		//		A query that can be passed to 'store' to initially filter the items,
+		//		before doing further filtering based on `searchAttr` and the key.
+		//		Any reference to the `searchAttr` is ignored.
+		query: {},
+
+		// autoComplete: Boolean
+		//		If user types in a partial string, and then tab out of the `<input>` box,
+		//		automatically copy the first entry displayed in the drop down list to
+		//		the `<input>` field
+		autoComplete: true,
+
+		// highlightMatch: String
+		// 		One of: "first", "all" or "none".
+		//
+		//		If the ComboBox/FilteringSelect opens with the search results and the searched
+		//		string can be found, it will be highlighted.  If set to "all"
+		//		then will probably want to change `queryExpr` parameter to '*${0}*'
+		//
+		//		Highlighting is only performed when `labelType` is "text", so as to not
+		//		interfere with any HTML markup an HTML label might contain.
+		highlightMatch: "first",
+		
+		// searchDelay: Integer
+		//		Delay in milliseconds between when user types something and we start
+		//		searching based on that value
+		searchDelay: 100,
+
+		// searchAttr: String
+		//		Search for items in the data store where this attribute (in the item)
+		//		matches what the user typed
+		searchAttr: "name",
+
+		// labelAttr: String?
+		//		The entries in the drop down list come from this attribute in the
+		//		dojo.data items.
+		//		If not specified, the searchAttr attribute is used instead.
+		labelAttr: "",
+
+		// labelType: String
+		//		Specifies how to interpret the labelAttr in the data store items.
+		//		Can be "html" or "text".
+		labelType: "text",
+
+		// queryExpr: String
+		//		This specifies what query ComboBox/FilteringSelect sends to the data store,
+		//		based on what the user has typed.  Changing this expression will modify
+		//		whether the drop down shows only exact matches, a "starting with" match,
+		//		etc.   Use it in conjunction with highlightMatch.
+		//		dojo.data query expression pattern.
+		//		`${0}` will be substituted for the user text.
+		//		`*` is used for wildcards.
+		//		`${0}*` means "starts with", `*${0}*` means "contains", `${0}` means "is"
+		queryExpr: "${0}*",
+
+		// ignoreCase: Boolean
+		//		Set true if the ComboBox/FilteringSelect should ignore case when matching possible items
+		ignoreCase: true,
+
+		// hasDownArrow: Boolean
+		//		Set this textbox to have a down arrow button, to display the drop down list.
+		//		Defaults to true.
+		hasDownArrow: true,
+
+		templateString:"<div class=\"dijit dijitReset dijitInlineTable dijitLeft\"\n\tid=\"widget_${id}\"\n\tdojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse\" dojoAttachPoint=\"comboNode\" waiRole=\"combobox\" tabIndex=\"-1\"\n\t><div style=\"overflow:hidden;\"\n\t\t><div class='dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton'\n\t\t\tdojoAttachPoint=\"downArrowNode\" waiRole=\"presentation\"\n\t\t\tdojoAttachEvent=\"onmousedown:_onArrowMouseDown,onmouseup:_onMouse,onmouseenter:_onMouse,onmouseleave:_onMouse\"\n\t\t\t><div class=\"dijitArrowButtonInner\">&thinsp;</div\n\t\t\t><div class=\"dijitArrowButtonChar\">&#9660;</div\n\t\t></div\n\t\t><div class=\"dijitReset dijitValidationIcon\"><br></div\n\t\t><div class=\"dijitReset dijitValidationIconText\">&Chi;</div\n\t\t><div class=\"dijitReset dijitInputField\"\n\t\t\t><input ${nameAttrSetting} type=\"text\" autocomplete=\"off\" class='dijitReset'\n\t\t\tdojoAttachEvent=\"onkeypress:_onKeyPress,compositionend\"\n\t\t\tdojoAttachPoint=\"textbox,focusNode\" waiRole=\"textbox\" waiState=\"haspopup-true,autocomplete-list\"\n\t\t/></div\n\t></div\n></div>\n",
+
+		baseClass:"dijitComboBox",
+
+		_getCaretPos: function(/*DomNode*/ element){
+			// khtml 3.5.2 has selection* methods as does webkit nightlies from 2005-06-22
+			var pos = 0;
+			if(typeof(element.selectionStart)=="number"){
+				// FIXME: this is totally borked on Moz < 1.3. Any recourse?
+				pos = element.selectionStart;
+			}else if(dojo.isIE){
+				// in the case of a mouse click in a popup being handled,
+				// then the dojo.doc.selection is not the textarea, but the popup
+				// var r = dojo.doc.selection.createRange();
+				// hack to get IE 6 to play nice. What a POS browser.
+				var tr = dojo.doc.selection.createRange().duplicate();
+				var ntr = element.createTextRange();
+				tr.move("character",0);
+				ntr.move("character",0);
+				try{
+					// If control doesnt have focus, you get an exception.
+					// Seems to happen on reverse-tab, but can also happen on tab (seems to be a race condition - only happens sometimes).
+					// There appears to be no workaround for this - googled for quite a while.
+					ntr.setEndPoint("EndToEnd", tr);
+					pos = String(ntr.text).replace(/\r/g,"").length;
+				}catch(e){
+					// If focus has shifted, 0 is fine for caret pos.
+				}
+			}
+			return pos;
+		},
+
+		_setCaretPos: function(/*DomNode*/ element, /*Number*/ location){
+			location = parseInt(location);
+			dijit.selectInputText(element, location, location);
+		},
+
+		_setDisabledAttr: function(/*Boolean*/ value){
+			// Additional code to set disabled state of combobox node.
+			// Overrides _FormValueWidget._setDisabledAttr() or ValidationTextBox._setDisabledAttr().
+			this.inherited(arguments);
+			dijit.setWaiState(this.comboNode, "disabled", value);
+		},	
+		
+		_onKeyPress: function(/*Event*/ evt){
+			// summary:
+			//		Handles keyboard events
+			var key = evt.charOrCode;
+			//except for cutting/pasting case - ctrl + x/v
+			if(evt.altKey || (evt.ctrlKey && (key != 'x' && key != 'v')) || evt.key == dojo.keys.SHIFT){
+				return; // throw out weird key combinations and spurious events
+			}
+			var doSearch = false;
+			var pw = this._popupWidget;
+			var dk = dojo.keys;
+			var highlighted = null;
+			if(this._isShowingNow){
+				pw.handleKey(key);
+				highlighted = pw.getHighlightedOption();
+			}
+			switch(key){
+				case dk.PAGE_DOWN:
+				case dk.DOWN_ARROW:
+					if(!this._isShowingNow||this._prev_key_esc){
+						this._arrowPressed();
+						doSearch=true;
+					}else if(highlighted){
+						this._announceOption(highlighted);
+					}
+					dojo.stopEvent(evt);
+					this._prev_key_backspace = false;
+					this._prev_key_esc = false;
+					break;
+
+				case dk.PAGE_UP:
+				case dk.UP_ARROW:
+					if(this._isShowingNow){
+						this._announceOption(highlighted);
+					}
+					dojo.stopEvent(evt);
+					this._prev_key_backspace = false;
+					this._prev_key_esc = false;
+					break;
+
+				case dk.ENTER:
+					// prevent submitting form if user presses enter. Also
+					// prevent accepting the value if either Next or Previous
+					// are selected
+					if(highlighted){
+						// only stop event on prev/next
+						if(highlighted == pw.nextButton){
+							this._nextSearch(1);
+							dojo.stopEvent(evt);
+							break;
+						}else if(highlighted == pw.previousButton){
+							this._nextSearch(-1);
+							dojo.stopEvent(evt);
+							break;
+						}
+					}else{
+						// Update 'value' (ex: KY) according to currently displayed text
+						this._setDisplayedValueAttr(this.attr('displayedValue'), true);
+					}
+					// default case:
+					// prevent submit, but allow event to bubble
+					evt.preventDefault();
+					// fall through
+
+				case dk.TAB:
+					var newvalue = this.attr('displayedValue');
+					// #4617: 
+					//		if the user had More Choices selected fall into the
+					//		_onBlur handler
+					if(pw && (
+						newvalue == pw._messages["previousMessage"] ||
+						newvalue == pw._messages["nextMessage"])
+					){
+						break;
+					}
+					if(this._isShowingNow){
+						this._prev_key_backspace = false;
+						this._prev_key_esc = false;
+						if(highlighted){
+							pw.attr('value', { target: highlighted });
+						}
+						this._lastQuery = null; // in case results come back later
+						this._hideResultList();
+					}
+					break;
+
+				case ' ':
+					this._prev_key_backspace = false;
+					this._prev_key_esc = false;
+					if(highlighted){
+						dojo.stopEvent(evt);
+						this._selectOption();
+						this._hideResultList();
+					}else{
+						doSearch = true;
+					}
+					break;
+
+				case dk.ESCAPE:
+					this._prev_key_backspace = false;
+					this._prev_key_esc = true;
+					if(this._isShowingNow){
+						dojo.stopEvent(evt);
+						this._hideResultList();
+					}
+					break;
+
+				case dk.DELETE:
+				case dk.BACKSPACE:
+					this._prev_key_esc = false;
+					this._prev_key_backspace = true;
+					doSearch = true;
+					break;
+
+				case dk.RIGHT_ARROW: // fall through
+				case dk.LEFT_ARROW: 
+					this._prev_key_backspace = false;
+					this._prev_key_esc = false;
+					break;
+
+				default: // non char keys (F1-F12 etc..)  shouldn't open list
+					this._prev_key_backspace = false;
+					this._prev_key_esc = false;
+					doSearch = typeof key == 'string';
+			}
+			if(this.searchTimer){
+				clearTimeout(this.searchTimer);
+			}
+			if(doSearch){
+				// need to wait a tad before start search so that the event
+				// bubbles through DOM and we have value visible
+				setTimeout(dojo.hitch(this, "_startSearchFromInput"),1);
+			}
+		},
+
+		_autoCompleteText: function(/*String*/ text){
+			// summary:
+			// 		Fill in the textbox with the first item from the drop down
+			// 		list, and highlight the characters that were
+			// 		auto-completed. For example, if user typed "CA" and the
+			// 		drop down list appeared, the textbox would be changed to
+			// 		"California" and "ifornia" would be highlighted.
+
+			var fn = this.focusNode;
+
+			// IE7: clear selection so next highlight works all the time
+			dijit.selectInputText(fn, fn.value.length);
+			// does text autoComplete the value in the textbox?
+			var caseFilter = this.ignoreCase? 'toLowerCase' : 'substr';
+			if(text[caseFilter](0).indexOf(this.focusNode.value[caseFilter](0)) == 0){
+				var cpos = this._getCaretPos(fn);
+				// only try to extend if we added the last character at the end of the input
+				if((cpos+1) > fn.value.length){
+					// only add to input node as we would overwrite Capitalisation of chars
+					// actually, that is ok
+					fn.value = text;//.substr(cpos);
+					// visually highlight the autocompleted characters
+					dijit.selectInputText(fn, cpos);
+				}
+			}else{
+				// text does not autoComplete; replace the whole value and highlight
+				fn.value = text;
+				dijit.selectInputText(fn);
+			}
+		},
+
+		_openResultList: function(/*Object*/ results, /*Object*/ dataObject){
+			if(	this.disabled || 
+				this.readOnly || 
+				(dataObject.query[this.searchAttr] != this._lastQuery)
+			){
+				return;
+			}
+			this._popupWidget.clearResultList();
+			if(!results.length){
+				this._hideResultList();
+				return;
+			}
+
+			// Fill in the textbox with the first item from the drop down list,
+			// and highlight the characters that were auto-completed. For
+			// example, if user typed "CA" and the drop down list appeared, the
+			// textbox would be changed to "California" and "ifornia" would be
+			// highlighted.
+
+			this.item = null;
+			var zerothvalue = new String(this.store.getValue(results[0], this.searchAttr));
+			if(zerothvalue && this.autoComplete && !this._prev_key_backspace &&
+				(dataObject.query[this.searchAttr] != "*")){
+				// when the user clicks the arrow button to show the full list,
+				// startSearch looks for "*".
+				// it does not make sense to autocomplete
+				// if they are just previewing the options available.
+				this.item = results[0];
+				this._autoCompleteText(zerothvalue);
+			}
+			dataObject._maxOptions = this._maxOptions;
+			this._popupWidget.createOptions(
+				results, 
+				dataObject, 
+				dojo.hitch(this, "_getMenuLabelFromItem")
+			);
+
+			// show our list (only if we have content, else nothing)
+			this._showResultList();
+
+			// #4091:
+			//		tell the screen reader that the paging callback finished by
+			//		shouting the next choice
+			if(dataObject.direction){
+				if(1 == dataObject.direction){
+					this._popupWidget.highlightFirstOption();
+				}else if(-1 == dataObject.direction){
+					this._popupWidget.highlightLastOption();
+				}
+				this._announceOption(this._popupWidget.getHighlightedOption());
+			}
+		},
+
+		_showResultList: function(){
+			this._hideResultList();
+			var items = this._popupWidget.getItems(),
+				visibleCount = Math.min(items.length,this.maxListLength);   // TODO: unused, remove
+			this._arrowPressed();
+			// hide the tooltip
+			this.displayMessage("");
+			
+			// Position the list and if it's too big to fit on the screen then
+			// size it to the maximum possible height
+			// Our dear friend IE doesnt take max-height so we need to
+			// calculate that on our own every time
+
+			// TODO: want to redo this, see 
+			//		http://trac.dojotoolkit.org/ticket/3272
+			//	and
+			//		http://trac.dojotoolkit.org/ticket/4108
+
+
+			// natural size of the list has changed, so erase old
+			// width/height settings, which were hardcoded in a previous
+			// call to this function (via dojo.marginBox() call)
+			dojo.style(this._popupWidget.domNode, {width: "", height: ""});
+
+			var best = this.open();
+			// #3212:
+			//		only set auto scroll bars if necessary prevents issues with
+			//		scroll bars appearing when they shouldn't when node is made
+			//		wider (fractional pixels cause this)
+			var popupbox = dojo.marginBox(this._popupWidget.domNode);
+			this._popupWidget.domNode.style.overflow = 
+				((best.h==popupbox.h)&&(best.w==popupbox.w)) ? "hidden" : "auto";
+			// #4134:
+			//		borrow TextArea scrollbar test so content isn't covered by
+			//		scrollbar and horizontal scrollbar doesn't appear
+			var newwidth = best.w;
+			if(best.h < this._popupWidget.domNode.scrollHeight){
+				newwidth += 16;
+			}
+			dojo.marginBox(this._popupWidget.domNode, {
+				h: best.h,
+				w: Math.max(newwidth, this.domNode.offsetWidth)
+			});
+			dijit.setWaiState(this.comboNode, "expanded", "true");
+		},
+
+		_hideResultList: function(){
+			if(this._isShowingNow){
+				dijit.popup.close(this._popupWidget);
+				this._arrowIdle();
+				this._isShowingNow=false;
+				dijit.setWaiState(this.comboNode, "expanded", "false");
+				dijit.removeWaiState(this.focusNode,"activedescendant");
+			}
+		},
+
+		_setBlurValue: function(){
+			// if the user clicks away from the textbox OR tabs away, set the
+			// value to the textbox value
+			// #4617: 
+			//		if value is now more choices or previous choices, revert
+			//		the value
+			var newvalue=this.attr('displayedValue');
+			var pw = this._popupWidget;
+			if(pw && (
+				newvalue == pw._messages["previousMessage"] ||
+				newvalue == pw._messages["nextMessage"]
+				)
+			){
+				this._setValueAttr(this._lastValueReported, true);
+			}else{
+				// Update 'value' (ex: KY) according to currently displayed text
+				this.attr('displayedValue', newvalue);
+			}
+		},
+
+		_onBlur: function(){
+			// summary:
+			//		Called magically when focus has shifted away from this widget and it's drop down
+			this._hideResultList();
+			this._arrowIdle();
+			this.inherited(arguments);
+		},
+
+		_announceOption: function(/*Node*/ node){
+			// summary:
+			//		a11y code that puts the highlighted option in the textbox.
+			//		This way screen readers will know what is happening in the
+			//		menu.
+
+			if(node == null){
+				return;
+			}
+			// pull the text value from the item attached to the DOM node
+			var newValue;
+			if( node == this._popupWidget.nextButton ||
+				node == this._popupWidget.previousButton){
+				newValue = node.innerHTML;
+			}else{
+				newValue = this.store.getValue(node.item, this.searchAttr);
+			}
+			// get the text that the user manually entered (cut off autocompleted text)
+			this.focusNode.value = this.focusNode.value.substring(0, this._getCaretPos(this.focusNode));
+			//set up ARIA activedescendant
+			dijit.setWaiState(this.focusNode, "activedescendant", dojo.attr(node, "id")); 
+			// autocomplete the rest of the option to announce change
+			this._autoCompleteText(newValue);
+		},
+
+		_selectOption: function(/*Event*/ evt){
+			var tgt = null;
+			if(!evt){
+				evt ={ target: this._popupWidget.getHighlightedOption()};
+			}
+				// what if nothing is highlighted yet?
+			if(!evt.target){
+				// handle autocompletion where the the user has hit ENTER or TAB
+				this.attr('displayedValue', this.attr('displayedValue'));
+				return;
+			// otherwise the user has accepted the autocompleted value
+			}else{
+				tgt = evt.target;
+			}
+			if(!evt.noHide){
+				this._hideResultList();
+				this._setCaretPos(this.focusNode, this.store.getValue(tgt.item, this.searchAttr).length);
+			}
+			this._doSelect(tgt);
+		},
+
+		_doSelect: function(tgt){
+			// summary:
+			//		Menu callback function, called when an item in the menu is selected.
+			this.item = tgt.item;
+			this.attr('value', this.store.getValue(tgt.item, this.searchAttr));
+		},
+
+		_onArrowMouseDown: function(evt){
+			// summary:
+			//		Callback when arrow is clicked
+			if(this.disabled || this.readOnly){
+				return;
+			}
+			dojo.stopEvent(evt);
+			this.focus();
+			if(this._isShowingNow){
+				this._hideResultList();
+			}else{
+				// forces full population of results, if they click
+				// on the arrow it means they want to see more options
+				this._startSearch("");
+			}
+		},
+
+		_startSearchFromInput: function(){
+			this._startSearch(this.focusNode.value.replace(/([\\\*\?])/g, "\\$1"));
+		},
+
+		_getQueryString: function(/*String*/ text){
+			return dojo.string.substitute(this.queryExpr, [text]);
+		},
+
+		_startSearch: function(/*String*/ key){
+			if(!this._popupWidget){
+				var popupId = this.id + "_popup";
+				this._popupWidget = new dijit.form._ComboBoxMenu({
+					onChange: dojo.hitch(this, this._selectOption),
+					id: popupId
+				});
+				dijit.removeWaiState(this.focusNode,"activedescendant");
+				dijit.setWaiState(this.textbox,"owns",popupId); // associate popup with textbox
+			}
+			// create a new query to prevent accidentally querying for a hidden
+			// value from FilteringSelect's keyField
+			this.item = null; // #4872
+			var query = dojo.clone(this.query); // #5970
+			this._lastInput = key; // Store exactly what was entered by the user.
+			this._lastQuery = query[this.searchAttr] = this._getQueryString(key);
+			// #5970: set _lastQuery, *then* start the timeout
+			// otherwise, if the user types and the last query returns before the timeout,
+			// _lastQuery won't be set and their input gets rewritten
+			this.searchTimer=setTimeout(dojo.hitch(this, function(query, _this){
+				var fetch = {
+					queryOptions: {
+						ignoreCase: this.ignoreCase, 
+						deep: true
+					},
+					query: query,
+					onBegin: dojo.hitch(this, "_setMaxOptions"),
+					onComplete: dojo.hitch(this, "_openResultList"), 
+					onError: function(errText){
+						console.error('dijit.form.ComboBox: ' + errText);
+						dojo.hitch(_this, "_hideResultList")();
+					},
+					start: 0,
+					count: this.pageSize
+				};
+				dojo.mixin(fetch, _this.fetchProperties);
+				var dataObject = _this.store.fetch(fetch);
+
+				var nextSearch = function(dataObject, direction){
+					dataObject.start += dataObject.count*direction;
+					// #4091:
+					//		tell callback the direction of the paging so the screen
+					//		reader knows which menu option to shout
+					dataObject.direction = direction;
+					this.store.fetch(dataObject);
+				};
+				this._nextSearch = this._popupWidget.onPage = dojo.hitch(this, nextSearch, dataObject);
+			}, query, this), this.searchDelay);
+		},
+
+		_setMaxOptions: function(size, request){
+			 this._maxOptions = size;
+		},
+
+		_getValueField: function(){
+			// summmary:
+			//		Helper for postMixInProperties() to set this.value based on data inlined into the markup.
+			//		Returns the attribute name in the item (in dijit.form._ComboBoxDataStore) to use as the value.
+			return this.searchAttr;
+		},
+
+		/////////////// Event handlers /////////////////////
+
+		_arrowPressed: function(){
+			if(!this.disabled && !this.readOnly && this.hasDownArrow){
+				dojo.addClass(this.downArrowNode, "dijitArrowButtonActive");
+			}
+		},
+
+		_arrowIdle: function(){
+			if(!this.disabled && !this.readOnly && this.hasDownArrow){
+				dojo.removeClass(this.downArrowNode, "dojoArrowButtonPushed");
+			}
+		},
+
+		// FIXME: For 2.0, rename to "_compositionEnd"
+		compositionend: function(/*Event*/ evt){
+			// summary:
+			//		When inputting characters using an input method, such as
+			//		Asian languages, it will generate this event instead of
+			//		onKeyDown event.
+			//		Note: this event is only triggered in FF (not in IE)
+			// tags:
+			//		private
+			this._onKeyPress({charCode:-1});
+		},
+
+		//////////// INITIALIZATION METHODS ///////////////////////////////////////
+
+		constructor: function(){
+			this.query={};
+			this.fetchProperties={};
+		},
+
+		postMixInProperties: function(){
+			if(!this.hasDownArrow){
+				this.baseClass = "dijitTextBox";
+			}
+			if(!this.store){
+				var srcNodeRef = this.srcNodeRef;
+
+				// if user didn't specify store, then assume there are option tags
+				this.store = new dijit.form._ComboBoxDataStore(srcNodeRef);
+
+				// if there is no value set and there is an option list, set
+				// the value to the first value to be consistent with native
+				// Select
+
+				// Firefox and Safari set value
+				// IE6 and Opera set selectedIndex, which is automatically set
+				// by the selected attribute of an option tag
+				// IE6 does not set value, Opera sets value = selectedIndex
+				if(	!this.value || (
+						(typeof srcNodeRef.selectedIndex == "number") && 
+						srcNodeRef.selectedIndex.toString() === this.value)
+				){
+					var item = this.store.fetchSelectedItem();
+					if(item){
+						this.value = this.store.getValue(item, this._getValueField());
+					}
+				}
+			}
+			this.inherited(arguments);
+		},
+		
+		postCreate: function(){
+			// summary:
+			//		Subclasses must call this method from their postCreate() methods
+			// tags: protected
+
+			//find any associated label element and add to combobox node.
+			var label=dojo.query('label[for="'+this.id+'"]');
+			if(label.length){
+				label[0].id = (this.id+"_label");
+				var cn=this.comboNode;
+				dijit.setWaiState(cn, "labelledby", label[0].id);
+				
+			}
+			this.inherited(arguments);
+		},
+
+		uninitialize: function(){
+			if(this._popupWidget){
+				this._hideResultList();
+				this._popupWidget.destroy();
+			}
+		},
+
+		_getMenuLabelFromItem: function(/*Item*/ item){
+			var label = this.store.getValue(item, this.labelAttr || this.searchAttr);
+			var labelType = this.labelType;
+			// If labelType is not "text" we don't want to screw any markup ot whatever.
+			if (this.highlightMatch!="none" && this.labelType=="text" && this._lastInput){
+				label = this.doHighlight(label, this._escapeHtml(this._lastInput));
+				labelType = "html";
+			}
+			return {html: labelType=="html", label: label};
+		},
+		
+		doHighlight: function(/*String*/label, /*String*/find){
+			// summary:
+			//		Highlights the string entered by the user in the menu.  By default this
+			//		highlights the first occurence found. Override this method
+			//		to implement your custom highlighing.
+			// tags:
+			//		protected
+
+			// Add greedy when this.highlightMatch=="all"
+			var modifiers = "i"+(this.highlightMatch=="all"?"g":"");
+			var escapedLabel = this._escapeHtml(label);
+			find = dojo.regexp.escapeString(find); // escape regexp special chars
+			var ret = escapedLabel.replace(new RegExp("(^|\\s)("+ find +")", modifiers),
+					'$1<span class="dijitComboBoxHighlightMatch">$2</span>');
+			return ret;// returns String, (almost) valid HTML (entities encoded)
+		},
+		
+		_escapeHtml: function(/*string*/str){
+			// TODO Should become dojo.html.entities(), when exists use instead
+			// summary:
+			//		Adds escape sequences for special characters in XML: &<>"'
+			str = String(str).replace(/&/gm, "&amp;").replace(/</gm, "&lt;")
+				.replace(/>/gm, "&gt;").replace(/"/gm, "&quot;");
+			return str; // string
+		},
+
+		open: function(){
+			// summary:
+			//		Opens the drop down menu.  TODO: rename to _open.
+			// tags:
+			//		private
+			this._isShowingNow=true;
+			return dijit.popup.open({
+				popup: this._popupWidget,
+				around: this.domNode,
+				parent: this
+			});
+		},
+		
+		reset: function(){
+			// Overrides the _FormWidget.reset().
+			// Additionally reset the .item (to clean up).
+			this.item = null;
+			this.inherited(arguments);
+		}
+		
+	}
+);
+
+dojo.declare(
+	"dijit.form._ComboBoxMenu",
+	[dijit._Widget, dijit._Templated],
+	{
+		// summary:
+		//		Focus-less menu for internal use in `dijit.form.ComboBox`
+		// tags:
+		//		private
+
+		templateString: "<ul class='dijitReset dijitMenu' dojoAttachEvent='onmousedown:_onMouseDown,onmouseup:_onMouseUp,onmouseover:_onMouseOver,onmouseout:_onMouseOut' tabIndex='-1' style='overflow: \"auto\"; overflow-x: \"hidden\";'>"
+				+"<li class='dijitMenuItem dijitMenuPreviousButton' dojoAttachPoint='previousButton' waiRole='option'></li>"
+				+"<li class='dijitMenuItem dijitMenuNextButton' dojoAttachPoint='nextButton' waiRole='option'></li>"
+			+"</ul>",
+
+		// _messages: Object
+		//		Holds "next" and "previous" text for paging buttons on drop down
+		_messages: null,
+
+		postMixInProperties: function(){
+			this._messages = dojo.i18n.getLocalization("dijit.form", "ComboBox", this.lang);
+			this.inherited(arguments);
+		},
+
+		_setValueAttr: function(/*Object*/ value){
+			this.value = value;
+			this.onChange(value);
+		},
+
+		// stubs
+		onChange: function(/*Object*/ value){
+			// summary:
+			//		Notifies ComboBox/FilteringSelect that user clicked an option in the drop down menu.
+			//		Probably should be called onSelect.
+			// tags:
+			//		callback
+		},
+		onPage: function(/*Number*/ direction){
+			// summary:
+			//		Notifies ComboBox/FilteringSelect that user clicked to advance to next/previous page.
+			// tags:
+			//		callback
+		},
+
+		postCreate: function(){
+			// fill in template with i18n messages
+			this.previousButton.innerHTML = this._messages["previousMessage"];
+			this.nextButton.innerHTML = this._messages["nextMessage"];
+			this.inherited(arguments);
+		},
+
+		onClose: function(){
+			// summary:
+			//		Callback from dijit.popup code to this widget, notifying it that it closed
+			// tags:
+			//		private
+			this._blurOptionNode();
+		},
+
+		_createOption: function(/*Object*/ item, labelFunc){
+			// summary: 
+			//		Creates an option to appear on the popup menu subclassed by
+			//		`dijit.form.FilteringSelect`.
+
+			var labelObject = labelFunc(item);
+			var menuitem = dojo.doc.createElement("li");
+			dijit.setWaiRole(menuitem, "option");
+			if(labelObject.html){
+				menuitem.innerHTML = labelObject.label;
+			}else{
+				menuitem.appendChild(
+					dojo.doc.createTextNode(labelObject.label)
+				);
+			}
+			// #3250: in blank options, assign a normal height
+			if(menuitem.innerHTML == ""){
+				menuitem.innerHTML = "&nbsp;";
+			}
+			menuitem.item=item;
+			return menuitem;
+		},
+
+		createOptions: function(results, dataObject, labelFunc){
+			// summary:
+			//		Fills in the items in the drop down list
+			// results:
+			//		Array of dojo.data items
+			// dataObject:
+			//		dojo.data store
+			// labelFunc:
+			//		Function to produce a label in the drop down list from a dojo.data item
+
+			//this._dataObject=dataObject;
+			//this._dataObject.onComplete=dojo.hitch(comboBox, comboBox._openResultList);
+			// display "Previous . . ." button
+			this.previousButton.style.display = (dataObject.start == 0) ? "none" : "";
+			dojo.attr(this.previousButton, "id", this.id + "_prev");
+			// create options using _createOption function defined by parent
+			// ComboBox (or FilteringSelect) class
+			// #2309:
+			//		iterate over cache nondestructively
+			dojo.forEach(results, function(item, i){
+				var menuitem = this._createOption(item, labelFunc);
+				menuitem.className = "dijitReset dijitMenuItem";
+				dojo.attr(menuitem, "id", this.id + i);
+				this.domNode.insertBefore(menuitem, this.nextButton);
+			}, this);
+			// display "Next . . ." button
+			var displayMore = false;
+			//Try to determine if we should show 'more'...
+			if(dataObject._maxOptions && dataObject._maxOptions != -1){
+				if((dataObject.start + dataObject.count) < dataObject._maxOptions){
+					displayMore = true;
+				}else if((dataObject.start + dataObject.count) > (dataObject._maxOptions - 1)){
+					//Weird return from a datastore, where a start + count > maxOptions
+					//implies maxOptions isn't really valid and we have to go into faking it.
+					//And more or less assume more if count == results.length
+					if(dataObject.count == results.length){
+						displayMore = true;
+					}
+				}
+			}else if(dataObject.count == results.length){
+				//Don't know the size, so we do the best we can based off count alone.
+				//So, if we have an exact match to count, assume more.
+				displayMore = true;
+			}
+
+			this.nextButton.style.display = displayMore ? "" : "none";
+			dojo.attr(this.nextButton,"id", this.id + "_next");
+		},
+
+		clearResultList: function(){
+			// summary:
+			//		Clears the entries in the drop down list, but of course keeps the previous and next buttons.
+			while(this.domNode.childNodes.length>2){
+				this.domNode.removeChild(this.domNode.childNodes[this.domNode.childNodes.length-2]);
+			}
+		},
+
+		// these functions are called in showResultList
+		getItems: function(){
+			// summary:
+			//		Called from _showResultList().   Returns DOM Nodes representing the items in the drop down list.
+			return this.domNode.childNodes;
+		},
+
+		getListLength: function(){
+			// summary:
+			//		Called from _showResultList().   Returns number of  items in the drop down list,
+			//		not including next and previous buttons.
+			return this.domNode.childNodes.length-2;
+		},
+
+		_onMouseDown: function(/*Event*/ evt){
+			dojo.stopEvent(evt);
+		},
+
+		_onMouseUp: function(/*Event*/ evt){
+			if(evt.target === this.domNode){
+				return;
+			}else if(evt.target==this.previousButton){
+				this.onPage(-1);
+			}else if(evt.target==this.nextButton){
+				this.onPage(1);
+			}else{
+				var tgt = evt.target;
+				// while the clicked node is inside the div
+				while(!tgt.item){
+					// recurse to the top
+					tgt = tgt.parentNode;
+				}
+				this._setValueAttr({ target: tgt }, true);
+			}
+		},
+
+		_onMouseOver: function(/*Event*/ evt){
+			if(evt.target === this.domNode){ return; }
+			var tgt = evt.target;
+			if(!(tgt == this.previousButton || tgt == this.nextButton)){
+				// while the clicked node is inside the div
+				while(!tgt.item){
+					// recurse to the top
+					tgt = tgt.parentNode;
+				}
+			}
+			this._focusOptionNode(tgt);
+		},
+
+		_onMouseOut: function(/*Event*/ evt){
+			if(evt.target === this.domNode){ return; }
+			this._blurOptionNode();
+		},
+
+		_focusOptionNode: function(/*DomNode*/ node){
+			// summary:
+			//		Does the actual highlight.
+			if(this._highlighted_option != node){
+				this._blurOptionNode();
+				this._highlighted_option = node;
+				dojo.addClass(this._highlighted_option, "dijitMenuItemSelected");
+			}
+		},
+
+		_blurOptionNode: function(){
+			// summary:
+			//		Removes highlight on highlighted option.
+			if(this._highlighted_option){
+				dojo.removeClass(this._highlighted_option, "dijitMenuItemSelected");
+				this._highlighted_option = null;
+			}
+		},
+
+		_highlightNextOption: function(){
+			//	summary:
+			// 		Highlight the item just below the current selection.
+			// 		If nothing selected, highlight first option.
+
+			// because each press of a button clears the menu,
+			// the highlighted option sometimes becomes detached from the menu!
+			// test to see if the option has a parent to see if this is the case.
+			var fc = this.domNode.firstChild;
+			if(!this.getHighlightedOption()){
+				this._focusOptionNode(fc.style.display=="none" ? fc.nextSibling : fc);
+			}else{
+				var ns = this._highlighted_option.nextSibling;
+				if(ns && ns.style.display!="none"){
+					this._focusOptionNode(ns);
+				}
+			}
+			// scrollIntoView is called outside of _focusOptionNode because in IE putting it inside causes the menu to scroll up on mouseover
+			dijit.scrollIntoView(this._highlighted_option);
+		},
+
+		highlightFirstOption: function(){
+			//	summary:
+			// 		Highlight the first real item in the list (not Previous Choices).
+			this._focusOptionNode(this.domNode.firstChild.nextSibling);
+			dijit.scrollIntoView(this._highlighted_option);
+		},
+
+		highlightLastOption: function(){
+			//	summary:
+			// 		Highlight the last real item in the list (not More Choices).
+			this._focusOptionNode(this.domNode.lastChild.previousSibling);
+			dijit.scrollIntoView(this._highlighted_option);
+		},
+
+		_highlightPrevOption: function(){
+			//	summary:
+			// 		Highlight the item just above the current selection.
+			// 		If nothing selected, highlight last option (if
+			// 		you select Previous and try to keep scrolling up the list).
+			var lc = this.domNode.lastChild;
+			if(!this.getHighlightedOption()){
+				this._focusOptionNode(lc.style.display == "none" ? lc.previousSibling : lc);
+			}else{
+				var ps = this._highlighted_option.previousSibling;
+				if(ps && ps.style.display != "none"){
+					this._focusOptionNode(ps);
+				}
+			}
+			dijit.scrollIntoView(this._highlighted_option);
+		},
+
+		_page: function(/*Boolean*/ up){
+			// summary:
+			//		Handles page-up and page-down keypresses
+
+			var scrollamount = 0;
+			var oldscroll = this.domNode.scrollTop;
+			var height = dojo.style(this.domNode, "height");
+			// if no item is highlighted, highlight the first option
+			if(!this.getHighlightedOption()){
+				this._highlightNextOption();
+			}
+			while(scrollamount<height){
+				if(up){
+					// stop at option 1
+					if(!this.getHighlightedOption().previousSibling ||
+						this._highlighted_option.previousSibling.style.display == "none"){
+						break;
+					}
+					this._highlightPrevOption();
+				}else{
+					// stop at last option
+					if(!this.getHighlightedOption().nextSibling ||
+						this._highlighted_option.nextSibling.style.display == "none"){
+						break;
+					}
+					this._highlightNextOption();
+				}
+				// going backwards
+				var newscroll=this.domNode.scrollTop;
+				scrollamount+=(newscroll-oldscroll)*(up ? -1:1);
+				oldscroll=newscroll;
+			}
+		},
+
+		pageUp: function(){
+			// summary:
+			//		Handles pageup keypress.
+			//		TODO: just call _page directly from handleKey().
+			// tags:
+			//		private
+			this._page(true);
+		},
+
+		pageDown: function(){
+			// summary:
+			//		Handles pagedown keypress.
+			//		TODO: just call _page directly from handleKey().
+			// tags:
+			//		private
+			this._page(false);
+		},
+
+		getHighlightedOption: function(){
+			//	summary:
+			//		Returns the highlighted option.
+			var ho = this._highlighted_option;
+			return (ho && ho.parentNode) ? ho : null;
+		},
+
+		handleKey: function(key){
+			switch(key){
+				case dojo.keys.DOWN_ARROW:
+					this._highlightNextOption();
+					break;
+				case dojo.keys.PAGE_DOWN:
+					this.pageDown();
+					break;	
+				case dojo.keys.UP_ARROW:
+					this._highlightPrevOption();
+					break;
+				case dojo.keys.PAGE_UP:
+					this.pageUp();
+					break;	
+			}
+		}
+	}
+);
+
+dojo.declare(
+	"dijit.form.ComboBox",
+	[dijit.form.ValidationTextBox, dijit.form.ComboBoxMixin],
+	{
+		//	summary:
+		//		Auto-completing text box, and base class for dijit.form.FilteringSelect.
+		// 
+		//	description:
+		//		The drop down box's values are populated from an class called
+		//		a data provider, which returns a list of values based on the characters
+		//		that the user has typed into the input box.
+		//		If OPTION tags are used as the data provider via markup,
+		//		then the OPTION tag's child text node is used as the widget value 
+		//		when selected.  The OPTION tag's value attribute is ignored.
+		//		To set the default value when using OPTION tags, specify the selected 
+		//		attribute on 1 of the child OPTION tags.
+		// 
+		//		Some of the options to the ComboBox are actually arguments to the data
+		//		provider.
+
+		_setValueAttr: function(/*String*/ value, /*Boolean?*/ priorityChange){
+			// summary:
+			//		Hook so attr('value', value) works.
+			// description:
+			//		Sets the value of the select.
+			if(!value){ value = ''; } // null translates to blank
+			dijit.form.ValidationTextBox.prototype._setValueAttr.call(this, value, priorityChange);
+		}
+	}
+);
+
+dojo.declare("dijit.form._ComboBoxDataStore", null, {
+	//	summary:
+	//		Inefficient but small data store specialized for inlined `dijit.form.ComboBox` data
+	//
+	//	description:
+	//		Provides a store for inlined data like:
+	//
+	//	|	<select>
+	//	|		<option value="AL">Alabama</option>
+	//	|		...
+	//
+	//		Actually. just implements the subset of dojo.data.Read/Notification
+	//		needed for ComboBox and FilteringSelect to work.
+	//
+	//		Note that an item is just a pointer to the <option> DomNode.
+
+	constructor: function( /*DomNode*/ root){
+		this.root = root;
+
+		dojo.query("> option", root).forEach(function(node){
+			//	TODO: this was added in #3858 but unclear why/if it's needed;  doesn't seem to be.
+			//	If it is needed then can we just hide the select itself instead?
+			//node.style.display="none";
+			node.innerHTML = dojo.trim(node.innerHTML);
+		});
+
+	},
+
+	getValue: function(	/* item */ item, 
+						/* attribute-name-string */ attribute, 
+						/* value? */ defaultValue){
+		return (attribute == "value") ? item.value : (item.innerText || item.textContent || '');
+	},
+
+	isItemLoaded: function(/* anything */ something) {
+		return true;
+	},
+
+	getFeatures: function(){
+		return {"dojo.data.api.Read": true, "dojo.data.api.Identity": true};
+	},
+	
+	_fetchItems: function(	/* Object */ args,
+							/* Function */ findCallback, 
+							/* Function */ errorCallback){
+		//	summary: 
+		//		See dojo.data.util.simpleFetch.fetch()
+		if(!args.query){ args.query = {}; }
+		if(!args.query.name){ args.query.name = ""; }
+		if(!args.queryOptions){ args.queryOptions = {}; }
+		var matcher = dojo.data.util.filter.patternToRegExp(args.query.name, args.queryOptions.ignoreCase),
+			items = dojo.query("> option", this.root).filter(function(option){
+				return (option.innerText || option.textContent || '').match(matcher);
+			} );
+		if(args.sort){
+			items.sort(dojo.data.util.sorter.createSortFunction(args.sort, this));
+		}
+		findCallback(items, args);
+	},
+
+	close: function(/*dojo.data.api.Request || args || null */ request){
+		return;
+	},
+
+	getLabel: function(/* item */ item){
+		return item.innerHTML;
+	},
+
+	getIdentity: function(/* item */ item){
+		return dojo.attr(item, "value");
+	},
+
+	fetchItemByIdentity: function(/* Object */ args){
+		//	summary:
+		//		Given the identity of an item, this method returns the item that has
+		//		that identity through the onItem callback.
+		//		Refer to dojo.data.api.Identity.fetchItemByIdentity() for more details.
+		//
+		//	description:
+		//		Given arguments like:
+		//
+		//	|		{identity: "CA", onItem: function(item){...}
+		//
+		//		Call `onItem()` with the DOM node `<option value="CA">California</option>`
+		var item = dojo.query("option[value='" + args.identity + "']", this.root)[0];
+		args.onItem(item);
+	},
+	
+	fetchSelectedItem: function(){
+		//	summary:
+		//		Get the option marked as selected, like `<option selected>`.
+		//		Not part of dojo.data API.
+		var root = this.root,
+			si = root.selectedIndex;
+		return dojo.query("> option:nth-child(" +
+			(si != -1 ? si+1 : 1) + ")",
+			root)[0];	// dojo.data.Item
+	}
+});
+//Mix in the simple fetch implementation to this class. 
+dojo.extend(dijit.form._ComboBoxDataStore,dojo.data.util.simpleFetch);
+
+}
+
+if(!dojo._hasResource["dijit.form.FilteringSelect"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.FilteringSelect"] = true;
+dojo.provide("dijit.form.FilteringSelect");
+
+
+
+dojo.declare(
+	"dijit.form.FilteringSelect",
+	[dijit.form.MappedTextBox, dijit.form.ComboBoxMixin],
+	{
+		// summary:
+		//		An enhanced version of the HTML SELECT tag, populated dynamically
+		//
+		// description:
+		//		An enhanced version of the HTML SELECT tag, populated dynamically. It works
+		//		very nicely with very large data sets because it can load and page data as needed.
+		//		It also resembles ComboBox, but does not allow values outside of the provided ones.
+		//		If OPTION tags are used as the data provider via markup, then the
+		//		OPTION tag's child text node is used as the displayed value when selected
+		//		while the OPTION tag's value attribute is used as the widget value on form submit.
+		//		To set the default value when using OPTION tags, specify the selected
+		//		attribute on 1 of the child OPTION tags.
+		//
+		//		Similar features:
+		//			- There is a drop down list of possible values.
+		//			- You can only enter a value from the drop down list.  (You can't
+		//				enter an arbitrary value.)
+		//			- The value submitted with the form is the hidden value (ex: CA),
+		//				not the displayed value a.k.a. label (ex: California)
+		// 
+		//		Enhancements over plain HTML version:
+		//			- If you type in some text then it will filter down the list of
+		//				possible values in the drop down list.
+		//			- List can be specified either as a static list or via a javascript
+		//				function (that can get the list from a server)
+
+		_isvalid: true,
+
+		// required: Boolean
+		//		True if user is required to enter a value into this field.
+		required: true,
+
+		_lastDisplayedValue: "",
+
+		isValid: function(){
+			// Overrides ValidationTextBox.isValid()
+			return this._isvalid || (!this.required && this.attr('displayedValue') == ""); // #5974
+		},
+
+		_callbackSetLabel: function(	/*Array*/ result, 
+						/*Object*/ dataObject, 
+						/*Boolean?*/ priorityChange){
+			// summary:
+			//		Callback function that dynamically sets the label of the
+			//		ComboBox
+
+			// setValue does a synchronous lookup,
+			// so it calls _callbackSetLabel directly,
+			// and so does not pass dataObject
+			// still need to test against _lastQuery in case it came too late
+			if((dataObject && dataObject.query[this.searchAttr] != this._lastQuery)||(!dataObject && result.length && this.store.getIdentity(result[0])!= this._lastQuery)){
+				return;
+			}
+			if(!result.length){
+				//#3268: do nothing on bad input
+				//this._setValue("", "");
+				//#3285: change CSS to indicate error
+				this.valueNode.value = "";
+				dijit.form.TextBox.superclass._setValueAttr.call(this, "", priorityChange || (priorityChange===undefined && !this._focused));
+				this._isvalid = false;
+				this.validate(this._focused);
+				this.item = null;
+			}else{
+				this._setValueFromItem(result[0], priorityChange);
+			}
+		},
+
+		_openResultList: function(/*Object*/ results, /*Object*/ dataObject){
+			// Overrides ComboBox._openResultList()
+
+			// #3285: tap into search callback to see if user's query resembles a match
+			if(dataObject.query[this.searchAttr] != this._lastQuery){
+				return;
+			}
+			this._isvalid = results.length != 0; // FIXME: should this be greater-than?
+			this.validate(true);
+			dijit.form.ComboBoxMixin.prototype._openResultList.apply(this, arguments);
+		},
+
+		_getValueAttr: function(){
+			// summary:
+			//		Hook for attr('value') to work.
+
+			// don't get the textbox value but rather the previously set hidden value
+			// TODO: seems suspicious that we need this; how is FilteringSelect different
+			// than another MappedTextBox widget?
+			return this.valueNode.value;
+		},
+
+		_getValueField: function(){
+			// Overrides ComboBox._getValueField()
+			return "value";
+		},
+
+		_setValue: function(	/*String*/ value, 
+					/*String*/ displayedValue,
+					/*Boolean?*/ priorityChange){
+			// summary:
+			//		Internal function for setting the displayed value and hidden value.
+			//		Differs from _setValueAttr() in that _setValueAttr() only takes a single
+			//		value argument, and has to look up the displayed value from that.
+			// tags:
+			//		private
+			this.valueNode.value = value;
+			dijit.form.FilteringSelect.superclass._setValueAttr.call(this, value, priorityChange, displayedValue);
+			this._lastDisplayedValue = displayedValue;
+		},
+
+		_setValueAttr: function(/*String*/ value, /*Boolean?*/ priorityChange){
+			// summary:
+			//		Hook so attr('value', value) works.
+			// description:
+			//		Sets the value of the select.
+			//		Also sets the label to the corresponding value by reverse lookup.
+			if(!this._onChangeActive){ priorityChange = null; }
+			this._lastQuery = value;
+
+			if(value === null || value === ''){
+				this._setDisplayedValueAttr('', priorityChange);
+				return;
+			}
+
+			//#3347: fetchItemByIdentity if no keyAttr specified
+			var self = this;
+			var handleFetchByIdentity = function(item, priorityChange){
+				if(item){
+					if(self.store.isItemLoaded(item)){
+						self._callbackSetLabel([item], undefined, priorityChange);
+					}else{
+						self.store.loadItem({
+							item: item, 
+							onItem: function(result, dataObject){
+								self._callbackSetLabel(result, dataObject, priorityChange);
+							}
+						});
+					}
+				}else{
+					self._isvalid = false;
+					// prevent errors from Tooltip not being created yet
+					self.validate(false);
+				}
+			};
+			this.store.fetchItemByIdentity({
+				identity: value, 
+				onItem: function(item){
+					handleFetchByIdentity(item, priorityChange);
+				}
+			});
+		},
+
+		_setValueFromItem: function(/*item*/ item, /*Boolean?*/ priorityChange){
+			//	summary:
+			//		Set the displayed valued in the input box, and the hidden value
+			//		that gets submitted, based on a dojo.data store item.
+			//	description:
+			//		Users shouldn't call this function; they should be calling
+			//		attr('displayedValue', value) or attr('value', ...) instead
+			// tags:
+			//		private
+			this._isvalid = true;
+			this.item = item; // Fix #6381
+			this._setValue(	this.store.getIdentity(item), 
+							this.labelFunc(item, this.store), 
+							priorityChange);
+		},
+
+		labelFunc: function(/*item*/ item, /*dojo.data.store*/ store){
+			// summary:
+			//		Computes the label to display based on the dojo.data store item.
+			// returns:
+			//		The label that the ComboBox should display
+			// tags:
+			//		private
+			return store.getValue(item, this.searchAttr);
+		},
+
+		_doSelect: function(/*Event*/ tgt){
+			// summary:
+			//		Overrides ComboBox._doSelect(), the method called when an item in the menu is selected.
+			//	description:
+			//		FilteringSelect overrides this to set both the visible and
+			//		hidden value from the information stored in the menu.
+			this._setValueFromItem(tgt.item, true);
+		},
+
+		_setDisplayedValueAttr: function(/*String*/ label, /*Boolean?*/ priorityChange){
+			// summary:
+			//		Hook so attr('displayedValue', label) works.
+			// description:
+			//		Sets textbox to display label. Also performs reverse lookup
+			//		to set the hidden value.
+
+			// When this is called during initialization it'll ping the datastore
+			// for reverse lookup, and when that completes (after an XHR request)
+			// will call setValueAttr()... but that shouldn't trigger an onChange()
+			// event, even when it happens after creation has finished
+			if(!this._created){
+				priorityChange = false;
+			}
+
+			if(this.store){
+				var query = dojo.clone(this.query); // #6196: populate query with user-specifics
+				// escape meta characters of dojo.data.util.filter.patternToRegExp().
+				this._lastQuery = query[this.searchAttr] = label.replace(/([\\\*\?])/g, "\\$1");
+				// if the label is not valid, the callback will never set it,
+				// so the last valid value will get the warning textbox set the
+				// textbox value now so that the impending warning will make
+				// sense to the user
+				this.textbox.value = label;
+				this._lastDisplayedValue = label;
+				var _this = this;
+				var fetch = {
+					query: query, 
+					queryOptions: {
+						ignoreCase: this.ignoreCase, 
+						deep: true
+					}, 
+					onComplete: function(result, dataObject){
+						        dojo.hitch(_this, "_callbackSetLabel")(result, dataObject, priorityChange);
+					},
+					onError: function(errText){
+						console.error('dijit.form.FilteringSelect: ' + errText);
+						dojo.hitch(_this, "_setValue")("", label, false);
+					}
+				};
+				dojo.mixin(fetch, this.fetchProperties);
+				this.store.fetch(fetch);
+			}
+		},
+
+		postMixInProperties: function(){
+			this.inherited(arguments);
+			this._isvalid = !this.required;
+		},
+
+		undo: function(){
+			this.attr('displayedValue', this._lastDisplayedValue);
+		}
+	}
+);
+
+}
+
+if(!dojo._hasResource["dijit.form.MultiSelect"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.MultiSelect"] = true;
+dojo.provide("dijit.form.MultiSelect");
+
+
+
+dojo.declare("dijit.form.MultiSelect", dijit.form._FormWidget, {
+	// summary:
+	//		Widget version of a <select multiple=true> element,
+	//		for selecting multiple options.
+
+	// size: Number
+	//		Number of elements to display on a page
+	//		NOTE: may be removed in version 2.0, since elements may have variable height;
+	//		set the size via style="..." or CSS class names instead.
+	size: 7,
+	
+	templateString: "<select multiple='true' ${nameAttrSetting} dojoAttachPoint='containerNode,focusNode' dojoAttachEvent='onchange: _onChange'></select>",
+
+	attributeMap: dojo.delegate(dijit.form._FormWidget.prototype.attributeMap, {
+		size: "focusNode"
+	}),
+
+	reset: function(){
+		// summary:
+		//		Reset the widget's value to what it was at initialization time
+
+		// TODO: once we inherit from FormValueWidget this won't be needed
+		this._hasBeenBlurred = false;
+		this._setValueAttr(this._resetValue, true);
+	},
+
+	addSelected: function(/* dijit.form.MultiSelect */ select){
+		// summary:
+		//		Move the selected nodes of a passed Select widget
+		//		instance to this Select widget.
+		//
+		// example:
+		// |	// move all the selected values from "bar" to "foo"
+		// | 	dijit.byId("foo").addSelected(dijit.byId("bar"));
+		
+		select.getSelected().forEach(function(n){
+			this.containerNode.appendChild(n);
+			// scroll to bottom to see item
+			// cannot use scrollIntoView since <option> tags don't support all attributes
+			// does not work on IE due to a bug where <select> always shows scrollTop = 0
+			this.domNode.scrollTop = this.domNode.offsetHeight; // overshoot will be ignored
+			// scrolling the source select is trickier esp. on safari who forgets to change the scrollbar size
+			var oldscroll = select.domNode.scrollTop;
+			select.domNode.scrollTop = 0;
+			select.domNode.scrollTop = oldscroll;
+		},this);
+	},
+					
+	getSelected: function(){
+		// summary:
+		//		Access the NodeList of the selected options directly
+		return dojo.query("option",this.containerNode).filter(function(n){
+			return n.selected; // Boolean
+		}); // dojo.NodeList
+	},
+	
+	_getValueAttr: function(){
+		// summary:
+		//		Hook so attr('value') works.
+		// description:
+		//		Returns an array of the selected options' values.
+		return this.getSelected().map(function(n){
+			return n.value;
+		});
+	},
+	
+	_multiValue: true, // for Form
+
+	_setValueAttr: function(/* Array */values){
+		// summary:
+		//		Hook so attr('value', values) works.
+		// description:
+		//		Set the value(s) of this Select based on passed values
+		dojo.query("option",this.containerNode).forEach(function(n){
+			n.selected = (dojo.indexOf(values,n.value) != -1);
+		});
+	},
+		
+	invertSelection: function(onChange){
+		// summary:
+		//		Invert the selection
+		// onChange: Boolean
+		//		If null, onChange is not fired.
+		dojo.query("option",this.containerNode).forEach(function(n){
+			n.selected = !n.selected;
+		});
+		this._handleOnChange(this.attr('value'), onChange==true);
+	},
+
+	_onChange: function(/*Event*/ e){
+		this._handleOnChange(this.attr('value'), true);
+	},
+	
+	// for layout widgets:
+	resize: function(/* Object */size){
+		if(size){
+			dojo.marginBox(this.domNode, size);
+		}
+	},
+	
+	postCreate: function(){
+		this._onChange();
+	}
+});
+
+}
+
+if(!dojo._hasResource["nomad.widget.CheckmarkMenuItem"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["nomad.widget.CheckmarkMenuItem"] = true;
+/*
+
+        Copyright 2006-2008 OpenAjax Alliance
+
+        Licensed under the Apache License, Version 2.0 (the "License"); 
+        you may not use this file except in compliance with the License. 
+        You may obtain a copy of the License at
+        
+                http://www.apache.org/licenses/LICENSE-2.0
+
+        Unless required by applicable law or agreed to in writing, software 
+        distributed under the License is distributed on an "AS IS" BASIS, 
+        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+        See the License for the specific language governing permissions and 
+        limitations under the License.
+*/
+dojo.provide("nomad.widget.CheckmarkMenuItem");
+
+
+
+dojo.declare(
+        "nomad.widget.CheckmarkMenuItem",
+        [ dijit.MenuItem ],
+{
+        // summary
+        //      Extending dijit.MenuItem to allow a concept of a 'currently
+        //      selected' menu item from a group of menu items.  Similar to
+        //      a radio button.
+
+        // Bringing in the template string from Menu.js because I need to know
+        // what the value of @initChecked is.  @initChecked will only be honored during
+        // initialization, after that the attribute is ignored.  The last
+        // menu item with @initChecked set will be the one that is actually
+        // checked.
+        templateString:
+                 '<tr class="dijitReset nomadCheckboxMenuItem"'
+                +'dojoAttachEvent="onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick" initChecked="${initChecked}">'
+                +'<td class="dijitReset"><div class="dijitMenuItemIcon ${iconClass}" dojoAttachPoint="iconNode" ></div></td>'
+                +'<td tabIndex="-1" class="dijitReset dijitMenuItemLabel" dojoAttachPoint="containerNode" waiRole="menuitem"></td>'
+                +'<td class="dijitReset" dojoAttachPoint="arrowCell">'
+                        +'<div class="dijitMenuExpand" dojoAttachPoint="expand" style="display:none">'
+                        +'<span class="dijitInline dijitArrowNode dijitMenuExpandInner">+</span>'
+                        +'</div>'
+                +'</td>'
+                +'</tr>',
+
+        _menus: {},
+
+        _checked: null,
+
+        initChecked: null,
+
+        // some checkmark menu items want the checkmark to only indicate the
+        // last item selected and still want every click of that menu item
+        // to run its click handler
+        handleEveryClick: false,
+
+        startup: function() {
+          var menuId = this.getParent().id;
+          // have to remember parent id since the menu item may be disconnected
+          // from the parent before destroy() is called, esp on IE
+          this._parentId = menuId;
+          if (!this._menus[menuId]) {
+            this._menus[menuId] = new Array();
+          }
+          this._menus[menuId].push(this);
+          var checked = this.initChecked;
+          if (checked && typeof checked == "boolean") {
+            // if @initChecked is 'true' accept it, otherwise ignore all
+            // other values
+            this.setChecked(true);
+          } else {
+            this.setChecked(false);
+          }
+          this.inherited(arguments);
+        },
+
+        destroy: function() {
+          var menuId = this._parentId;
+          var menuItemArray = this._menus[menuId];
+          var arrayLength = menuItemArray ? menuItemArray.length : 0;
+          for (var i = 0; i < arrayLength; i++) {
+            if (menuItemArray[i] == this) {
+              menuItemArray.splice(i, 1);
+              if (!menuItemArray.length) {
+                this._menus[menuId] = null;
+              }
+              break;
+            }
+          }
+          this._parentId = null;
+          this.inherited(arguments);
+        },
+
+        setChecked: function(/* boolean */enableCheck) {
+          // return whether this call changed the checked state of the menuitem
+
+          // if we are changing the state of the menu item to unchecked, just
+          // remove the icon, otherwise we'll loop through all of the menu items
+          // and remove their checks before we enable the check for the menu
+          // item that we are enabling
+          if (enableCheck == this._checked) {
+            return false;
+          }
+          if (enableCheck == false) {
+            dojo.removeClass(this.iconNode, "nomadCheckedMenuItemIcon");
+          } else {
+            var menuId = this._parentId;
+            var menuItemArray = this._menus[menuId];
+            var arrayLength = menuItemArray ? menuItemArray.length : 0;
+            for (var i = 0; i < arrayLength; i++) {
+              if (menuItemArray[i] != this) {
+                menuItemArray[i].setChecked(false);
+              }
+            }
+            dojo.addClass(this.iconNode, "nomadCheckedMenuItemIcon");
+          }
+          this._checked = enableCheck;
+          return true;
+        },
+
+        _onClick: function() {
+          // If this menu item isn't already checked, check it.  If the item
+          // was already checked, don't call superclass otherwise onClick
+          // handler will get called when it doesn't need to be.  Keep in mind
+          // that setChecked needs to be called everytime here, so put it first.
+          if (this.setChecked(true) || this.handleEveryClick) {
+            this.inherited(arguments);
+          }
+        }
+
+});
+
+}
+
+if(!dojo._hasResource["nomad.widget.Date"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["nomad.widget.Date"] = true;
+/*
+
+        Copyright 2006-2008 OpenAjax Alliance
+
+        Licensed under the Apache License, Version 2.0 (the "License"); 
+        you may not use this file except in compliance with the License. 
+        You may obtain a copy of the License at
+        
+                http://www.apache.org/licenses/LICENSE-2.0
+
+        Unless required by applicable law or agreed to in writing, software 
+        distributed under the License is distributed on an "AS IS" BASIS, 
+        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+        See the License for the specific language governing permissions and 
+        limitations under the License.
+*/
+dojo.provide("nomad.widget.Date");
+
+
+
+
+
+dojo.declare(
+        "nomad.widget.Date",
+        [dijit.form.DateTextBox],
+{
+        // summary
+        //     Extending a dijit.form.DateTextBox to allow for showing a calendar
+        //     without having to use a popup (causes sizing issues in an iframe),
+        //     especially on IE
+
+        postCreate: function() {
+          this.inherited(arguments);
+
+          var tempNode = document.createElement('div');
+          tempNode.className = 'nomadErrorMsg';
+          this.errorMsg = this.domNode.parentNode.insertBefore(tempNode, this.domNode.nextSibling);
+          tempNode = document.createElement('div');
+          tempNode = this.domNode.parentNode.insertBefore(tempNode, this.errorMsg.nextSibling);
+          this.calendar = new dijit._Calendar({}, tempNode);
+
+          // override _onFocus to keep the default dojo calendar from popping
+          // up
+          this._onFocus = function(event) {};
+
+          // Only set the calendar value if there is a value to set it to.  It
+          // doesn't handle null dates very well.  By default it will show
+          // today's date.
+          if (this.value) {
+            this.calendar.setValue(this.value);
+          }
+          this.calendar.onChange = dojo.hitch(this, this.onCalendarChange);
+          this.onChange = dojo.hitch(this, this.onTextboxChange);
+          this.displayMessage = dojo.hitch(this, this.onTextboxInvalid);
+        },
+
+        // if this widget is created programmatically instead of using markup,
+        // then startup won't be called by default
+        startup: function() {
+          this.domNode.style.width = this.calendar.domNode.scrollWidth;
+        },
+
+        getValue: function() {
+          var value = this.inherited(arguments);
+          if (typeof value === 'undefined') {
+            // If dojo's DateTextBox can't parse the current date value, it
+            // will return 'undefined'.  Unfortunately it will do that when
+            // the current value is just an empty string.  Since empty strings
+            // are ok with us, we'll allow those back.
+            if (this.value == "") {
+              value = this.value;
+            }
+          }
+          return value;
+        },
+
+        setAttribute: function(attr, value) {
+          this.inherited(arguments);
+          if (attr == 'disabled') {
+            // XXX need to use an overlay with opacity set on it to 'disable'
+            // the calendar.  Or do something else to keep users from messing
+            // with it.
+          }
+//          this.calendar.setDisabled(disableInput);
+        },
+
+        setTextboxValue: function(value) {
+          this.setValue(value);
+        },
+
+        setCalendarValue: function(value) {
+          // Only set the calendar value if there is a value to set it to.  It
+          // doesn't handle null dates very well.  By default make it show
+          // today's date.
+          if (!value) {
+            value = new Date();
+          }
+          this.calendar.setValue(value);
+        },
+
+        onCalendarChange: function(/* Date */date) {
+          if (!this._settingCalendar) {
+            this._settingTextbox = true;
+            this.setTextboxValue(date);
+            this._settingTextbox = false;
+          }
+        },
+
+        onTextboxChange: function(/* String */value) {
+          if (this.isValid() && !this._settingTextbox) {
+            this._settingCalendar = true;
+            this.setCalendarValue(value);
+            this._settingCalendar = false;
+          }
+        },
+
+        onTextboxInvalid: function(/* String */value) {
+          this.errorMsg.innerHTML = value;
+        }
+});
+
+}
+
+if(!dojo._hasResource["nomad.widget.MashupDialog"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["nomad.widget.MashupDialog"] = true;
+/*
+
+        Copyright 2006-2008 OpenAjax Alliance
+
+        Licensed under the Apache License, Version 2.0 (the "License"); 
+        you may not use this file except in compliance with the License. 
+        You may obtain a copy of the License at
+        
+                http://www.apache.org/licenses/LICENSE-2.0
+
+        Unless required by applicable law or agreed to in writing, software 
+        distributed under the License is distributed on an "AS IS" BASIS, 
+        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+        See the License for the specific language governing permissions and 
+        limitations under the License.
+*/
+dojo.provide("nomad.widget.MashupDialog");
+
+
+
+
+dojo.declare(
+        "nomad.widget.MashupDialog",
+        [ dijit.Dialog ],
+{
+        // summary
+        //      Extending a dijit.Dialog to allow for rolling up and unrolling
+        //      the dialog
+
+//        templateString:
+//          '<div dojoType="dijit.Dialog" id="${id}" name="${id}"'
+//         +'     title="Properties" execute="dijit.byId(\'${id}\').hide();"'
+//         +'     refreshOnShow="true">'
+        _contentString: "",
+
+        postCreate: function() {
+          this.inherited(arguments);
+          this._contentString = '<div id="'+this.id+'_Contents" name="'+this.id+'_Contents"></div>'
+            +'<span id="'+this.id+'_Rollup" name="'+this.id+'_Rollup"'
+            +'     style="height: 50px; display: none;">'
+//            +'  <span id="'+this.id+'_RollupText" name="'+this.id+'_RollupText" style="float: left"></span>'
+            +'  <span id="'+this.id+'_RollupText" name="'+this.id+'_RollupText"></span>'
+            +'  <button id="'+this.id+'_RollupCancel"></button>'
+            +'</span>';
+
+          this.setContent(this._contentString);
+          var rollupCancel = dojo.byId(this.id+'_RollupCancel');
+          new dijit.form.Button({
+              label: "Cancel",
+              onClick: dojo.hitch(this, "rolldownContent")
+            }, rollupCancel);
+
+          dojo.connect(dojo.byId(this.id+"_RollupCancel"), "onclick", dojo.hitch(this, "rolldownContent"));
+          this._oldCoords = null;
+          mashupMaker.hub.subscribe( "nomad-propertyEditor-resize", this.contentsResized, this );
+        },
+
+        widgetsInTemplate: false,
+
+        execute: function() { this.hide(); },
+
+        getTitle: function() {
+          return this.titleNode.innerHTML;
+        },
+
+        setTitle: function(title) {
+          this.titleNode.innerHTML = title;
+        },
+
+        rollupContent: function(/* string */topicName, /* boolean */inputTopic) {
+          // hide the current property controls
+          this._oldCoords = dojo.coords(this.domNode, true);
+          this.domNode.style.top = '10px';
+          this.domNode.style.width = 'auto';
+          this.domNode.style.height = 'auto';
+
+          dojo.byId(this.id+'_Contents').style.display = 'none';
+
+          // set the proper text given the topicName and whether this property
+          // is looking to recieve this topic as input or to publish the topic
+          var rollupText = inputTopic ? "Receive " : "Send ";
+          rollupText += '"'+topicName+'"';
+          rollupText += inputTopic ? " from which widget?" : " to which widget?";
+          dojo.byId(this.id+'_RollupText').innerHTML = rollupText;
+
+          // display the rollup part of the dialog
+          dojo.byId(this.id+'_Rollup').style.display = 'inline';
+        },
+
+        rolldownContent: function() {
+          if (this._oldCoords) {
+            this.domNode.style.top = this._oldCoords.t+'px';
+            this.domNode.style.width = this._oldCoords.w+'px';
+            this.domNode.style.height = this._oldCoords.h+'px';
+            this._oldCoords = null;
+          }
+
+          // show the property controls again
+          dojo.byId(this.id+'_Contents').style.display = 'block';
+
+          // hide the rollup part of the dialog
+          dojo.byId(this.id+'_Rollup').style.display = 'none';
+
+          // notify subscribers that the user pressed the rolldown button
+          mashupMaker.hub.publish("nomad-dialog-rolldown", null);
+        },
+
+        contentsResized: function(event) {
+          var dialogContents = dojo.byId(this.id+'_Contents');
+          var gadgetContainer = dojo.query(".gadgetFrame", dialogContents)[0];
+          dialogContents.style.height = gadgetContainer.scrollHeight + "px";
+          dialogContents.style.width = gadgetContainer.scrollWidth + "px";
+          var coords = dojo.coords(this.domNode);
+          var dpCompStyle = dojo.style(dojo.query(".dijitDialogPaneContent", this.domNode)[0]);
+          var tbCompStyle = dojo.style(dojo.query(".dijitDialogTitleBar", this.domNode)[0]);
+          var pxPos = dpCompStyle.paddingLeft.indexOf('px');
+          if (pxPos == -1) {
+            pxPos = dpCompStyle.paddingLeft.indexOf('em');
+          }
+          var paddingLeft = parseInt(dpCompStyle.paddingLeft.substring(0, pxPos != -1 ? pxPos : 0));
+          var titlebar = dojo.query(".dijitDialogTitleBar", this.domNode)[0];
+          pxPos = dpCompStyle.paddingRight.indexOf('px');
+          if (pxPos == -1) {
+            pxPos = dpCompStyle.paddingRight.indexOf('em');
+          }
+          var paddingRight = parseInt(dpCompStyle.paddingRight.substring(0, pxPos != -1 ? pxPos : 0));
+          coords.w = gadgetContainer.scrollWidth+paddingLeft+paddingRight;
+          pxPos = dpCompStyle.paddingTop.indexOf('px');
+          if (pxPos == -1) {
+            pxPos = dpCompStyle.paddingTop.indexOf('em');
+          }
+          var tbpxPos = tbCompStyle.paddingTop.indexOf('px');
+          if (tbpxPos == -1) {
+            tbpxPos = tbCompStyle.paddingLeft.indexOf('em');
+          }
+          var paddingTop = parseInt(dpCompStyle.paddingTop.substring(0, pxPos != -1 ? pxPos : 0));
+          paddingTop += parseInt(tbCompStyle.paddingTop.substring(0, tbpxPos != -1 ? tbpxPos : 0));
+          pxPos = dpCompStyle.paddingBottom.indexOf('px');
+          if (pxPos == -1) {
+            pxPos = dpCompStyle.paddingBottom.indexOf('em');
+          }
+          tbpxPos = tbCompStyle.paddingBottom.indexOf('px');
+          if (tbpxPos == -1) {
+            tbpxPos = tbCompStyle.paddingBottom.indexOf('em');
+          }
+          var paddingBottom = parseInt(dpCompStyle.paddingBottom.substring(0, pxPos != -1 ? pxPos : 0));
+          paddingBottom += parseInt(tbCompStyle.paddingBottom.substring(0, tbpxPos != -1 ? tbpxPos : 0));
+          coords.h = gadgetContainer.scrollHeight+paddingTop+paddingBottom+titlebar.offsetHeight;
+
+          // can't use this.resize (dijit.dialog.resize) because it takes
+          // the changes and then shrinks them for some reason
+          this.domNode.style.height = coords.h + "px";
+          this.domNode.style.width = coords.w + "px";
+        }
+
+});
+
+}
+
+if(!dojo._hasResource["nomad.widget.MultiSelect"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["nomad.widget.MultiSelect"] = true;
+/*
+
+        Copyright 2006-2008 OpenAjax Alliance
+
+        Licensed under the Apache License, Version 2.0 (the "License"); 
+        you may not use this file except in compliance with the License. 
+        You may obtain a copy of the License at
+        
+                http://www.apache.org/licenses/LICENSE-2.0
+
+        Unless required by applicable law or agreed to in writing, software 
+        distributed under the License is distributed on an "AS IS" BASIS, 
+        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+        See the License for the specific language governing permissions and 
+        limitations under the License.
+*/
+dojo.provide("nomad.widget.MultiSelect");
+
+
+
+//
+
+dojo.declare(
+        "nomad.widget.MultiSelect",
+        [dijit.form.MultiSelect],
+{
+    // summary
+    //     Extending a dijit.form.MultiSelect to allow for pulling options
+    //     out of a store and to allow for user adding to the options list
+
+    templateString: "<table class='nomadMultiSelect' cellpadding='0' cellspacing='0'><tbody><tr><td><input dojoType='dijit.form.TextBox' dojoAttachPoint='textfield'></input></td></tr><tr><td><select multiple='true' dojoAttachPoint='containerNode,focusNode' dojoAttachEvent='onchange: _onChange'></select></td></tr></tbody></table>",
+
+    // by default only allow the items already defined in the list
+    unconstrained: false,
+
+    widgetsInTemplate: true,
+
+    // store: Object
+    //     Reference to data provider object used by this MultiSelect
+    store: null,
+
+    // _optionsArray: Object
+    //     List of options and their values, only really of use with an
+    //     unconstrained select
+    _optionsArray: null,
+
+    gotError: function(error, request) {
+      
+    },
+
+    _addOption: function(label, value) {
+      var option = document.createElement('option');
+      option.innerHTML = label;
+      option.setAttribute('value', value);
+      option = this.containerNode.appendChild(option);
+      if (this.unconstrained) {
+        this._optionsArray[label] = option;
+      }
+      return option;
+    },
+
+    gotItem: function(item, request) {
+      this._addOption(item.label, item.value);
+    },
+
+    postCreate: function() {
+      if (!this.unconstrained) {
+        this.textfield.domNode.style.display = 'none';
+      } else {
+        dojo.connect(this.textfield.domNode, "onkeypress", dojo.hitch(this, this._onKeyPress));
+        this._optionsArray = {};
+      }
+
+      if (this.store) {
+        this.store.fetch({
+          onItem: dojo.hitch(this, this.gotItem),
+          onError: dojo.hitch(this, this.gotItem)
+        });
+      }
+      this.inherited(arguments);
+    },
+
+    startup: function() {
+      if (this.unconstrained) {
+        var textBox = dojo.marginBox(this.textfield.domNode);
+        var selectBox = dojo.marginBox(this.containerNode);
+        if (textBox.w > selectBox.w) {
+          selectBox.w = textBox.w;
+          dojo.marginBox(this.containerNode, selectBox);
+        } else {
+          textBox.w = selectBox.w;
+          dojo.marginBox(this.textfield, textBox);
+        }
+      }
+    },
+
+    // If the user hits the 'enter' key, add the item in the textfield to the
+    // list of options.  The label and value will be identical, the value that
+    // is currently in the textfield.  Select that item after it is added to
+    // the list and then clear the textfield so that it is ready for any more
+    // input.
+    _onKeyPress: function(/*Event*/ event) {
+      //except for pasting case - ctrl + v(118)
+      if(event.altKey || (event.ctrlKey && event.charCode != 118)){
+        return;
+      }
+      if (event.keyCode == dojo.keys.ENTER) {
+        var currText = this.textfield.getValue();
+        var option = this._optionsArray[currText];
+        if (typeof option === 'undefined') {
+          option = this._addOption(currText, currText);
+        }
+        if (option) {
+          if (dojo.isIE) {
+            option.setAttribute('selected', true);
+          } else {
+            option.selected = true;
+          }
+          this.textfield.setValue('');
+        }
+      }
+    },
+
+    setTextboxValue: function(value) {
+      this.textfield.setValue(value);
+    },
+
+    getValue: function() {
+      var selectedOpts = [];
+      if (!(this.containerNode.selectedIndex < 0)) {
+        var options = this.containerNode.options;
+        for (var i = this.containerNode.selectedIndex; i < options.length; i++) {
+          var option = options[i];
+          if (option.selected) {
+            selectedOpts.push(option.value);
+          }
+        }
+      }
+      return selectedOpts;
+    },
+
+    setValue: function(value) {
+      // make sure we are passed an array
+      if (!(typeof value == 'object')) {
+          return;
+      }
+      var options = this.containerNode.options;
+      if (!options) {
+          return;
+      }
+
+      // Value could be an Array of values or it could be an associative array
+      // of values (what dojo.fromString produces when converting a json-ified
+      // array back from a string).  If the latter, just build a JS array to
+      // keep the code consistent.
+      var valueArray = value;
+      var isArray = value instanceof Array;
+      if (!isArray) {
+          valueArray = [];
+          var tempValue = null;
+          for( tempValue in value ) {
+              valueArray.push(value[tempValue]);
+          }
+      }
+
+      var optLen = options.length;
+      var valLen = valueArray.length;
+
+      // Look for all options with their value property in the list of values
+      // to select.  If the option value isn't on the list, make sure that it
+      // is deselected.  Have to check through all of the options because it is
+      // possible that more than one option has the same value.
+      var foundVals = {};
+      for (var i = 0; i < optLen; i++) {
+        var option = options[i];
+        if (dojo.isIE) {
+          option.setAttribute('selected', false);
+        } else {
+          option.selected = false;
+        }
+        for (var j = 0; j < valLen; j++) {
+          if (option.value == valueArray[j]) {
+            if (dojo.isIE) {
+              option.setAttribute('selected', true);
+            } else {
+              option.selected = true;
+            }
+            foundVals[option.value] = true;
+          }
+        }
+      }
+
+      if (this.unconstrained) {
+        for (var k = 0; k < valLen; k++) {
+          var tempVal = valueArray[k];
+          if (typeof foundVals[tempVal] === 'undefined') {
+            var option = this._addOption(tempVal, tempVal);
+            if (dojo.isIE) {
+              option.setAttribute('selected', true);
+            } else {
+              option.selected = true;
+            }
+          }
+        }
+      }
+    }
+
+});
+
+}
+
+if(!dojo._hasResource["nomad.widget.PaletteMenu"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["nomad.widget.PaletteMenu"] = true;
+/*
+
+        Copyright 2006-2008 OpenAjax Alliance
+
+        Licensed under the Apache License, Version 2.0 (the "License"); 
+        you may not use this file except in compliance with the License. 
+        You may obtain a copy of the License at
+        
+                http://www.apache.org/licenses/LICENSE-2.0
+
+        Unless required by applicable law or agreed to in writing, software 
+        distributed under the License is distributed on an "AS IS" BASIS, 
+        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+        See the License for the specific language governing permissions and 
+        limitations under the License.
+*/
+dojo.provide("nomad.widget.PaletteMenu");
+
+
+
+//
+
+
+
+dojo.declare(
+        "nomad.widget.PaletteMenu",
+        [ dijit.Menu ],
+{
+        // summary
+        //      Extending a dijit.Menu to allow for scroll buttons when the menu
+        //      extends beyond the client area of the browser
+
+        templateString:
+          '<table id="${id}" cellspacing="0" cellpadding="0" class="dijitMenu"><tbody><tr><td><button class="paletteScrollButton" dojoAttachPoint="scrollUpButton" dojoAttachEvent="onmousedown: scrollUp"><span class="dijitInline nomadToolbarIcon nomadIconScrollUp"></span></button></td></tr>' +
+          //'<tr><td>' + 
+          //'<div id="${id}_searchOptions" dojoType="nomad.widget.NorgiePaletteItem"' +
+          //     'class="paletteNorgie" title="Advanced Search Options" paletteId="${id}">' +
+          //'</div>' +
+          //'</td></tr>' +
+          '<tr><td><div dojoAttachPoint="menuViewport">' +
+            '<table class="dijit nomadInnerMenu dijitReset dijitMenuTable" dojoAttachPoint="menu" waiRole="menu" dojoAttachEvent="onkeypress:_onKeyPress" width="100%">' +
+                '<tbody class="dijitReset" dojoAttachPoint="containerNode"></tbody>'+
+            '</table>' +
+          '</div></td></tr>' +
+          '<tr><td><button class="paletteScrollButton" dojoAttachPoint="scrollDownButton" dojoAttachEvent="onmousedown: scrollDown"><span class="dijitInline nomadToolbarIcon nomadIconScrollDown"></span></button></td></tr></tbody></table>',
+
+        widgetsInTemplate: true,
+
+        startup: function() {
+          var menuViewportStyle = this.menuViewport.style;
+          menuViewportStyle.overflow = 'hidden';
+          // Need to set these relative positions to make IE happy with the
+          // overflow hidden style.  But setting menuViewport relative upsets
+          // Safari.  Ack!
+          if (dojo.isIE) {
+            menuViewportStyle.position = 'relative';
+          }
+          menuViewportStyle.height = '100%';
+          this.menuViewport.parentNode.style.position = 'relative';
+
+          this.inherited(arguments);
+          dojo.connect(window, 'onresize', dojo.hitch(this, 'resizePalette', false));
+        },
+
+        destroy: function() {
+          if (this._tooltip) {
+            this._tooltip.destroy();
+          }
+          this.inherited(arguments);
+        },
+
+        _sizeInitialized: false,
+
+        _getMenuItems: function() {
+          // this assumes that all menu items in this menu are
+          // nomad.widget.PaletteItem's
+          return dojo.query(".dijitMenuItem", this.domNode);
+        },
+
+        _tooltip: null,
+
+        setTooltip: function(tooltip) {
+          if (this._tooltip) {
+            this._tooltip.destroy();
+          }
+          this._tooltip = tooltip;
+        },
+
+        resizePalette: function(opening) {
+          // if we've already resized the palette to fit the browser
+          // we'd better reset the height style before we calculate again
+          if (!this._open && !opening) {
+            // If we got a resize and the palette isn't open, then it came from
+            // the browser resizing.  Make sure we recalc the next time
+            // we open the palette.
+            this._sizeInitialized = false;
+
+            // gotta make sure that the buttons are visible when the calculation
+            this.scrollUpButton.style.display = 'block';
+            this.scrollDownButton.style.display = 'block';
+            return;
+          }
+
+          var menuViewportStyle = this.menuViewport.style;
+          if (menuViewportStyle.height != '100%') {
+            menuViewportStyle.height = '100%';
+          }
+
+          // figure out if we need to show the scroll buttons and if so,
+          // resize the menu viewport so that everything fits
+          var menuCoords = dojo.coords(this.domNode, true);
+          var viewport = dijit.getViewport();
+          if (menuCoords.t + menuCoords.h < viewport.h) {
+            // the menu can fit in the viewport area of browser so we don't
+            // need to keep the scroll buttons visible
+            this.scrollUpButton.style.display = 'none';
+            this.scrollDownButton.style.display = 'none';
+          } else {
+            // Make sure that the buttons are visible, recalc menucoords if
+            // they weren't.  Enough to check just one since they appear and
+            // disappear in pairs.
+            if (this.scrollUpButton.style.display == 'none') {
+              this.scrollUpButton.style.display = 'block';
+              this.scrollDownButton.style.display = 'block';
+              menuCoords = dojo.coords(this.domNode, true);
+            }
+            var menubox = dojo.marginBox(this.menuViewport, null);
+            var controlsHeight = menuCoords.h - menubox.h;
+            menubox.h = viewport.h - viewport.t - controlsHeight - menuCoords.y;
+            dojo.marginBox(this.menuViewport, menubox);
+          }
+          this._sizeInitialized = true;
+        },
+
+        focusFirstItem: function() {
+          if (this.hasChildren()) {
+            this._getMenuItems()[0].focus();
+          }
+        },
+
+        onOpen: function() {
+          var browserHeight = dijit.getViewport().h;
+          if (!this._sizeInitialized) {
+            this.resizePalette(true);
+          }
+          this.inherited(arguments);
+          this._open = true;
+        },
+
+        onClose: function() {
+          var currFocus = this.focusedChild;
+          if (currFocus && !currFocus._blur) {
+            this.focusFirstItem();
+          }
+          this.inherited(arguments);
+          if (this._tooltip) {
+            this._tooltip.close();
+          }
+          this._open = false;
+        },
+
+        scrollUp: function(event) {
+          this.focusPrev();
+          dojo.stopEvent(event);
+        },
+
+        scrollDown: function(event) {
+          this.focusNext();
+          dojo.stopEvent(event);
+        }
+
+});
+
+dojo.declare(
+        "nomad.widget.PaletteItem",
+        [ dijit.MenuItem ],
+{
+        // summary
+        //      Extending a dijit.MenuItem to allow for icons that when clicked
+        //      will run the palette item, get more info for the palette item,
+        //      or bookmark the palette item
+
+        // Make 3 columns
+        //   icon, label, and expand arrow (BiDi-dependent) indicating sub-menu
+        templateString:
+                 '<tr class="dijitReset dijitMenuItem nomadPaletteItem"'
+                +'dojoAttachEvent="onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick">'
+                +'<td><table><tbody><tr><td><table><tbody><tr>'
+                +'<td class="dijitReset"><div class="dijitMenuItemIcon ${iconClass}" dojoAttachPoint="iconNode" dojoAttachEvent="ondijitclick:_startDND "></div></td>'
+                +'<td><div class="dijitMenuItemIcon ${runIconClass}" dojoAttachEvent="ondijitclick:_runGadget"/></td>'
+                +'<td tabIndex="-1" class="dijitReset dijitMenuItemLabel" dojoAttachPoint="containerNode" waiRole="menuitem"></td>'
+                +'</tr></tbody></table></td>'
+                +'</tr></tbody></table></td>'
+                +'</tr>',
+
+        // runIconClass: String
+        //      class to apply to div in button to make it display an icon
+        //      for the action to display a sample of the palette item
+        runIconClass: "",
+
+        // bookmarkIconClass: String
+        //      class to apply to div in button to make it display an icon
+        //      for the action to bookmark the palette item
+        bookmarkIconClass: "",
+
+        // infoIconClass: String
+        //      class to apply to div in button to make it display an icon
+        //      for the action to retrieve more info on the palette item
+        infoIconClass: "",
+
+        // itemUrl: String
+        //      the url of the widget represented by this palette item
+        itemUrl: "",
+
+        _runGadget: function(event) {
+          var mywindow = window.open(OpenAjax.widget.baseURI+'standaloneGadget.php?specURL='+this.itemUrl, 'samplewindow', 'width=600,height=500,resizable=yes,scrollbars=yes');
+          dojo.stopEvent(event);
+          return false;
+        },
+
+        _startDND: function(event) {
+          mashupMaker.startDND(event, this);
+          dojo.stopEvent(event);
+          return false;
+        },
+
+        focus: function() {
+          this.inherited(arguments);
+          if (window.ActiveXObject) {
+            dojo.addClass(this.domNode, 'dijitMenuItemHoverIE');
+          }
+          
+          dijit.scrollIntoView(this.domNode);
+        },
+        
+        _blur: function() {
+          this.inherited(arguments);
+          if (window.ActiveXObject) {
+            dojo.removeClass(this.domNode, 'dijitMenuItemHoverIE');
+          }
+        },
+
+        setImage: function(path) {
+          this.iconNode.style.backgroundImage = path;
+        }
+
+});
+
+dojo.declare(
+        "nomad.widget.NorgiePaletteItem",
+        [ dijit.TitlePane ],
+{
+        // summary
+        //      Extending a dijit.MenuItem to allow for icons that when clicked
+        //      will run the palette item, get more info for the palette item,
+        //      or bookmark the palette item
+
+        templateString:
+                  '<div class="dijitTitlePane">' +
+                    '<div dojoAttachEvent="onclick:toggle,onkeypress: _onTitleKey,onfocus:_handleFocus,onblur:_handleFocus" tabindex="0"' +
+                        'waiRole="button" class="dijitTitlePaneTitle" dojoAttachPoint="focusNode">' +
+                      '<div dojoAttachPoint="arrowNode" class="dijitInline dijitArrowNode"><span dojoAttachPoint="arrowNodeInner" class="dijitArrowNodeInner"></span></div>' +
+                      '<div dojoAttachPoint="titleNode" class="dijitTitlePaneTextNode"></div>' +
+                    '</div>' +
+                    '<div class="dijitTitlePaneContentOuter" dojoAttachPoint="hideNode">' +
+                      '<div class="dijitReset" dojoAttachPoint="wipeNode">' +
+                        '<div class="dijitTitlePaneContentInner" dojoAttachPoint="containerNode" waiRole="region" tabindex="-1">' +
+                          "<!-- nested divs because wipeIn()/wipeOut() doesn't work right on node w/padding etc.  Put padding on inner div. -->" +
+                        '</div>' +
+                      '</div>' +
+                    '</div>' +
+                  '</div>',
+
+        _contentString: "",
+
+        widgetsInTemplate: false,
+
+        postCreate: function() {
+          this.inherited(arguments);
+          this._contentString =
+             '<table><tr>'
+//            +'<td><label for="'+this.id+'_widgetName">widget name</label></td>'
+//            +'<td><input id="'+this.id+'_widgetName" name="'+this.id+'_widgetName" dojoType="dijit.form.CheckBox"/></td>'
+//            +'</tr>'
+//            +'<td><label for="'+this.id+'_widgetTags">widget tags</label></td>'
+//            +'<td><input id="'+this.id+'_widgetTags" name="'+this.id+'_widgetTags" dojoType="dijit.form.CheckBox"/></td>'
+//            +'</tr>'
+//            +'<td><label for="'+this.id+'_widgetDescr">widget description</label></td>'
+//            +'<td><input id="'+this.id+'_widgetDescr" name="'+this.id+'_widgetDescr" dojoType="dijit.form.CheckBox"/></td>'
+//            +'</tr>'
+//            +'<td><label for="'+this.id+'_widgetPropDescr">widget property description</label></td>'
+//            +'<td><input id="'+this.id+'_widgetPropDescr" name="'+this.id+'_widgetPropDescr" dojoType="dijit.form.CheckBox"/></td>'
+//            +'</tr>'
+            +'<td><label for="'+this.id+'_repositoryList">Repositories:</label></td></tr>'
+            +'<tr><td colspan="2">'
+            +'<select id="'+this.id+'_repositoryList" name="'+this.id+'_repositoryList"  size="3" multiple>'
+            +'</select>'
+            +'</td></tr><td colspan="2">'
+            +'<button dojoType="dijit.form.Button" iconClass="nomadToolbarIcon nomadIconRefresh" onclick="searchRepositories">Refresh Search Results</button>'
+            +'</td></tr></table>';
+          this.setContent(this._contentString);
+          if (this.paletteId.length > 0) {
+            this._palette = dijit.byId(this.paletteId);
+          }
+          mashupMaker.getRepositoryList(dojo.hitch(this, this.buildRepositoryList));
+        },
+
+        // id of the palette that contains this norgie
+        paletteId: "",
+
+        // palette widget that contains this norgie.  Found during
+        // initialization using paletteId
+        _palette: null,
+
+        toggle: function() {
+          this.inherited(arguments);
+          if (this._palette) {
+            setTimeout(dojo.hitch(this._palette, 'resizePalette', false), this.duration);
+          }
+        },
+
+        buildRepositoryList: function(list) {
+          if (!list || list.length < 1) {
+            return;
+          }
+          var repositorySelect = dojo.query("select", this.domNode)[0];
+          while (repositorySelect.length > 0) {
+            repositorySelect.remove(0);
+          }
+          for (var i = 0; i < list.length; i++) {
+            var repository = list[i];
+            var option = new Option(repository.name, repository.url, false, false);
+            if (i == 0) option.selected = true;
+            repositorySelect.options[i] = option;
+          }
+        },
+
+        getSelectedRepositories: function() {
+          var list = dojo.byId(this.id+'_repositoryList');
+          var selected = new Array();
+          for (var i = 0; i < list.options.length; i++) {
+            var option = list.options[i];
+            if (option.selected) {
+              selected.push(option.value);
+            }
+          }
+          return selected;
+        }
+
+});
+
+dojo.declare(
+        "nomad.widget.PaletteTooltip",
+        [ dijit.Tooltip ],
+{
+        // summary
+        //      Extending dijit.Tooltip will allow us to use only one tooltip
+        //      to display the abbreviated information on each palette item.
+        //      This will work because when the tooltip is opened, we'll gather
+        //      the description from the palette item that is enclosing the
+        //      target of the tooltip (the information icon displayed on the
+        //      currently hovered palette item).
+
+        open: function(target) {
+          var paletteItem = dijit.getEnclosingWidget(target);
+          this.label = "description for: "+paletteItem.label;
+          this.inherited(arguments);
+        }
+});
+
+}
+
+if(!dojo._hasResource["nomad.widget.WiringDropDownButton"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["nomad.widget.WiringDropDownButton"] = true;
+/*
+
+        Copyright 2006-2008 OpenAjax Alliance
+
+        Licensed under the Apache License, Version 2.0 (the "License"); 
+        you may not use this file except in compliance with the License. 
+        You may obtain a copy of the License at
+        
+                http://www.apache.org/licenses/LICENSE-2.0
+
+        Unless required by applicable law or agreed to in writing, software 
+        distributed under the License is distributed on an "AS IS" BASIS, 
+        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+        See the License for the specific language governing permissions and 
+        limitations under the License.
+*/
+dojo.provide("nomad.widget.WiringDropDownButton");
+
+//
+
+
+
+dojo.declare(
+        "nomad.widget.WiringDropDownButton",
+        [ dijit.form.DropDownButton ],
+{
+        // summary
+        //      Extending a dijit.form.DropDownButton for our propertyeditor
+        //      so that the drop down menu is created automatically based on
+        //      the state of the corresponding property.
+
+        // IE has a problem with showLabel = false, so need to have code here
+        // to show and hide the label node depending on whether the label
+        // has text or not.
+
+        templateString:
+          '<div class="wiringButton dijit dijitLeft dijitInline"'
+         +'  dojoAttachEvent="onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse,onclick:_onDropDownClick,onkeydown:_onDropDownKeydown,onblur:_onDropDownBlur,onkeypress:_onKey"'
+         +'  ><div class="dijitRight">'
+         +'  <button class="dijitStretch dijitButtonNode dijitButtonContents" type="${type}"'
+         +'    dojoAttachPoint="focusNode,titleNode" waiRole="button" waiState="haspopup-true,labelledby-${id}_label"'
+         +'    ><div class="dijitInline ${iconClass}" dojoAttachPoint="iconNode"></div'
+         +'    ><span class="dijitButtonText" dojoAttachPoint="containerNode,popupStateNode"'
+         +'    id="${id}_label">${label}</span'
+         +'    ><span dojoAttachPoint="arrowNode" class="dijitA11yDownArrow">&#9660;</span>'
+         +'  </button>'
+         +'</div></div>',
+
+        // behave like a normal button...no dropdown menu, no down arrow, etc
+        mimicButton: false,
+
+        // this button is for wiring input into the property
+        wiringInput: true,
+
+        // The property editor that contains this wiring button.  We can't
+        // assume that we can find the property editor through the default
+        // property dialog box since the gadget might embed the property editor
+        // inside the gadgets content mode="edit" node.
+        propertyEditor: null,
+        
+        // Reference to the parent window's MashupMaker instance
+        mm: null,
+
+        setLabel: function(/*String*/ content) {
+          // IE has a problem with showLabel = false, so need to have this
+          // override to make sure
+          if (content && content.length) {
+            this.containerNode.style.display = 'inline';
+          }
+          this.inherited(arguments);
+        },
+
+        postCreate: function() {
+          this.inherited(arguments);
+          var property = this.property;
+          if (!property) {
+            return;
+          }
+
+          var topic = this.property.topic();
+          var defaultTopic = this.property.defaultTopic();
+          // setup the icon to appear on the button
+          this._setIcon(topic, defaultTopic, this.property.getSingleBoundGadget());
+          if (this.mimicButton) {
+            this.arrowNode.style.display = 'none';
+            dojo.connect(this.domNode, 'onclick', this, 'onClick');
+          } else {
+            // create the menu to display if the button is clicked
+            var menu = this._createMenu(property, topic, defaultTopic);
+            this.dropDown = menu;
+          }
+          dojo.connect(this.domNode, "onmouseenter", this, "onHover");
+          dojo.connect(this.domNode, "onmouseleave", this, "onUnhover");
+          if (!this.label) {
+            this.containerNode.style.display = 'none';
+          }
+        },
+
+        refresh: function(/* boolean */retainCachedValues) {
+          // Can be called by the property editor to make sure that the icon
+          // on the button is correct.  Small price to pay to keep from
+          // blowing the button away and creating a new one.
+
+          if (!this.wiringInput) {
+            // the output button doesn't change its icon and has no dropdown
+            // menu to update so just bow out gracefully
+            return;
+          }
+          var topic = "";
+          var singleBoundGadget = null;
+          if (typeof retainCachedValues === "undefined" || !retainCachedValues) {
+            topic = this.property.topic();
+            this._newTopic = null;
+            this._singleBoundGadget = null;
+            singleBoundGadget = this.property.getSingleBoundGadget();
+          } else {
+            topic = this._newTopic != null ? this._newTopic : this.property.topic();
+            singleBoundGadget = this._singleBoundGadget ? this._singleBoundGadget : this.property.getSingleBoundGadget();
+          }
+          var defaultTopic = this.property.defaultTopic();
+          this._setIcon(topic, defaultTopic, singleBoundGadget);
+
+          // Resync the dropdown menu in case the user made changes and then
+          // cancelled them.
+          var menuitems = this.dropDown.getChildren();
+          var setChecked = false;
+          if (menuitems && menuitems.length > 0) {
+            for (var index = 0; index < menuitems.length; index++) {
+              switch (index) {
+                case 0:
+                  // multi bound
+                  setChecked = (topic == defaultTopic && !singleBoundGadget);
+                  break;
+                case 1:
+                  // unbound
+                  setChecked = (!topic || topic == "");
+                  break;
+                case 2:
+                  // single bound
+                  setChecked = (topic && !!singleBoundGadget);
+              }
+              if (setChecked) {
+                menuitems[index].setChecked(true);
+                break;
+              }
+            }
+          }
+        },
+
+        _startWiringProperty: function() {
+          this.onUnhover();
+          var topic = "";
+          if (this.wiringInput) {
+            topic = this._newTopic ? this._newTopic : this.property.topic();
+          } else {
+            topic = this.property.defaultTopic();
+          }
+          this.propertyEditor.wiringSessionStarting(this, topic);
+          var wiringManager = this.mm.getWiringManager();
+          var that = this;
+          var callback = function( success, subHandle ) {
+              if ( !success ) {
+                  // XXX handle error
+                  alert( "wiring complete subscribe failed" );
+                  return;
+              }
+              that._connectListener = subHandle;
+          };
+          this.mm.hub.subscribe("nomad-wiring-property-complete", callback, dojo.hitch(this, this.onWiringComplete) );
+          wiringManager.wirePropertyToGadget(this.property, this.wiringInput);
+        },
+
+        onClick: function() {
+          this._startWiringProperty();
+        },
+
+        onWiringCancelled: function(/* event */event) {
+          this.propertyEditor.wiringSessionCompleting(true);
+          var callback = function( success, subHandle ) {};
+          this._connectListener.unsubscribe(callback);
+          this._connectListener = null;
+          var wiringManager = this.mm.getWiringManager();
+          wiringManager.stopWiringProperty();
+          this.refresh(true);
+        },
+
+        onWiringComplete: function(/* event */event) {
+          var callback = function( success, subHandle ) {};
+          this._connectListener.unsubscribe(callback);
+          this._connectListener = null;
+          this.propertyEditor.wiringSessionCompleting(false);
+          if (this.wiringInput) {
+            // if the user requested a change to this property's wiring,
+            // remember it until the change is committed
+            var wiringManager = this.mm.getWiringManager();
+            var changeObj = wiringManager.getWiringChange(this.property, this.wiringInput);
+            if (changeObj) {
+              this._newTopic = changeObj.newTopic;
+              this._singleBoundGadget = changeObj.publishingGadget.getId();
+              var controlId = this.id.substring(0, this.id.indexOf('_InputBinding'));
+              this.propertyEditor.hideDefaultControl(controlId, this._newTopic, this.property.defaultTopic(), changeObj.publishingGadget);
+              this._setIcon(this._newTopic, this.property.defaultTopic(), changeObj.publishingGadget);
+            }
+          }
+        },
+
+//        widgetsInTemplate: false,
+//
+//        property: null,
+//
+        _newTopic: null,
+        _singleBoundGadget: null,
+        label: "",
+        _setIcon: function(/*string*/ topic, /*string*/ defaultTopic, /*gadget*/singleBindingGadget) {
+          var bindingClass = "nomadToolbarIcon nomadIconNoBinding";
+          if (this.wiringInput) {
+            if (topic && topic.length > 0) {
+              if (singleBindingGadget) {
+                bindingClass = "nomadToolbarIcon nomadIconSingleBinding";
+              } else if (topic == defaultTopic) {
+                bindingClass = "nomadToolbarIcon nomadIconMultipleBinding";
+              }
+            }
+          } else {
+            // since published topics go to everyone, always set the icon to
+            // be multiple binding
+            bindingClass = "nomadToolbarIcon nomadIconMultipleBinding";
+          }
+          this.iconNode.className = bindingClass;
+        },
+        _createMenu: function(/*GadgetProperty*/ property, /*string*/ topic, /*string*/ defaultTopic) {
+          var menu = new dijit.Menu({id: property.getGadget().getId()+'_'+property.name()+'_wiringMenu'});
+          if (!menu) {
+            return null;
+          }
+
+          // assign menuitem.initChecked prior to menu.startup()
+          var singleBoundGadget = property.getSingleBoundGadget();
+          var menuitem = null;
+          if (defaultTopic && defaultTopic.length) {
+            menuitem = new nomad.widget.CheckmarkMenuItem({
+                label: 'Listen for all '+defaultTopic+' topics',
+                onClick: dojo.hitch(this, this._wireDefaultTopics)
+              });
+            menuitem.initChecked = (topic == defaultTopic && !singleBoundGadget);
+            menu.addChild(menuitem);
+          }
+          menuitem = new nomad.widget.CheckmarkMenuItem({
+              label: 'Listen for no topics',
+              onClick: dojo.hitch(this, this._wireNoTopics)
+            });
+          menuitem.initChecked = (!topic || topic == "");
+          menu.addChild(menuitem);
+          menuitem = new nomad.widget.CheckmarkMenuItem({
+              label: 'Bind to one widget...',
+              handleEveryClick: true,
+              onClick: dojo.hitch(this, this._wireOneSourceTopic)
+            });
+          menuitem.initChecked = (topic && !!singleBoundGadget);
+          menu.addChild(menuitem);
+          menu.startup();
+          return menu;
+        },
+
+        _wireDefaultTopics: function(/*event*/ event) {
+          var prevTopic = this._newTopic != null ? this._newTopic : this.property.topic();
+          this._newTopic = this.property.defaultTopic();
+          this._singleBoundGadget = null;
+          var controlId = this.id.substring(0, this.id.indexOf('_InputBinding'));
+          this.propertyEditor.hideDefaultControl(controlId, this._newTopic, this._newTopic, null);
+          this._setIcon(this._newTopic, this._newTopic, null);
+          this.mm.getWiringManager().registerWiringChange(this.property, this._newTopic, prevTopic, null, this.wiringInput);
+        },
+        _wireNoTopics: function(/*event*/ event) {
+          var prevTopic = this._newTopic != null ? this._newTopic : this.property.topic();
+          this._newTopic = "";
+          this._singleBoundGadget = null;
+          var controlId = this.id.substring(0, this.id.indexOf('_InputBinding'));
+          this.propertyEditor.showDefaultControl(controlId, this.property);
+          this._setIcon(this._newTopic, this.property.defaultTopic(), null);
+          this.mm.getWiringManager().registerWiringChange(this.property, this._newTopic, prevTopic, null, this.wiringInput);
+        },
+        _wireOneSourceTopic: function(/*event*/ event) {
+          this._startWiringProperty();
+        },
+
+        destroy: function() {
+          if (this.dropDown) {
+            this.dropDown.destroyRecursive();
+            this.dropDown = null;
+          }
+          if (this._connectListener) {
+            var callback = function( success, subHandle ) {};
+            this._connectListener.unsubscribe(callback);
+            this._connectListener = null;
+          }
+          this._singleBoundGadget = null;
+          this.inherited(arguments);
+        },
+
+        onHover: function(/*event*/ event) {
+          var wiringManager = this.mm.getWiringManager();
+          var topic = this._newTopic != null ? this._newTopic : this.property.topic();
+          var singleBoundGadget = this._singleBoundGadget ? this._singleBoundGadget: this.property.getSingleBoundGadget();
+          // don't bother with the highlighting logic if this property neither
+          // publishes nor listens to a topic
+          if (topic && topic.length) {
+            if (singleBoundGadget) {
+              var gadgets = new Array();
+              gadgets[singleBoundGadget] = this.mm.getWidgetModelFromID(singleBoundGadget);
+              wiringManager.highlightGadgets(gadgets, topic, this.wiringInput);
+            } else {
+              wiringManager.highlightTopic(topic, this.wiringInput, this.property.getGadget());
+            }
+          }
+        },
+        onUnhover: function(/*event*/ event) {
+          if (!this._connectListener) {
+            // don't mess with topic highlighting if wiring is in progress
+            var wiringManager = this.mm.getWiringManager();
+            wiringManager.unhighlightTopic();
+          }
+        }
+
+});
+
+}
+
+
+dojo.i18n._preloadLocalizations("dojo.nls.refimpldojo", ["ROOT","ar","ca","cs","da","de","de-de","el","en","en-gb","en-us","es","es-es","fi","fi-fi","fr","fr-fr","he","he-il","hu","it","it-it","ja","ja-jp","ko","ko-kr","nl","nl-nl","no","pl","pt","pt-br","pt-pt","ru","sk","sl","sv","th","tr","xx","zh","zh-cn","zh-tw"]);
diff --git a/UNGProject/gadgets/sample/colorpalette_oam.xml b/UNGProject/gadgets/sample/colorpalette_oam.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0d2f804bd2d1e33de39bbed5dc45895680bea78a
--- /dev/null
+++ b/UNGProject/gadgets/sample/colorpalette_oam.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+        Copyright 2006-2008 OpenAjax Alliance
+
+        Licensed under the Apache License, Version 2.0 (the "License"); 
+        you may not use this file except in compliance with the License. 
+        You may obtain a copy of the License at
+        
+                http://www.apache.org/licenses/LICENSE-2.0
+
+        Unless required by applicable law or agreed to in writing, software 
+        distributed under the License is distributed on an "AS IS" BASIS, 
+        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+        See the License for the specific language governing permissions and 
+        limitations under the License.
+-->
+<widget name="ColorPalette" id="http://openajax.org/samples/widgets/colorpalette"
+		spec="1.0" width="208" height="148"
+		xmlns="http://openajax.org/metadata">
+
+    <requires>
+		<library name="dojo" version="1.3" src="http://ajax.googleapis.com/ajax/libs/dojo/1.3/">
+            <preload>
+				djConfig = { isDebug: false, parseOnLoad: false, afterOnLoad: true };
+			</preload>
+		    <require type="javascript" src="dojo/dojo.xd.js"/>
+		    <require type="css" src="dojo/resources/dojo.css"/>
+		    <require type="css" src="dijit/themes/dijit.css"/>
+		    <require type="css" src="dijit/themes/dijit_rtl.css"/>
+		    <require type="css" src="dijit/themes/tundra/ColorPalette.css"/>
+		</library>
+    </requires>
+
+  <properties>
+    <property name='color' datatype='String' defaultValue="#ffffff" sharedAs='color'/>
+    <!-- publish='true' -->
+  </properties>
+  
+    <javascript location='afterContent'>
+		dojo.require("dijit.ColorPalette");
+
+      	dojo.addOnLoad(function(){
+			new dijit.ColorPalette(
+                    {   "class": "tundra",
+                        onChange: function( color ) {
+                            OpenAjax.widget.byId('__WID__').OpenAjax.setPropertyValue( 'color', color );
+                        }
+                    },
+                    "__WID__palette"
+            );
+		});
+    </javascript>
+
+    <content>
+      <![CDATA[
+          <div class="tundra" style="background-color:#f5f5f5" >
+	        <span ID='__WID__palette' dojoType="dijit.ColorPalette">
+            </span>
+          </div> 
+      ]]>      
+    </content>
+</widget>
diff --git a/UNGProject/gadgets/sample/dateListener.oam.xml b/UNGProject/gadgets/sample/dateListener.oam.xml
new file mode 100644
index 0000000000000000000000000000000000000000..95eaa02270c272e8c4624d99bce63bc2a290b62d
--- /dev/null
+++ b/UNGProject/gadgets/sample/dateListener.oam.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+        Copyright 2006-2008 OpenAjax Alliance
+
+        Licensed under the Apache License, Version 2.0 (the "License"); 
+        you may not use this file except in compliance with the License. 
+        You may obtain a copy of the License at
+        
+                http://www.apache.org/licenses/LICENSE-2.0
+
+        Unless required by applicable law or agreed to in writing, software 
+        distributed under the License is distributed on an "AS IS" BASIS, 
+        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+        See the License for the specific language governing permissions and 
+        limitations under the License.
+-->
+<widget name="DateListener" id="http://openajax.org/samples/widgets/DateListener"
+		spec="1.0" version='0.9' width="300" height="24" sandbox="true"
+		xmlns="http://openajax.org/metadata">
+    <description>This is a test widget that tests the UI representation of various parts of the OAA spec</description>
+    <properties>
+      <property name="date" datatype="Date" defaultValue="" sharedAs="date"></property>
+<!--
+      <property name="subscribedDate" datatype="Date" defaultValue="" readonly="false" sharedAs="date">
+        // subscribe="true"
+        <description>last date published by another gadget</description>
+      </property>
+      <property name="publishedDate" datatype="String" defaultValue="" readonly="false" hidden="false" sharedAs="datestring">
+        // publish="true" 
+        <description>when this value is changed, this date will be published to other gadgets</description>
+      </property>
+      <property name="hiddenDate" datatype="String" defaultValue="" readonly="false" hidden="true" sharedAs="datestring">
+        // publish="true"
+        <description>when this value is changed, this date will be published to other gadgets</description>
+      </property>
+-->
+    </properties>
+
+    <content>
+    <![CDATA[
+        <script>
+            var w__WID__ = OpenAjax.widget.byId("__WID__");
+            
+            w__WID__.onLoad = function() {
+                document.getElementById("__WID__date").value = this.OpenAjax.getPropertyValue( "date" );
+            };
+            
+            w__WID__.handleClick = function() {
+//                alert("click!");
+            };
+            
+            w__WID__.handleChange = function() {
+                this.OpenAjax.setPropertyValue( "date", document.getElementById("__WID__date").value );
+            };
+            
+            w__WID__.onChangeDate = function( event ) {
+                document.getElementById("__WID__date").value = event.newValue;
+            };
+        </script>
+        
+        <label id="__WID__date_label" for="__WID__date" style="border: 1px solid red;">date last broadcast: </label>
+        <input id="__WID__date" name="__WID__date" onclick="OpenAjax.widget.byId('__WID__').handleClick();" onChange="OpenAjax.widget.byId('__WID__').handleChange();"/>
+    ]]>
+    </content>
+</widget>
diff --git a/UNGProject/gadgets/toolbar.js b/UNGProject/gadgets/toolbar.js
new file mode 100644
index 0000000000000000000000000000000000000000..3bf3c2194b3f5c55c4613f9bda619ea8a64c8958
--- /dev/null
+++ b/UNGProject/gadgets/toolbar.js
@@ -0,0 +1,333 @@
+/*
+
+        Copyright 2006-2008 OpenAjax Alliance
+
+        Licensed under the Apache License, Version 2.0 (the "License"); 
+        you may not use this file except in compliance with the License. 
+        You may obtain a copy of the License at
+        
+                http://www.apache.org/licenses/LICENSE-2.0
+
+        Unless required by applicable law or agreed to in writing, software 
+        distributed under the License is distributed on an "AS IS" BASIS, 
+        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+        See the License for the specific language governing permissions and 
+        limitations under the License.
+*/
+
+var toolbarInit;
+var retrieveMyStuff;
+var searchRepositories;
+
+(function(){
+
+  toolbarInit = function()
+  {
+    dojo.require("dojo.parser");
+    dojo.require("dojo.data.ItemFileReadStore");
+    dojo.require("dijit.form.Button");
+    dojo.require("dijit.form.FilteringSelect");
+    dojo.require("dijit.form.TextBox");
+    dojo.require("dijit.form.ValidationTextBox");
+    dojo.require("dijit.Menu");
+    dojo.require("dijit.Toolbar");
+    dojo.require("dijit.TitlePane");
+//    dojo.registerModulePath("nomad", "../../../nomad");
+    dojo.require("nomad.widget.PaletteMenu");
+    dojo.require("nomad.widget.CheckmarkMenuItem");
+
+    dojo.addOnLoad(function(){
+      var toolbar = dojo.byId('mashupToolbarContainer');
+      dojo.parser.parse(toolbar);
+//      toolbarOffsetY = toolbar.offsetTop + toolbar.offsetHeight + 10;
+      
+      // disable the "Save" and "Share" menu items if we didn't load from a page
+      if ( mashupMaker.pageName == '' ) {
+          dijit.byId( 'save' ).setDisabled( true );
+          dijit.byId( 'share' ).setDisabled( true );
+      }
+      var searchDropDown = dojo.byId( 'searchResults' );
+      dojo.connect(searchDropDown, 'onclick', null, populateDropDown);
+    });
+  }
+
+  var __firstSearch = true;
+
+   function populateDropDown() {
+       if ( __firstSearch ) {
+           window.retrieveMyStuff();
+           __firstSearch = false;
+       }
+   }
+
+  retrieveMyStuff = function() {
+    var resourceUri = 'gadgets.html';
+    var bindArgs = {
+        handleAs: 'json',
+        url:  resourceUri,
+        sync: false,
+        load: function(response) {
+            buildPaletteFromSearchResults(response);
+        },
+        error: function(error, request) {
+            alert('Search Error: \n'+error);
+        }
+    };
+    dojo.xhrGet(bindArgs);
+  }
+
+  searchRepositories = function(event) {
+    if (event.keyCode != 13 && event.type != 'click') {
+        return;
+    }
+    var searchTerms = dojo.byId('widgetSearchTerms').value;
+      if ( searchTerms == "Enter widget search terms" ) {
+          searchTerms = "";
+      }
+    var resourceUri = 'gadgets.html?terms='+searchTerms;
+    var advancedSearch = dijit.byId('searchResultsMenu_searchOptions');
+    var selectedRepositories = advancedSearch.getSelectedRepositories();
+    for (var i = 0; i < selectedRepositories.length; i++) {
+      resourceUri += "&repos[]=" + encodeURIComponent(selectedRepositories[i]);
+    }
+    var bindArgs = {
+        handleAs: 'json',
+        url:  resourceUri,
+        sync: true,
+        load: function(response) {
+            buildPaletteFromSearchResults(response);
+        },
+        error: function(error, request) {
+            alert('Search Error: \n'+error);
+        }
+    };
+    dojo.xhrGet(bindArgs);
+
+  }
+
+  function buildPaletteFromSearchResults(response) {
+      var temp = '';
+      var searchResults = dojo.byId('searchResultsMenu');
+      var searchResultsWidget = dijit.byId('searchResultsMenu');
+
+      // remove all of the previous search results
+      dojo.query('*[id^="searchResults_foundWidget"]').forEach(
+        function(itemFromMenu) {
+          var widget = dijit.byId(itemFromMenu.id);
+          if (widget) {
+            searchResultsWidget.removeChild(widget);
+            widget.destroyRecursive();
+          }
+        }
+      );
+      dojo.query('*[id^="searchResults_menuSeparator"]').forEach(
+        function(itemFromMenu) {
+          var widget = dijit.byId(itemFromMenu.id);
+          if (widget) {
+            searchResultsWidget.removeChild(widget);
+            widget.destroyRecursive();
+          }
+        }
+      );
+
+      var tooltipConnectIds = [];
+      for (var i = 0; i < response.length; i++) {
+          var opt = response[i];
+          var labelstr, url;
+
+          // insert the menu separator first
+          var menuItemWidget = new dijit.MenuSeparator({
+              id: 'searchResults_menuSeparator'+i
+            });
+          searchResultsWidget.addChild(menuItemWidget);
+
+          url = opt.url;
+          labelstr = opt.name;
+
+          // insert the menuitem for the gadget
+          /* XXX probably need to be able to insert the widget's icon
+           * if it has one rather than using nomadIconWidget iconclass
+           * I put a method called setImage on the PaletteMenuItem class
+           * to handle this once we know how to get the image src path
+           * out of the repository.  Similar thing should be done for
+           * the description, too.
+           */
+          menuItemWidget = new nomad.widget.PaletteItem({
+              id: 'searchResults_foundWidget'+i,
+              label: labelstr,
+              iconClass: "nomadToolbarIcon nomadIconWidget",
+              runIconClass: "nomadToolbarIcon nomadIconRun",
+              bookmarkIconClass: "nomadToolbarIcon nomadIconBookmark",
+              infoIconClass: "nomadToolbarIcon nomadIconInfo",
+              itemUrl: url,
+              onClick: function() {
+                  mashupMaker.createGadget(this.itemUrl, null);
+// XXX JHP TODO
+//                  var gadgetCoords = dojo.coords(mashupMaker._creatingGadget.frame, true);
+//                  window.scrollTo(gadgetCoords.x, gadgetCoords.y);
+                }
+            });
+          searchResultsWidget.addChild(menuItemWidget);
+            var tooltip = new dijit.Tooltip({
+                label: "test info message",
+                connectId: [menuItemWidget.id+"_infoIcon"]
+              });
+          // we are going to connect a tooltip to the 'more info' icons
+          // on each palette item so build a list of the ids to use
+          tooltipConnectIds.push(menuItemWidget.id+"_infoIcon");
+      }
+
+      var tooltip = new nomad.widget.PaletteTooltip({
+          label: "",
+          connectId: tooltipConnectIds
+        });
+      searchResultsWidget.setTooltip(tooltip);
+      searchResultsWidget.resizePalette();
+      if (searchResultsWidget.domNode.style.visibility == 'hidden') {
+        // menu tries to blur its focused child but since we may have just
+        // destroyed it in our clean up of menu items, we should null it out
+        // to be safe
+        dijit.byId('searchResults')._toggleDropDown();
+      } else {
+        searchResultsWidget.focusFirstItem();
+      }
+  }
+
+})();  // end closure
+
+
+  openMashup = function() {
+      var dialogDiv = dojo.byId('__OAA_openDialog_container');
+      dojo.parser.parse(dialogDiv);
+      openDialog = dijit.byId('__OAA_open_dialog');
+      openDialog.show();
+  }
+
+  doOpen = function(mashupname) {
+      var url = OpenAjax.widget.baseURI + 'newmashup.php?pageName=' + mashupname;
+      window.document.location = url;
+  }
+
+  saveMashup = function() {
+      doSave(mashupMaker.pageName);
+  }
+
+  saveMashupAs = function() {
+      var dialogDiv = dojo.byId('__OAA_saveAsDialog_container');
+      dojo.parser.parse(dialogDiv);
+      saveAsDialog = dijit.byId('__OAA_saveAs_dialog');
+      saveAsDialog.show();
+  }
+
+  doSave = function(pagename) {
+      var resourceUri = 'doSave.php';
+      var serializedPage = mashupMaker.exportElement().innerHTML;
+      var bindArgs = {
+          handleAs: 'text',
+          url:  resourceUri,
+          sync: true,
+          content: { page : pagename, data : serializedPage },
+          load: function(response) {
+              var select = dijit.byId( "openname" );
+              if ( select ) {
+                  // Since 'clearOnClose' is set to true on the data store,
+                  // calling close() will cause the data store to refetch
+                  // from the server next time.
+                  select.store.close();
+              }
+          },
+          error: function(error, request) {
+              alert('Save error: \n'+error);
+          }
+      };
+      dojo.xhrPost(bindArgs);
+      
+  }
+
+  shareMashup = function() {
+      var script = "&lt;script src=\"" + OpenAjax.widget.baseURI + "embedWidget.php?pageName=" + mashupMaker.pageName + "\"&gt;&lt;/script&gt;";
+      var dialogDiv = dojo.byId('__OAA_shareDialog_container');
+      dojo.parser.parse(dialogDiv);
+      dojo.byId("__OAA_shareDialog_script_tag").innerHTML = script;
+      dijit.byId("__OAA_share_dialog").show();
+      return;
+  }
+
+  function resetTextfield() {
+    var textbox = dijit.byId('widgetSearchTerms');
+    var textboxNode = dojo.byId('widgetSearchTerms');
+    textbox.setValue("");
+    textboxNode.className = 'postEdit';
+  }
+  
+  function launchAboutRefimpl( event ) {
+    window.open( OpenAjax.widget.baseURI + 'README.html', 'aboutRefimpl',
+            'width=800,height=570,resizable=yes,scrollbars=yes,toolbar=no,menubar=yes' );
+    dojo.stopEvent( event );
+    return false;
+  }
+  
+  function launchGeneralHelp( event ) {
+    window.open( OpenAjax.widget.baseURI + 'HELP.html', 'generalHelp',
+            'width=900,height=800,resizable=yes,scrollbars=yes,toolbar=no,menubar=yes' );
+    dojo.stopEvent( event );
+    return false;
+  }
+
+  function launchGeneralHelp2( event ) {
+    window.open( OpenAjax.widget.baseURI + 'HELP2.html', 'generalHelp2',
+            'width=900,height=800,resizable=yes,scrollbars=yes,toolbar=no,menubar=yes' );
+    dojo.stopEvent( event );
+    return false;
+  }
+
+  function launchParticipationHelp( event ) {
+    window.open( OpenAjax.widget.baseURI + 'PARTICIPATE.html', 'participationHelp',
+            'width=900,height=800,resizable=yes,scrollbars=yes,toolbar=no,menubar=yes' );
+    dojo.stopEvent( event );
+    return false;
+  }
+
+  function launchMetadataIntro( event ) {
+    window.open( OpenAjax.widget.baseURI + 'METADATAINTRO.html', 'metadataIntroHelp',
+            'width=900,height=800,resizable=yes,scrollbars=yes,toolbar=no,menubar=yes' );
+    dojo.stopEvent( event );
+    return false;
+  }
+
+  function launchHubIntro( event ) {
+    window.open( OpenAjax.widget.baseURI + 'HUBINTRO.html', 'hubIntroHelp',
+            'width=900,height=800,resizable=yes,scrollbars=yes,toolbar=no,menubar=yes' );
+    dojo.stopEvent( event );
+    return false;
+  }
+
+  function launchOpenBug( event ) {
+    window.open( 'http://sourceforge.net/tracker/?atid=874168&group_id=175671', 'openBug',
+            'width=900,height=800,resizable=yes,scrollbars=yes,toolbar=no' );
+    dojo.stopEvent( event );
+    return false;
+  }
+
+  function launchRepository( event ) {
+      var sarray = OpenAjax.widget.baseURI.split("/");
+      var current = sarray.pop();
+      while ( current != "gadgets" ) {
+          current = sarray.pop();
+      }
+      var baseURL = sarray.join("/");
+      window.open(  baseURL + '/repository/', 'launchRepository',
+                    'resizable=yes,scrollbars=yes,toolbar=no' );
+      dojo.stopEvent( event );
+      return false;
+  }
+
+  function newMashup( event ) {
+      window.document.location = OpenAjax.widget.baseURI + "newmashup.php";
+      dojo.stopEvent( event );
+      return false;
+  }
+
+//  var toolbarOffsetY = 0;
+  toolbarInit();
+
diff --git a/UNGProject/js/loader.js b/UNGProject/js/loader.js
new file mode 100644
index 0000000000000000000000000000000000000000..cd845bca77cfe5ae93a85205bace2ef43527da24
--- /dev/null
+++ b/UNGProject/js/loader.js
@@ -0,0 +1,1990 @@
+/*
+
+        Copyright 2006-2009 OpenAjax Alliance
+
+        Licensed under the Apache License, Version 2.0 (the "License"); 
+        you may not use this file except in compliance with the License. 
+        You may obtain a copy of the License at
+        
+                http://www.apache.org/licenses/LICENSE-2.0
+
+        Unless required by applicable law or agreed to in writing, software 
+        distributed under the License is distributed on an "AS IS" BASIS, 
+        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+        See the License for the specific language governing permissions and 
+        limitations under the License.
+*/
+
+// XXX
+if ( typeof console === "undefined" ) {
+    console = {};
+}
+if ( typeof console.log === "undefined" ) {
+    console.log = function() {};
+}
+
+
+if ( typeof OpenAjax !== "undefined" ) {
+
+OpenAjax.hub.registerLibrary("OpenAjax.widget", "http://openajax.org/widget", "0.3", {});
+
+// XXX make this a part of Loader params?
+/*=====
+oaaLoaderConfig = {
+	// proxy: String
+    //      URL of proxy which allows cross-domain calls.  The proxy must take
+    //      a URL parameter "oawu", which is the requested URL.
+    proxy: undefined
+}
+=====*/
+
+if ( ! OpenAjax.widget ) {
+    /**
+     * @namespace
+     */
+    OpenAjax.widget = {};
+}
+
+(function() {
+
+/**
+ * @class
+ * <p> Widget loader. </p>
+ * 
+ * @description
+ * Creates a new Loader instance.
+ * 
+ * @param {Object} args
+ *     Parameters used to instantiate the Loader.  This object may contain the
+ *     following properties:
+ * @param {Object} args.ManagedHub
+ *     Parameters for creating a ManagedHub instance.
+ */
+OpenAjax.widget.Loader = function( args )
+{
+    var onsub = args.ManagedHub.onSubscribe;
+    var onpub = args.ManagedHub.onPublish;
+    var onunsub = args.ManagedHub.onUnsubscribe;
+    var scope = args.scope || window;
+    
+    function _onSubscribe( topic, container )
+    {
+        return onsub.apply( scope, arguments );
+    }
+    
+    function _onPublish( topic, data, pcont, scont )
+    {
+        return onpub.apply( scope, arguments );
+    }
+    
+    function _onUnsubscribe( topic, container )
+    {
+        if ( onunsub ) {
+            return onunsub.apply( scope, arguments );
+        }
+    }
+    
+    this.hub = new OpenAjax.hub.ManagedHub({
+        onPublish: _onPublish,
+        onSubscribe: _onSubscribe,
+        onUnsubscribe: _onUnsubscribe,
+        scope: scope,
+        log: args.logs
+    });
+    
+    _hub = this.hub;
+    
+    _metadataCache = {};
+    
+    // Find location of OpenAjax Hub files, so that we can generate 'tunnel.html'
+    // location.
+    _tunnelURI = null;
+    _loaderRoot = null;
+    var scripts = document.getElementsByTagName("script");
+    // match "OpenAjax-mashup.js", "OpenAjaxManagedHub-std.js", "OpenAjaxManagedHub-core.js", or "OpenAjaxManagedHub-all.js"
+    var reHub = /openajax(?:ManagedHub-.+|-mashup)\.js$/i;
+    var reLoader = /loader\.js$/i;
+    for ( var i = 0; (_tunnelURI === null || _loaderRoot === null) && i < scripts.length; i++ ) {
+        var src = scripts[i].src;
+        if ( src ) {
+            var m;
+            if ( _tunnelURI === null ) {
+                if ( reHub.test( src ) ) {
+                    // make URL absolute
+                    src = /^\w+:/.test( src ) ? src : scripts[i].getAttribute('src', -1);
+                    _hubBaseJS = src;
+                    m = src.match( reHub );
+                    var hubRoot = src.substring( 0, m.index );
+                    if ( /openajax-mashup\.js/i.test( m[0] ) ) {
+                        _tunnelURI = hubRoot + "containers/iframe/tunnel.html"; 
+                    } else {
+                        _tunnelURI = hubRoot + "tunnel.html";
+                    }
+                }
+            }
+            
+            if ( _loaderRoot === null ) {
+                if ( reLoader.test( src ) ) {
+                    // make URL absolute
+                    src = /^\w+:/.test( src ) ? src : scripts[i].getAttribute('src', -1);
+                    m = src.match( reLoader );
+                    _loaderRoot = src.substring( 0, m.index );
+                }
+            }
+        }
+    }
+    
+    // parse oaaLoaderConfig object
+    if ( typeof oaaLoaderConfig !== "undefined" ) {
+        // Save proxy URL, if specified
+        if ( oaaLoaderConfig.proxy ) {
+            _proxyURL = oaaLoaderConfig.proxy;
+            if ( _proxyURL.charAt(0) !== "/" && ! /^\w+:/.test( _proxyURL ) ) {
+                // make absolute
+                _proxyURL = window.location.protocol + "//" + window.location.host +
+                        /^(\/(.*\/)*)/.exec( window.location.pathname )[1] + _proxyURL;
+            }
+        }
+    }
+    
+    _metadata_plurals = {
+        authors: "author",
+        categories: "category",
+        configs: "config",
+        contents: "content",
+        enums: "enum",
+        examples: "example",
+        icons: "icon",
+        javascripts: "javascript",
+        libraries: "library",
+        options: "option",
+        properties: "property",
+        references: "reference",
+        requires: "require",
+        topics: "topic"
+    };
+};
+
+/**
+ * Load and parse a widget specification. 
+ *
+ * @param {Object} args
+ *     Parameters used to load widget metadata.  This object may contain the
+ *     following properties:
+ * @param {String} args.url
+ *     The URL of the widget specification.
+ * @param {String} [args.locale]
+ *     The locale to be used when doing localization substitutions.  If not
+ *     specified, defaults to the browser locale.
+ * @param {Object} [args.properties]
+ *     Initial widget properties.  This is an object of name-value pairs, where
+ *     the name matches a property name as defined in the widget metadata.  This
+ *     object is used when doing property value substitutions.  If this
+ *     parameter is null, or if a given property name is not specified, then
+ *     the substitution code will use the property's default value.
+ * @param {Function} args.onComplete
+ *     Callback which is invoked if loading the URL was successful,
+ *     onSuccess(metadata).
+ * @param {Function} args.onError
+ *     Callback which is invoked if an error occurs, onError(error).
+ * 
+ * @returns {Object}
+ *     An object whose properties represent the widget elements.
+ */
+OpenAjax.widget.Loader.prototype.loadMetadata = function( args )
+{
+    // XXX TODO properly handle plural elements
+    
+    // make sure the URL is absolute
+    // XXX need a better method of doing this
+    var a = document.createElement('a');
+    a.href = args.url;
+    var url = a.href;
+    
+    var cache = _metadataCache;
+    var locale = null;
+    
+    // Return the attributes of the given DOM element as an object of
+    // name-value pairs.
+    var _getAttrs = function(elem) {
+        var map = {}, domAttrs = elem.attributes;
+        for(var i = 0; i < domAttrs.length; i++) {
+            map[domAttrs[i].name] = domAttrs[i].value;
+        }
+        return map;
+    };
+    
+    // Return the text content of the given DOM element.
+    var _innerText = function( node ) {
+        var text = node.innerText || node.textContent;
+        if ( typeof text === "undefined" ) {
+            text = "";
+            var children = node.childNodes;
+            if (children) {
+                for (var i = 0; i < children.length; i++) {
+                    var n = children.item(i);
+                    if (n.nodeType == 3 || n.nodeType == 4) {  // text or CDATA
+                        text += n.nodeValue;
+                    }
+                }
+            }
+        }
+        return text;
+    };
+    
+    // Compute the appropriate text content of the give DOM element, doing
+    // any necessary substitutions. 
+    var _getContentText = function( node, item ) {
+        function escapequotes( text ) {
+            return text.replace(/'/g, "\\'").replace(/"/g, '\\"');
+        }
+        
+        function entityencode( text ) {
+            return text.replace(/&/gm, "&amp;").replace(/</gm, "&lt;")
+			        .replace(/>/gm, "&gt;").replace(/"/gm, "&quot;")
+					.replace(/'/gm, "&#39;");
+        }
+        
+        var text = null;
+        if ( item.locid && locale ) {
+            text = locale.getMsg( item.locid );
+        }
+        if ( ! text ) {
+            text = _innerText( node );
+        }
+        
+        if ( text ) {
+            item._content_ = text.replace( /##(\w+)(?:\((\w+)\))?##/g,
+                    function( str, p1, p2 ) {
+                        var key = p2 || p1;
+                        var newText = locale.getMsg( key );
+                        if ( newText ) {
+                            if ( p2 ) {
+                                switch ( p1 ) {
+                                    case "escapequotes":
+                                        newText = escapequotes( newText );
+                                        break;
+                                    case "entityencode":
+                                        newText = entityencode( newText );
+                                        break;
+                                }
+                            }
+                            return newText;
+                        }
+                        return str;
+                    }
+            ).replace( /__BIDI_\w+__/g,
+                    function( str ) {
+                        switch ( str ) {
+                            case "__BIDI_START_EDGE__":
+                                if ( locale.language_direction === "ltr" ) {
+                                    return "left";
+                                }
+                                return "right";
+                            case "__BIDI_END_EDGE__":
+                                if ( locale.language_direction === "ltr" ) {
+                                    return "right";
+                                }
+                                return "left";
+                            case "__BIDI_DIR__":
+                                return locale.language_direction;
+                            case "__BIDI_REVERSE_DIR__":
+                                if ( locale.language_direction === "ltr" ) {
+                                    return "rtl";
+                                }
+                                return "ltr";
+                        }
+                        return str;
+                    }
+            );
+        }
+    };
+    
+    // Find which of the widget's message bundles to use for widget
+    // localization.  Generates the "locale" object.
+    var _getLocale = function( metadata, onComplete ) {
+        // find the client's locale
+        var userLocale = (args.locale ? args.locale :
+                (navigator.language ? navigator.language : navigator.userLanguage)).toLowerCase();
+        
+        // find the closest widget locale match to the client's locale
+        var localeNode = null;
+        do {
+            if ( metadata.locale[ userLocale ] ) {
+                localeNode = metadata.locale[ userLocale ];
+                break;
+            }
+            
+            var idx = userLocale.lastIndexOf( "-" );
+            if ( idx === -1 ) {
+                break;
+            }
+            userLocale = userLocale.slice( 0, idx );
+        } while(1);
+        
+        // no appropriate message bundle was found for the user's locale -- try
+        // the fallback message bundle
+        if ( ! localeNode ) {
+            if ( metadata.locale.ALL ) {
+                localeNode = metadata.locale.ALL;
+            } else {
+                // no appropriate message bundle found; don't create 'locale' object
+                onComplete();
+                return;
+            }
+        }
+        
+        // retrieve the message bundle file contents
+        var u = _getProxyUrl( _resolveURI( localeNode.messages, metadata._src_ ) );
+        OpenAjax.widget._xhrGet( u, true,
+                /* onComplete */
+                function( dom ) {
+                    var messages = {};
+                    var bundle = dom.getElementsByTagName( "messagebundle" ).item(0);
+                    var msg = bundle.getElementsByTagName( "msg" );
+                    for ( var j = 0; j < msg.length; j++ ) {
+                        var name = msg[j].getAttribute( "name" );
+                        var text = _innerText( msg[j] );
+                        messages[ name ] = text;
+                    }
+                    
+                    // create locale object, in context of loadMetadata()
+                    locale = {
+                        lang: localeNode.lang,
+                        language_direction: localeNode.language_direction ? localeNode.language_direction : "ltr",
+                        _messages: messages,
+                        getMsg: function( name ) {
+                            return this._messages[ name ];
+                        }
+                    };
+                    onComplete();
+                },
+                /* onError */
+                function( error ) {
+                    args.onError( "Failed to retrieve message bundle file -- " +
+                            "url: " + u + "  error: " + error );
+                }
+        );
+    };
+    
+    // Parse the given DOM element's children and add data to the "parentObj"
+    // object. 
+    var _parseElement = function( element, parentObj, grandparentObj ) {
+        if ( element.childNodes.length === 0 ) {
+            return true; // return true in order to circumvent _innerText() call
+        }
+        
+        var elemName = element.tagName.toLowerCase();
+        var hasNonTextContent = false;
+        
+        for ( var i = 0; i < element.childNodes.length; i++ ) {
+            var node = element.childNodes.item( i );
+            
+            // for text nodes, "node.tagName" is undefined
+            if ( ! node.tagName ) {
+                continue;
+            }
+            var tagName = node.tagName.toLowerCase();
+            
+            if ( tagName in _metadata_plurals ) {
+                // Ignore plural elements, but loop over their child nodes.
+                _parseElement( node, parentObj, parentObj );
+            } else {
+                // If the parent of this element is a plural element, then we
+                // only want to deal with the singular version of that parent,
+                // and ignore all other elements.  For example, for the parent
+                // <properties>, we only want to handle any child <property>
+                // elements, while ignoring others such as <description>.
+                // The only exception is the <library> element, which can be a
+                // child of <requires>.
+                if ( (elemName in _metadata_plurals) &&
+                        tagName !== _metadata_plurals[ elemName ] &&
+                        tagName !== "library" )
+                {
+                    continue;
+                }
+                
+                // <locale> and <property> have already been handled
+                if ( tagName === "locale" || tagName === "property" ) {
+                    continue;
+                }
+                
+                hasNonTextContent = true;
+
+                // get the attributes for this element
+                var item = _getAttrs( node );
+                
+                // handle any special cases
+                var attrs,
+                    obj = parentObj;
+                switch ( tagName ) {
+                    case "option":
+                        // If <option> is a child of <options>, save the
+                        // 'multiple' and 'unconstrained' attributes if they
+                        // exist on the parent.
+                        if ( elemName === "options" ) {
+                            attrs = _getAttrs( node.parentNode );
+                            if ( attrs.multiple ) {
+                                item._multiple_ = attrs.multiple;
+                            }
+                            if ( attrs.unconstrained ) {
+                                item._unconstrained_ = attrs.unconstrained;
+                            }
+                        }
+                        break;
+                    case "require":
+                        // If a <require> element is a child of a <library>
+                        // element, then we save the name of the library to
+                        // which that require belongs.
+                        if ( elemName === "library" ) {
+                            obj = grandparentObj;
+                            item._library_ = _getAttrs( node.parentNode ).name;
+                        }
+                        break;
+                }
+                
+                // Add this element info to the object.  If this element has a
+                // 'name' attribute, then we index using that.
+                var name = item.name;
+                if ( name ) {
+                    if ( ! obj[ tagName ] ) {
+                        obj[ tagName ] = {};
+                    }
+                    delete item.name;
+                    obj[ tagName ][ name ] = item;
+                } else {
+                    if ( ! obj[ tagName ] ) {
+                        obj[ tagName ] = [];
+                    }
+                    obj[ tagName ].push( item );
+                }
+                
+                // See if this element has any child nodes that need to be
+                // handled.  If not, then see if it has any text content.
+                if ( ! _parseElement( node, item, parentObj ) ) {
+                    _getContentText( node, item );
+                }
+            }
+        }
+        
+        return hasNonTextContent;
+    };
+    
+    // Convert the widget's DOM into a JavaScript object.
+    var _transformXML = function( dom ) {
+        var widget = dom.getElementsByTagName('widget').item(0);
+        var metadata = _getAttrs(widget);
+        
+        // save location of widget metadata file
+        metadata._src_ = url;
+        
+        // In order to handle substitutions, we need to first parse the 'locale'
+        // and 'property' elements.
+        var locales = widget.getElementsByTagName( "locale" );
+        if ( locales.length > 0 ) {
+            metadata.locale = {};
+            for ( var i = 0; i < locales.length; i++ ) {
+                var item = _getAttrs( locales[i] );
+                var lang = item.lang ? item.lang.toLowerCase() : null;
+                
+                if ( ! lang ) {
+                    // If <locale> has no "lang" attribute, then this is the
+                    // fallback message bundle.  We only allow one, so just
+                    // take the first one.
+                    if ( ! metadata.locale.ALL ) {
+                        metadata.locale.ALL = item;
+                    }
+                } else {
+                    delete item.lang;
+                    metadata.locale[ lang ] = item;
+                }
+            }
+            
+            // given these locale elements, find the user's locale
+            _getLocale( metadata, finish );
+        } else {
+            finish();
+        }
+        
+        function finish() {
+            // Now that we've handled <locale>, we move on to <property>
+            var properties = widget.getElementsByTagName( "property" );
+            if ( properties.length > 0 ) {
+                metadata.property = {};
+                
+                for ( var i = 0; i < properties.length; i++ ) {
+                    var item = _getAttrs( properties[i] );
+                    var name = item.name;
+                    delete item.name;
+                    
+                    metadata.property[ name ] = item;
+
+                    // If <property> is a child of <properties>, save the
+                    // 'name' and 'managed' attributes if they exist on
+                    // the parent.
+                    if ( properties[i].parentNode.tagName.toLowerCase() === "properties" ) {
+                        attrs = _getAttrs( properties[i].parentNode );
+                        if ( attrs.name ) {
+                            item._group_ = attrs.name;
+                        }
+                        if ( attrs.managed ) {
+                            item._managed_ = attrs.managed;
+                        }
+                    }
+                    
+                    // see if it has any child elements
+                    _parseElement( properties[i], item, null );
+                }
+            }
+            
+            // parse the rest of the widget DOM
+            _parseElement( widget, metadata, metadata );
+            
+            if ( cache ) {
+                cache[url] = metadata;
+            }
+            args.onComplete( metadata );
+        }
+    };
+
+    if (cache && cache[url]) {
+        args.onComplete(cache[url]);
+    } else {
+        // If a proxy has been defined, then we use it in order to get widget
+        // definitions that live on other domains.
+        var u = _getProxyUrl( url );
+        OpenAjax.widget._xhrGet( u, true, _transformXML, args.onError);
+    }
+};
+
+
+/**
+ * Creates an instance of a widget and adds it to the page, loading resources as
+ * needed.
+ *
+ * @param {Object} args
+ *     Parameters used to create a widget.  This object may contain the
+ *     following properties:
+ * @param {Object | String} args.spec
+ *     A widget spec object (as returned by
+ *     {@link OpenAjax.widget.Loader#loadMetadata}) or a URL pointing to the
+ *     widget specification.
+ * @param {HTMLElement | String} args.target
+ *     HTML DOM element or ID of element in which this widget is rendered.
+ * @param {String} [args.id]
+ *     A string identifier for this widget.  If null, one is generated.
+ * @param {String} [args.mode]
+ *     Initial mode of rendered widget.  If not specified, defaults to "view".
+ * @param {String} [args.locale]
+ *     The locale to be used when doing localization substitutions.  If not
+ *     specified, defaults to the browser locale.
+ * @param {Object} [args.properties]
+ *     Initial widget properties.  This is an object of name-value pairs, where
+ *     the name matches a property name as defined in the widget metadata.
+ * @param {Object} [args.availableDimensions]
+ *     The maximum size to which a widget can be sized inside of this mashup
+ *     framework.  This object has "width" and "height" properties.  If either
+ *     is omitted, then that dimension is considered unconstrained.
+ * @param {Function} [args.adjustDimensions]
+ *     A callback which gets invoked whenever a widget requests a resize.  This
+ *     function takes two parameters: a widget ID and a dimensions object, with
+ *     "width" and "height" properties.  If the callback returns null, the
+ *     resize request is ignored.  Otherwise, the callback should return a
+ *     dimensions object with dimensions less than or equal to those passed in,
+ *     in order to size the widget to those dimensions.
+ * @param {Boolean} [args.sandbox]
+ *     If true, will load the widget as sandboxed (in an iframe), regardless
+ *     of what the "sandbox" attribute is set to in the widget spec.  If false
+ *     or unspecified, then we honor the "sandbox" attribute as specified in
+ *     the widget spec.
+ * @param {Function} args.onComplete
+ *     Callback which is invoked if loading the URL was successful,
+ *     onSuccess(metadata).
+ * @param {Function} args.onError
+ *     Callback which is invoked if an error occurs, onError(error).
+ * 
+ * @returns {Object}
+ *     Widget instance object.
+ */
+OpenAjax.widget.Loader.prototype.create = function(args)
+{
+    var spec = args.spec;
+
+    if(typeof spec == "string") {
+        var that = this;
+        return this.loadMetadata({
+                url: spec,
+                locale: args.locale,
+                properties: args.properties,
+                onComplete: function(metadata) {
+                    args.spec = metadata;
+                    that.create(args);
+                },
+                onError: onError
+        });
+    }
+
+    var target = args.target,
+        view = args.view,
+        properties = args.properties || {},
+        availDimensions = {},
+        onComplete = args.onComplete,
+        onError = args.onError || function(e) { console.error(e); };
+    
+    if ( typeof target == "string" ) {
+        target = document.getElementById( target );
+    }
+
+    // XXX widget ID should be randomized
+    var wid = args.id;
+    if ( ! wid ) {
+        while ((wid = "OAA" + ++_uniqueId) && document.getElementById(wid));
+    }
+    
+    if ( args.availableDimensions ) {
+        if ( args.availableDimensions.width ) {
+            availDimensions.width = args.availableDimensions.width;
+        }
+        if ( args.availableDimensions.height ) {
+            availDimensions.height = args.availableDimensions.height;
+        }
+    }
+    
+    var oaa;
+    if ( spec.sandbox || args.sandbox ) {
+        oaa = new ProxyWidget();
+    } else {
+        oaa = new BaseWidget();
+    }
+    oaa._init({
+        spec: spec,
+        id: wid,
+        props: properties,
+        root: target,
+        availDimensions: availDimensions,
+        adjustDimensions: args.adjustDimensions
+    });
+    
+    oaa._render( target, view, onComplete );
+
+    // XXX How does the mashup developer get access to the widget object (or even
+    //     the widget ID)?  create() doesn't return anything.  But there is the
+    //     byId() method.  So either have create() return the generated widget ID,
+    //     so that the dev can get the widget object by calling byId(), or have
+    //     create() return the widget object itself.
+    return oaa._widget;
+};
+
+/**
+ * Updates the available dimensions for the given widget.
+ * 
+ * @param {Object | String} widget
+ *     Widget instance object or ID.
+ * @param {Object} availDimensions
+ *     The new available dimensions.  The object may have properties of "width"
+ *     and "height".  If either property is undefined, then that dimensions is
+ *     considered to be unconstrained.
+ */
+OpenAjax.widget.Loader.prototype.setAvailableDimensions = function( widget, availDimensions )
+{
+    if ( typeof widget == "String" ) {
+        widget = OpenAjax.widget.byId( widget );
+    }
+    widget.OpenAjax._setAvailableDimensions( availDimensions );
+};
+
+/**
+ * Returns a widget instance for the given ID.
+ * 
+ * @param {Object} id
+ *     Requested widget ID.
+ */
+OpenAjax.widget.byId = function( id )
+{
+    return _widgetTable[id];
+};
+
+
+
+    //*************** private functions and variables ***************//
+
+
+// ManagedHub instance
+var _hub;
+// optional cache object.  hide in closure? expose  remove?
+var _metadataCache;
+// shared counter to be used for __WID__ substitution
+var _uniqueId = 0;
+// lookup table for widgets
+var _widgetTable = {};
+// hash to keep track of loaded requires
+//var _requiresCache = {};
+// absolute URL of main OpenAjax Hub JS file
+var _hubBaseJS;
+// absolute URL of OpenAjax Hub tunnel.html
+var _tunnelURI;
+// base URL for this JS file
+var _loaderRoot;
+// arrays of element names; used by loadMetadata() to parse widget XML file
+var _metadata_plurals;
+
+// URL of proxy, if specified
+var _proxyURL = null;
+
+/**
+ * Returns the proxied version of the given URL.  If a proxy was never
+ * specified, or if the given URL is in the same origin, then the URL is
+ * returned unchanged.
+ *  
+ * @param {String} url
+ * @returns {String}
+ *     Proxied version of URL
+ */
+function _getProxyUrl( url ) {
+    if ( _proxyURL ) {
+        if ( url.match( /^(\w+:\/\/[^\/?#]+).*/ )[1] ===
+                (window.location.protocol + "//" + window.location.host) ) {
+            // no need to use proxy if 'url' is in same origin
+            return url;
+        }
+        return _proxyURL + "?oawu=" + encodeURIComponent( url );
+    }
+    return url;
+}
+
+/**
+ * Returns an absolute URI version of the passed-in uri.  URI is resolved
+ * against the widget metadata location.
+ * 
+ * @param {Object} uri
+ *     URI to resolve
+ * @param {Object} specURI
+ *     URI of widget metadata file
+ */
+function _resolveURI( uri, specURI )
+{
+    // if absolute URI, return
+    // XXX save off RegExp object, rather than creating anew every time?
+    if ( /^\w+:\/\/.+/.exec( uri ) !== null ) {
+        return uri;
+    }
+    
+    if ( uri.charAt(0) !== "/" ) {
+        return specURI.slice( 0, specURI.lastIndexOf("/") + 1 ) + uri;
+    }
+    
+    return (/^(\w+:\/\/[^\/]+).*/.exec( specURI ))[1] + uri;
+}
+
+var _head = document.getElementsByTagName('HEAD').item(0);
+if (!_head) {
+    _head = document.createElement('HEAD');
+    document.body.insertBefore(_head, document.body.childNodes.item(0));
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+//    BaseWidget
+////////////////////////////////////////////////////////////////////////////
+
+var BaseWidget = function() {};
+
+BaseWidget.prototype = 
+{
+    //*** OpenAjax Metadata Widget APIs ***//
+   
+    getId: function() {
+        return this._id;
+    },
+    
+    getAvailableDimensions: function() {
+        return this._availableDimensions;
+    },
+    
+    getDimensions: function() {
+        return {
+            width: parseInt( this._rootElement.style.width, 10 ),
+            height: parseInt( this._rootElement.style.height, 10 )
+        };
+    },
+    
+    adjustDimensions: function( dimensions ) {
+        // ask the app if this widget is allowed to resize to the
+        // requested dimensions
+        if ( this._adjustDimensionsCB ) {
+            // XXX scope for callback?
+            dimensions = this._adjustDimensionsCB( this._widget, dimensions );
+        }
+        if ( dimensions ) {
+            this._rootElement.style.width = dimensions.width + "px";
+            this._rootElement.style.height = dimensions.height + "px";
+            return dimensions;
+        }
+        return null;
+    },
+    
+    getMode: function() {
+        // XXX TODO
+        alert( "BaseWidget.getMode not implemented" );
+    },
+    
+    requestMode: function( mode ) {
+        // XXX TODO
+        alert( "BaseWidget.requestMode not implemented" );
+    },
+    
+    getPropertyValue: function(name) {
+        return this._properties[name] || this._spec.property[name].defaultValue;
+    },
+    
+    setPropertyValue: function( name, value )
+    {
+        if ( this._setPropertyValue( name, value, true, true ) ) {
+            var prop = this._spec.property[ name ];
+            if ( prop.sharedAs ) {
+                this._hubClient.publish( prop.sharedAs,
+                        this._encodePropValue( name, value ) );
+            }
+        }
+    },
+    
+    getPropertyNames: function() {
+        var names = [];
+        for (var name in this._spec.property) {
+            names.push(name);
+        }
+        return names;
+    },
+    
+    getMsg: function( key )
+    {
+        // XXX TODO
+        alert( "BaseWidget.getMsg not implemented" );
+    },
+    
+    rewriteURI: function( url )
+    {
+        return _getProxyUrl( _resolveURI( url, this._spec._src_ ) );
+    },
+    
+// XXX old code
+//      getSupportedViews: function() {
+//          var views = {};
+//          for (var i=0; i < this.spec.contents; i++) {
+//              var list = (this.spec.contents[i].view || "default").split(",");
+//              for (var j=0; j < list.length; j++) {
+//                  //TODO: this method is supposed to construct a hash of View objects. What are View objects? 
+//                  views[list[j] = undefined];
+//              }
+//          }
+//          return views;
+//      },
+//      requestNavigateTo: function() {
+//          //TODO
+//      },
+    
+    //*** private functions ***//
+   
+    _init: function ( args )
+    {
+        this._id = args.id;
+        this._spec = args.spec;
+        this._properties = args.props || {};
+        this._rootElement = args.root;
+        this._availableDimensions = args.availDimensions;
+        this._adjustDimensionsCB = args.adjustDimensions;
+        
+        this._connectToHub();
+        this._createHubSubObject();
+        this._handlePropSubscriptions();
+        
+        // XXX should we directly set size on rootElement, or create a DIV
+        //   inside and change its dimensions?
+        this._rootElement.style.width = this._spec.width + "px";
+        this._rootElement.style.height = this._spec.height + "px";
+    },
+    
+    _connectToHub: function()
+    {
+        // XXX add error checks
+        this._container = new OpenAjax.hub.InlineContainer( _hub, this._id,
+                {   Container: {
+                        onSecurityAlert: function( source, alertType ) {
+                            console.log( "onSecurityAlert: s=" + source.getClientID() + " a=" + alertType );
+                        },
+                        scope: this,
+                        log: function( msg ) { console.log( msg ); }
+                    }
+                }
+        );
+        
+        this._hubClient = new OpenAjax.hub.InlineHubClient({
+                HubClient: {
+                    onSecurityAlert: function( source, alertType ) {
+                        console.log( "onSecurityAlert: s=" + source.getClientID() + " a=" + alertType );
+                    },
+                    scope: this,
+                    log: function(msg) { console.log( msg ); }
+                },
+                InlineHubClient: {
+                    container: this._container
+                }
+        });
+        this._hubClient.connect();
+    },
+    
+    _createHubSubObject: function()
+    {
+        var that = this;
+        this.hub = new function() {
+            this.subscribe = function() {
+                that._hubClient.subscribe.apply( that._hubClient, arguments );
+            };
+            
+            this.publish = function() {
+                that._hubClient.publish.apply( that._hubClient, arguments );
+            };
+            
+            this.unsubscribe = function() {
+                that._hubClient.unsubscribe.apply( that._hubClient, arguments );
+            };
+            
+            this.isConnected = function() {
+                that._hubClient.isConnected.apply( that._hubClient, arguments );
+            };
+            
+            this.getScope = function() {
+                that._hubClient.getScope.apply( that._hubClient, arguments );
+            };
+            
+            this.getSubscriberData = function() {
+                that._hubClient.getSubscriberData.apply( that._hubClient, arguments );
+            };
+            
+            this.getSubscriberScope = function() {
+                that._hubClient.getSubscriberScope.apply( that._hubClient, arguments );
+            };
+            
+            // do no expose this function
+            this.getParameters = function() {};
+        };
+    },
+    
+    _handlePropSubscriptions: function()
+    {
+        var that = this;
+        function createSubscription( name, prop ) {
+            return that._hubClient.subscribe( prop.sharedAs,
+                    function( topic, data ) {
+                        that._setPropertyValue( name, data, true, false );
+                    },
+                    that
+            );
+        }
+        
+        this._subscriptions = [];
+        for ( var name in this._spec.property ) {
+            var prop = this._spec.property[ name ];
+            if ( prop.sharedAs ) {
+                var sid = createSubscription( name, prop );
+                this._subscriptions.push( sid );
+            }
+        }
+    },
+    
+    _setPropertyValue: function( name, newValue, notify, self )
+    {
+        var oldValue = this.getPropertyValue( name );
+        newValue = this._decodePropValue( name, newValue );
+        
+        if ( this._equals( name, oldValue, newValue )) {
+            return false;
+        }
+        
+        this._properties[ name ] = newValue;
+
+        // call onChange* functions
+        if ( notify ) {
+            var event = {
+                property: name,
+                oldValue: oldValue,
+                newValue: newValue,
+                self: self
+            };
+            if ( this._widget.onChange ) {
+                this._widget.onChange.call( this._widget, event );
+            }
+            var cb = "onChange" + name.charAt(0).toUpperCase() + name.substring(1);
+            if ( this._widget[ cb ] ) {
+                this._widget[ cb ].call( this._widget, event );
+            }
+        }
+        
+        return true;
+    },
+    
+    _equals: function( propName, value1, value2 )
+    {
+        var prop = this._spec.property[ propName ];
+        switch( prop.datatype ) {
+            case "Date":
+                return value1.valueOf() == value2.valueOf();
+            default:
+                return value1 == value2;
+        }
+    },
+    
+    _encodePropValue: function( name, value )
+    {
+        var prop = this._spec.property[ name ];
+        switch ( prop.datatype ) {
+            // XXX for type 'Date', we transmit the value as milliseconds
+            case "Date":
+                if ( typeof value === "object" ) {
+                    value = value.getTime();
+                }
+                break;
+        }
+        return value;
+    },
+    
+    _decodePropValue: function( name, value )
+    {
+        var prop = this._spec.property[ name ];
+        switch ( prop.datatype ) {
+            case "Date":
+                if ( typeof value !== "object" ) {
+                    if ( value === "" ) {
+                        // XXX assume empty string for type 'Date' signifies "now"
+                        value = new Date();
+                    } else {
+                        value = new Date( value );
+                    }
+                }
+                break;
+        }
+        return value;
+    },
+
+    _render: function( target, view, onComplete )
+    {
+        var that = this;
+        
+        this._widgetContext = new function() {
+            // Keep track of the widget's content.  The scripts are separated
+            // from each other, depending on when they should run.
+            this.body = {
+                jsBefore: [],
+                content: null,
+                jsContent: [],
+                jsAfter: [],
+                jsEnd: []
+            };
+            this.loadedCallbacks = 0;
+            this.runDeferredScripts = function() {
+                if (--this.loadedCallbacks) {
+                    return;
+                }
+
+                var _getObject = function(clazz, context) {
+                    var obj = context || window,
+                        path = clazz.split(".");
+                    for (var i=0; i < path.length; i++) {
+                        obj = obj[path[i]];
+                    }
+                    return obj;
+                };
+
+                // create widget instance
+                var widget;
+                if ( that._spec.jsClass ) {
+                    widget = new (_getObject( that._spec.jsClass ))();
+                } else {
+                    widget = {};
+                }
+                widget.OpenAjax = that;
+                that._widget = widget;
+                // XXX How do we handle _widgetTable in the sandbox case?  Should it only be used
+                //     on the app side?  Or is it also necessary inside an iframe?  Where does
+                //     the developer get the widget ID from?
+                _widgetTable[ that._id ] = widget;
+                
+                // evaluate widget content -- render content and run scripts
+                // in order
+                var s = [ "jsBefore", "jsContent", "jsAfter", "jsEnd" ];
+                for ( i = 0; i < s.length; i++ ) {
+                    if ( s[i] == "jsContent" ) {
+                        // add content to page, before running the scripts we
+                        // had previously extracted from the content
+                        target.innerHTML = this.body.content;
+                    }
+
+                    var scripts = this.body[ s[i] ];
+                    this.body[ s[i] ] = [];
+
+                    for ( var j = 0; j < scripts.length; j++ ) {
+                        OpenAjax.widget._runScript( scripts[j]/*, onError*/ );    // XXX handle error
+                    }
+                }
+                
+                // let the widget code know that the widget has been fully
+                // loaded
+                if ( widget.onLoad ) {
+                    widget.onLoad( {} );
+                }
+
+                if ( onComplete ) {
+                    onComplete( widget );
+                }
+            };
+        };
+
+        this._widgetContext.loadedCallbacks++;
+        
+        if ( this._spec.require ) {
+            this._loadAndEvalRequires();
+        }
+        
+        this._loadContent( target, view );
+
+        this._widgetContext.runDeferredScripts();
+    },
+    
+    _loadAndEvalRequires: function()
+    {
+        var scripts = [];
+        var prepost = {};
+        
+        for (var i = 0; i < this._spec.require.length; i++) {
+            var req = this._spec.require[i];
+
+//            // check for duplicates
+//            // XXX This is for use by inline widgets, where multiple widgets
+//            //    exist on the same page and may have similar requires. The
+//            //    problem with this approach is that the first instance of a
+//            //    given library of file is used.  Rather, we should probably
+//            //    use the one with the greatest version.
+//            var requireInfo;
+//            if (req.src in _requiresCache && (requireInfo = _requiresCache[req.src]).library == req.library) {
+//                if (requireInfo.inFlight) {
+//                    this._widgetContext.loadedCallbacks++;
+//                    requireInfo.callbacks.push(function(uri){
+//                        that._widgetContext.runDeferredScripts();
+//                    });
+//                }
+//
+//                // already loaded on page
+//                continue;
+//            }
+//
+//            _requiresCache[req.src] = {
+//                library: req.library
+//            };
+//
+//            var library = req.library && this._spec.libraries[req.library];
+//
+//            if (library && library.preload) {
+//                this._runScript(library.preload);
+//            }
+//
+//            this._insertResource(document, req, library ? library.src : "");
+//
+//            if (library && library.postload) {
+//                this._runScript(library.postload);
+//            }
+            
+            var library = req._library_ && this._spec.library[ req._library_ ];
+            if ( library && library.preload && ! (req._library_ in prepost) ) {
+                scripts.push( { text: library.preload[0]._content_ } );
+            }
+            
+            var prefix = library ? library.src : "";
+            // relative URLs are assumed to be relative to widget XML file
+            var uri = req.src ? _resolveURI( prefix + req.src, this._spec._src_ ) : null;
+            switch ( req.type ) {
+                case "javascript":
+                    scripts.push( uri ?
+                            { src: uri } :
+                            { text: req._content_ }
+                    );
+                    break;
+                case "css":
+                    // XXX Directly loading the CSS require could result in it
+                    //    being loaded out of order as compared to the JS
+                    //    requires as defined in the widget XML.
+                    this._loadCSS( req._content_, uri );
+                    break;
+                default:
+                    // XXX TODO
+            }
+            
+            if ( library && library.postload && ! (req._library_ in prepost) ) {
+                scripts.push( { text: library.postload[0]._content_ } );
+            }
+            
+            // keep track that we have already handled preload/postload for library
+            if ( library ) {
+                prepost[ req._library_ ] = true;
+            }
+        }
+        
+        this._widgetContext.loadedCallbacks++;
+        var that = this;
+        OpenAjax.widget._loadScripts( scripts, true,
+                function( scripts, success, error ) { // onComplete
+                    if ( success ) {
+                        that._widgetContext.runDeferredScripts();
+                        return;
+                    }
+                    // XXX handle error
+console.error( error );
+                }
+        );
+    },
+    
+    // load widget content (<content> & <javascript>)
+    _loadContent: function( target, mode )
+    {
+        var that = this;
+        var content;
+        for (var i = 0; i < this._spec.content.length; i++) {
+            var c = this._spec.content[i],
+                list = ","+(c.mode||"view")+",";
+
+            if (list.indexOf(","+(mode||"view")+",") != -1) {
+                content = c;
+                break;
+            }
+            if (!content && list.indexOf(",view,") != -1) {
+                content = c;
+            }
+        }
+        if ( ! content ) {
+            // XXX handle error
+            return;
+        }
+
+        var _propReplace = function(match, transform, name)
+        {
+			name = name || transform; // if no transform, name will be in the first position
+			if (transform) {
+				switch (transform) {
+					case "escapequotes":
+						name = name.replace(/'/g, "\\'").replace(/"/g, '\\"');
+						break;
+					case "entityencode":
+						name = name.replace(/&/gm, "&amp;").replace(/</gm, "&lt;")
+							.replace(/>/gm, "&gt;").replace(/"/gm, "&quot;")
+							.replace(/'/gm, "&#39;");
+//									break;
+//								default:
+						//TODO: error handling?
+				}
+			}
+
+            return that._properties[name] || that._spec.property[name].defaultValue;
+        };
+
+        if ( content.src ) {
+            // relative URLs are assumed to be relative to widget XML file
+            var uri = _resolveURI( content.src, this._spec._src_ );
+            this._widgetContext.loadedCallbacks++;
+            OpenAjax.widget._xhrGet( uri, false,
+                function(text){
+                    text = text.replace(/__WID__/g, that._id).replace(/@@(\w+)(?:\((\w+)\))?@@/g, _propReplace);
+                    that._widgetContext.body.content = that._extractScripts(text);
+                    that._widgetContext.runDeferredScripts();
+                },
+                function(err){
+                    target.innerHTML = "<b>An error occurred</b>"; // XXX TODO
+                    console.error(err);
+                    return;
+                }
+            );
+        } else {
+            var text = content._content_.replace(/__WID__/g, this._id).replace(/@@(\w+)(?:\((\w+)\))?@@/g, _propReplace);
+            that._widgetContext.body.content = this._extractScripts(text);
+        }
+
+        if ( this._spec.javascript ) {
+            this._widgetContext.loadedCallbacks++;
+    
+            var scripts = [];
+            for ( i = 0; i < this._spec.javascript.length; i++ ) {
+                scripts.push( this._spec.javascript[i] );
+                var s = scripts[i];
+                if ( s .src ) {
+                    // relative URLs are assumed to be relative to widget XML file
+                    s.src = _resolveURI( s.src, this._spec._src_ );
+                } else {
+                    s.text = s._content_;
+                }
+            }
+            
+            // load <javascript> elements, but don't evaluate yet
+            OpenAjax.widget._loadScripts( scripts, false,
+                    function( scripts, success, error ) {
+                        if ( success ) {
+                            var jsBefore = 0, jsAfter = 0, jsEnd = 0;
+                            for ( var i = 0; i < scripts.length; i++ ) {
+                                var text = scripts[i].text.replace(/__WID__/g, that._id).replace(/@@(\w+)(?:\((\w+)\))?@@/g, _propReplace);
+                                switch ( scripts[i].location ) {
+                                    case "beforeContent":
+                                        that._widgetContext.body.jsBefore[ jsBefore++ ] = text;
+                                        break;
+                                    case "atEnd":
+                                        that._widgetContext.body.jsEnd[ jsEnd++ ] = text;
+                                        break;
+                                    default:
+                                    //case "afterContent":
+                                        that._widgetContext.body.jsAfter[ jsAfter++ ] = text;
+                                        break;
+                                }
+                            }
+                            that._widgetContext.runDeferredScripts();
+                            return;
+                        }
+                        // XXX handle error
+console.error( error );
+                    },
+                    false // doEval
+            );
+        }
+    },
+
+    _loadCSS: function( data, uri )
+    {
+        if (uri) {
+            var link = document.createElement('LINK');
+            link.setAttribute('rel', 'stylesheet');
+            link.setAttribute('type', 'text/css');
+            link.setAttribute('href', uri);
+            _head.appendChild(link);
+        } else {
+            var style = document.createElement('STYLE');
+            if (!window.attachEvent) { //XXX FIXME: odd test
+                style.text = data;
+            } else {
+                document.styleSheets[document.styleSheets.length - 1].cssText = data;
+            }
+            _head.appendChild(style);
+        }
+    },
+
+    _extractScripts: function( text )
+    {
+//XXX TODO: avoid SCRIPT in <!-- -->
+// XXX See old version of createGadget() in minimashup.js, where we create a DOM
+//     node (DIV), inject the HTML code and use DOM APIs to acquire and remove
+//     the script elements.  This should get around the issue of accidentally
+//     matching <script> in comments.
+        var that = this;
+        return text.replace(/<script\s*(?:[^>]*?(?:src=(['"]?)([^>]*?)\1[^>]*)?)*>([\s\S]*?)<\/script>/gi, function(ignore, delim, src, code){
+            if (src) {
+                OpenAjax.widget._xhrGet( src, false,
+                    function(text){
+                        that._widgetContext.body.jsContent.push( text );
+                    },
+                    function(err) {
+                        console.error(err); // XXX TODO
+                    }
+                );
+            } else {
+                that._widgetContext.body.jsContent.push(code);
+            }
+            return "";
+        });
+    },
+    
+    _setAvailableDimensions: function( availDimensions )
+    {
+        if ( availDimensions.width ) {
+            this._availableDimensions.width = availDimensions.width;
+        } else {
+            delete this._availableDimensions.width;
+        }
+        if ( availDimensions.height ) {
+            this._availableDimensions.height = availDimensions.height;
+        } else {
+            delete this._availableDimensions.height;
+        }
+    },
+
+    _unload: function( callback ) {
+        if ( this._widget.onUnload ) {
+            try {
+                this._widget.onUnload( {} );
+            } catch(e) {}
+        }
+        _hub.removeContainer( this._container );
+        delete _widgetTable[ this._id ];
+        callback( this._id );
+    }
+};
+
+////////////////////////////////////////////////////////////////////////////
+//    ProxyWidget
+////////////////////////////////////////////////////////////////////////////
+
+var ProxyWidget = function() {};
+
+ProxyWidget.prototype = new BaseWidget();
+
+  //*** OpenAjax Metadata Widget APIs ***//
+
+ProxyWidget.prototype.adjustDimensions = function( dimensions )
+{
+    dimensions = BaseWidget.prototype.adjustDimensions.apply( this, arguments );
+    if ( dimensions ) {
+        _hub.publish( "openajax.widget." + this._id + "._sizeChanged", dimensions );
+    }
+};
+
+ProxyWidget.prototype.setPropertyValue = function(name, value)
+{
+    if ( this._setPropertyValue( name, value, false, false ) ) {
+        _hub.publish( "openajax.widget." + this._id + "._propValueChange.proxy",
+                { p: name, v: this._encodePropValue( name, value ) } );
+    }
+};
+
+  //*** private functions ***//
+
+ProxyWidget.prototype._init = function( args )
+{
+    BaseWidget.prototype._init.apply( this, arguments );
+    
+    // create a dummy widget instance
+    var widget = {
+        OpenAjax: this
+    };
+    this._widget = widget;
+    _widgetTable[ this._id ] = widget;
+};
+
+ProxyWidget.prototype._connectToHub = function()
+{
+    var widgetBaseURI = encodeURIComponent( this._spec._src_.slice( 0, this._spec._src_.lastIndexOf("/") + 1 ));
+    //AP var stubURI = _loaderRoot + "widget.html?oawb=" + widgetBaseURI + "&oawh=" + encodeURIComponent( _hubBaseJS );
+    var stubURI = "http://localhost/js/widget.html?oawb=" + widgetBaseURI + "&oawh=" + encodeURIComponent( _hubBaseJS );
+
+    this._container = new OpenAjax.hub.IframeContainer( _hub, this._id,
+            {   Container: {
+                    onSecurityAlert: function( source, alertType ) {
+                        console.log( "onSecurityAlert: s=" + source.getClientID() + " a=" + alertType );
+                    },
+                    scope: this,
+                    log: function( msg ) { console.log( msg ); }
+                },
+                IframeContainer: {
+                    uri: stubURI,
+                    tunnelURI: _tunnelURI,
+                    iframeAttrs: {
+                            frameBorder: "0",
+                            scrolling: "no",
+                            style: { width: "100%", height: "100%" }
+                        },
+                    parent: this._rootElement
+                }
+            }
+    );
+    
+    this._listenForEvents();
+};
+
+ProxyWidget.prototype._createHubSubObject = function() {};
+ProxyWidget.prototype._handlePropSubscriptions = function() {};
+
+ProxyWidget.prototype._listenForEvents = function()
+{
+    this._subs = [];
+    var prefix = "openajax.widget." + this._id;
+    
+    var sid = _hub.subscribe( prefix + "._instantiated",
+            function( topic, data ) {
+                _hub.publish( prefix + "._init",
+                        {   _spec: this._spec,
+                            _properties: this._properties,
+                            _sentinel: this._sentinel,
+                            _subscriptions: this._subscriptions,
+                            _availableDimensions: this._availableDimensions,
+                            _proxy: _proxyURL
+                        }
+                );
+                _hub.unsubscribe( sid );
+            },
+            this
+    );
+    
+    this._subs.push( _hub.subscribe( prefix + ".api.*", this._apiCall, this ) );
+    
+    this._subs.push( _hub.subscribe( prefix + "._propValueChange.remote",
+            function( topic, data ) {
+                this._properties[ data.p ] = this._decodePropValue( data.p, data.v );
+            },
+            this
+    ));
+};
+
+ProxyWidget.prototype._render = function( target, view, onComplete )
+{
+    // Call onComplete when the remote widget has finished loading
+    if ( onComplete ) {
+        var sid = _hub.subscribe(
+                "openajax.widget." + this._id + "._loaded",
+                function( topic, data ) {
+                    onComplete( this._widget );
+                    _hub.unsubscribe( sid );
+                },
+                this
+        );
+    }
+};
+
+ProxyWidget.prototype._apiCall = function( topic, data )
+{
+    var api = topic.slice( topic.lastIndexOf(".") + 1 );
+    this[ api ].call( this, data );
+};
+
+ProxyWidget.prototype._setAvailableDimensions = function( availDimensions )
+{
+    BaseWidget.prototype._setAvailableDimensions.apply( this, arguments );
+    _hub.publish( "openajax.widget." + this._id + "._availDimensions",
+            this._availableDimensions );
+};
+
+ProxyWidget.prototype._unload = function( callback )
+{
+    var that = this;
+    function finishUnload() {
+        _hub.removeContainer( that._container );
+        for ( var i = 0; i < that._subs.length; i++ ) {
+            _hub.unsubscribe( that._subs[i] );
+        }
+        delete _widgetTable[ that._id ];
+        callback( that._id );
+    }
+    
+    var prefix = "openajax.widget." + this._id;
+    
+    // XXX set a timeout in case RemoteWidget never responds?
+    this._subs.push( _hub.subscribe( prefix + "._unloaded",
+            function( topic, data ) {    // onData
+                // RemoteWidget finished unloading
+                finishUnload();
+            },
+            this,
+            function( item, success, errCode ) {    // onComplete
+                if ( ! success ) {
+                    // something went wrong -- log error and invoke callback
+                    // XXX TODO log error
+                    finishUnload();
+                }
+            }
+    ));
+    
+    _hub.publish( prefix + "._unload", null );
+};
+
+////////////////////////////////////////////////////////////////////////////
+//    RemoteWidget
+////////////////////////////////////////////////////////////////////////////
+
+var RemoteWidget = function( target )
+{
+    this._rootElement = target;
+    this._proxyPropChange = false;
+    
+    this._hubClient = new OpenAjax.hub.IframeHubClient({
+            HubClient: {
+                onSecurityAlert: function( source, alertType ) {
+                    console.log( "onSecurityAlert: s=" + source.getClientID() + " a=" + alertType );
+                },
+                scope: this,
+                log: function(msg) { console.log( msg ); }
+            }
+    });
+    
+    this._id = this._hubClient.getClientID();
+    
+    this._hubClient.connect(
+            function( item, success, errorCode ) {
+                // XXX handle error
+                // first, subscribe to "_init" msg from parent
+                var topicPrefix = "openajax.widget." + this._id;
+                this._initSub = this._hubClient.subscribe(
+                        topicPrefix + "._init",
+                        this._init,
+                        this
+                );
+                
+                // then, let parent know that we are ready
+                this._hubClient.publish( topicPrefix + "._instantiated", null );
+            },
+            this
+    );
+};
+
+RemoteWidget.prototype = new BaseWidget();
+
+  //*** OpenAjax Metadata Widget APIs ***//
+   
+RemoteWidget.prototype.adjustDimensions = function( dimensions )
+{
+    this._hubClient.publish( "openajax.widget." + this._id + ".api.adjustDimensions", dimensions );
+};
+
+  //*** private functions ***//
+
+RemoteWidget.prototype._init = function( topic, data )
+{
+    this._hubClient.unsubscribe( this._initSub );
+    delete this._initSub;
+    
+    // mixin received object with 'this'
+    for ( var prop in data ) {
+        if ( ! (prop in this) ) {
+            this[ prop ] = data[ prop ];
+        }
+    }
+    
+    _proxyURL = this._proxy;
+    delete this._proxy;    // XXX handle this better
+    
+    this._createHubSubObject();
+    this._handlePropSubscriptions();
+    this._listenForEvents();
+    
+    // Add widget to page
+    // _render() calls the widget objects "onLoad" method.
+    var that = this;
+    this._render( this._rootElement, /*view*/ null,
+            function() { // onComplete
+                that._hubClient.publish( "openajax.widget." + that._id + "._loaded", null );
+            }
+    );
+    
+    // set widget size
+    this._rootElement.style.width = this._spec.width + "px";
+    this._rootElement.style.height = this._spec.height + "px";
+};
+
+// already connected to hub in constructor - nothing to do here
+RemoteWidget.prototype._connectToHub = function() {};
+
+RemoteWidget.prototype._listenForEvents = function()
+{
+    var topicPrefix = "openajax.widget." + this._id;
+    
+    // widget has been resized
+    this._hubClient.subscribe( topicPrefix + "._sizeChanged", this._sizeChanged, this);
+    
+    // update to the available (max) dimensions for this widget
+    this._hubClient.subscribe( topicPrefix + "._availDimensions",
+            function( topic, data ) {
+                this._availableDimensions = data;
+            },
+            this
+    );
+    
+    // ProxyWidget has updated property value
+    this._hubClient.subscribe( topicPrefix + "._propValueChange.proxy",
+            function( topic, data ) {
+                this._proxyPropChange = true;
+                this.setPropertyValue( data.p, this._decodePropValue( data.p, data.v ) );
+                this._proxyPropChange = false;
+            },
+            this
+    );
+    
+    this._hubClient.subscribe( topicPrefix + "._unload", this._unload, this );
+};
+
+RemoteWidget.prototype._setPropertyValue = function( name, value, notify, self )
+{
+    var changed = BaseWidget.prototype._setPropertyValue.apply( this, arguments );
+    if ( changed && ! this._proxyPropChange ) {
+        this._hubClient.publish( "openajax.widget." + this._id + "._propValueChange.remote",
+                { p: name, v: this._encodePropValue( name, value ) }
+        );
+    }
+    return changed;
+};
+
+RemoteWidget.prototype._sizeChanged = function( topic, data )
+{
+    // If the widget object has a 'sizeChanged' method, then we need to save
+    // the current dimensions, before changing them.
+    if ( this._widget.onSizeChanged ) {
+        var oldDimensions = this.getDimensions();
+    }
+    
+    // change dimensions based on data from parent
+    BaseWidget.prototype.adjustDimensions.call( this, data );
+    
+    if ( this._widget.onSizeChanged ) {
+        var newDimensions = this.getDimensions();
+        this._widget.onSizeChanged.call(
+                this._widget,
+                {  oldWidth: oldDimensions.width,
+                   oldHeight: oldDimensions.height,
+                   newWidth:  newDimensions.width,
+                   newHeight: newDimensions.height
+                }
+        );
+    }
+};
+
+RemoteWidget.prototype._unload = function()
+{
+    if ( this._widget.onUnload ) {
+        try {
+            this._widget.onUnload( {} );
+        } catch(e) {}
+    }
+    
+    this._hubClient.publish( "openajax.widget." + this._id + "._unloaded",
+            null );
+};
+
+OpenAjax.widget._createRemoteWidget = function( target )
+{
+    return new RemoteWidget( target );
+};
+
+})();
+
+
+// remove object that may have been created previously (in case of widget.html)
+if ( typeof window.__openajax_widget__ !== "undefined" ) {
+    try {
+        window.__openajax_widget__ = null;
+        delete window.__openajax_widget__;
+    } catch(e) {}
+}
+
+} // OpenAjax !== "undefined"
+
+
+var oaw;
+if ( typeof OpenAjax === "undefined" ) {
+    oaw = window.__openajax_widget__ = {};
+} else {
+    oaw = OpenAjax.widget;
+}
+
+////////////////////////////////////////////////////////////////////////////
+//    _xhrGet
+////////////////////////////////////////////////////////////////////////////
+
+/**
+ * @memberOf OpenAjax.widget
+ * 
+ * @param {String} url
+ * @param {Boolean} forceXml
+ * @param {Function} onComplete
+ * @param {Function} onError
+ */
+oaw._xhrGet = function(url, forceXml, onComplete, onError) {
+    var activeX = "ActiveXObject" in window;
+
+    //TODO: what happens to namespaces on various browsers?
+    var toXml = function(xhr){
+        var result = xhr.responseXML;
+        if (activeX && (!result || !result.documentElement)){
+            var dom = new ActiveXObject("Microsoft.XMLDOM");
+            dom.async = false;
+            dom.loadXML(xhr.responseText);
+            result = dom;
+        }
+
+        if (result && result.documentElement.tagName == "parsererror") { // Annoying Mozilla behavior
+            throw result.documentElement.firstChild.nodeValue;
+        }
+        if (!result) {
+            throw "Parser error";
+        }
+
+        return result;
+    };
+
+    var xhr = ((typeof XMLHttpRequest == "undefined" || !location.href.indexOf("file:")) && activeX) ?
+        new ActiveXObject("Msxml2.XMLHTTP") : new XMLHttpRequest();
+    onError = onError || function(e) { console.error(e); };
+
+
+    xhr.onreadystatechange = function() {
+        if (xhr.readyState == 4) {
+            if (!xhr.status || xhr.status == 200) {
+                try {
+                    onComplete(forceXml ? toXml(xhr) : xhr.responseText);
+                } catch(e) {
+                    onError(e);
+                }
+            } else {
+                onError(new Error("Unable to load " + url + " status:" + xhr.status));
+            }
+        }
+    };
+    if ( forceXml && xhr.overrideMimeType ) {
+        xhr.overrideMimeType("text/xml");
+    } 
+    xhr.open("GET", url, true);
+    try {
+        xhr.send(null);
+    } catch(e) {
+        onError(e);
+    }
+};
+
+////////////////////////////////////////////////////////////////////////////
+//    _loadScripts
+////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Load all of the given scripts, making sure they are evaluated in order.
+ * 
+ * @memberOf OpenAjax.widget
+ * 
+ * @param {Object[]} scripts
+ *     An array of scripts.  Each array element is an object which must have
+ *     either a "text" property (the full script text) or a "src"
+ *     property (URL of script).
+ * @param {Boolean} [xdomain="false"]
+ *     If true, signifies that the given scripts array may contain cross-domain
+ *     URLs.  If false, it is assumed that all script URLs are within the
+ *     current domain.
+ * @param {Function} [onComplete]
+ *     Callback function invoked on successful completion or error. The first
+ *     parameter is the original 'scripts' array; each script now has a valid
+ *     'text' property (when 'xdomain' is true, this may not be correct).
+ *     Syntax is as follows:
+ *     onComplete( //Object[]// scripts, //Boolean// success, //Error|String// error )  
+ * @param {Boolean} [doEval="true"]
+ *     By default, the scripts are evaluated after being loaded. Specify "false"
+ *     to prevent evaluation.
+ */
+oaw._loadScripts = function( scripts, xdomain, onComplete, doEval )
+{
+    // For scripts that may be cross-domain, load them one-by-one  -- this
+    // maintains the proper order.
+    if ( xdomain ) {
+        var head = document.getElementsByTagName('HEAD').item(0);
+        function addScript( scripts, idx ) {
+            if ( idx == scripts.length ) {
+                if ( onComplete ) {
+                    onComplete( scripts, true );
+                }
+                return;
+            }
+            
+            var script = document.createElement( 'SCRIPT' );
+            script.setAttribute( 'type', 'text/javascript' );
+            if ( scripts[idx].text ) {
+                script.text = scripts[idx].text;
+                head.appendChild(script);
+                addScript( scripts, idx + 1 );
+            } else {
+                script.setAttribute( 'src', scripts[idx].src );
+                script.onload = script.onreadystatechange = function(e) {
+                    if ((e && e.type == "load") || /complete|loaded/.test(script.readyState)) {
+                        addScript( scripts, idx + 1 );
+                    }
+                };
+                head.appendChild(script);
+            }
+        }
+        
+        addScript( scripts, 0 );
+    }
+
+    // If there are no cross-domain scripts, then use async XHR to load the
+    // scripts, but make sure that they are evaluated in the proper order.
+    else {
+        doEval = (typeof doEval !== "undefined") ? doEval : true;
+        
+        var nextIdx = 0;
+        function evalNextScript( idx ) {
+            if ( idx === nextIdx ) {
+                while ( nextIdx < scripts.length && scripts[ nextIdx ].text ) {
+                    if ( doEval ) {
+                        oaw._runScript( scripts[ nextIdx ].text,
+                                function( errorMsg ) {
+                                    onComplete( scripts, false, errorMsg );
+                                }
+                        );
+                    }
+                    nextIdx++;
+                }
+
+                if ( onComplete && nextIdx == scripts.length ) {
+                    onComplete( scripts, true );
+                }
+            }
+        }
+        
+        function getAndEval( idx ) {
+            var s = scripts[idx];
+            oaw._xhrGet( s.src, false,
+                    function( text ) { // onComplete
+                        s.text = text;
+                        evalNextScript( idx );
+                    },
+                    function( err ) { // onError
+                        if ( onComplete ) {
+                            onComplete( scripts, false,
+                                    "Failed to retrieve script, with error: " + err.toString() +
+                                    "\nscript src = " + s.src );
+                        }
+                    }
+            );
+        }
+        
+        for ( var i = 0; i < scripts.length; i++ ) {
+            var s = scripts[i];
+            if ( s.text ) {
+                evalNextScript( i );
+            } else {
+                getAndEval( i );
+            }
+        }
+    }
+};
+
+////////////////////////////////////////////////////////////////////////////
+//    _runScript
+////////////////////////////////////////////////////////////////////////////
+
+oaw._runScript = (function(){
+    // Test window.eval first, since this is the standards compliant way of
+    // running scripts.
+    if ( window.eval ) {
+        window.eval( "function __openajax_widget_fn__() {};" );
+        if ( window.__openajax_widget_fn__ ) {
+            delete window.__openajax_widget_fn__;
+            return function( text ) {
+                window.eval( text );
+            };
+        }
+    }
+    
+    // fallbacks
+    
+    // Next, see if the browser provides the execScript function (IE).
+    if ( window.execScript ) {
+        return function( text ) {
+            window.execScript( text );
+        };
+    }
+    
+    // Lastly, if all else fails, dynamically add script to HEAD
+    // (i.e. Safari 3.2).
+    var head = document.getElementsByTagName('HEAD').item(0);
+    return function( text ) {
+        var script = document.createElement( 'SCRIPT' );
+        script.setAttribute( 'type', 'text/javascript' );
+        script.text = text;
+        head.appendChild( script );
+    };
+})();
diff --git a/UNGProject/js/minimashup.js b/UNGProject/js/minimashup.js
new file mode 100644
index 0000000000000000000000000000000000000000..7904984285ccf314e43d7f13d8a9103699272635
--- /dev/null
+++ b/UNGProject/js/minimashup.js
@@ -0,0 +1,1889 @@
+/*
+
+        Copyright 2006-2009 OpenAjax Alliance
+
+        Licensed under the Apache License, Version 2.0 (the "License"); 
+        you may not use this file except in compliance with the License. 
+        You may obtain a copy of the License at
+        
+                http://www.apache.org/licenses/LICENSE-2.0
+
+        Unless required by applicable law or agreed to in writing, software 
+        distributed under the License is distributed on an "AS IS" BASIS, 
+        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+        See the License for the specific language governing permissions and 
+        limitations under the License.
+*/
+
+/**
+ * The Wiring Overlay class does the work to overlay a gadget with a
+ * semi-transparent DIV.  Through a context menu on the DIV, the user can
+ * express a desire to wire one or more gadgets to the currently selected
+ * property on the Property Dialog of a gadget.  Any wiring changes will be
+ * committed once the user selects 'save' from the Property Dialog
+ *
+ * @class WiringOverlay
+ */
+function  WiringOverlay(/* Gadget */gadget, topic, /* boolean */publisher)
+{
+    // Create a DIV overlay that covers the given gadget.  We are overlaying the
+    // gadget because we are overlaying gadgets that publish (if publisher is
+    // true) or listen (if publisher is false) the given topic.
+    if (!gadget) {
+        return;
+    }
+
+    var container = gadget.getSite().getContainer();
+    var gadgetCoords = dojo.coords(container, true);
+    var overlay = document.createElement('div');
+    overlay.id = gadget.getId()+'_overlay';
+    overlay.style.left = gadgetCoords.x;
+    overlay.style.top = gadgetCoords.y;
+    overlay.style.width = gadgetCoords.w;
+    overlay.style.height = gadgetCoords.h;
+    var zIndex = container.style.zIndex;
+    if (zIndex) {
+        overlay.style.zIndex = zIndex+1;
+    } else {
+        overlay.style.zIndex = 1;
+    }
+    overlay.style.position = 'absolute';
+    Browser.setAlpha(overlay, 0.6);
+    dojo.body().appendChild(overlay);
+    this.gadget = gadget;
+    this.topic = topic;
+    this.publish = publisher;
+    this.element = overlay;
+    // If we got to the point of creating an overlay, then we know that this
+    // gadget is a possible match for wiring at least.  The type may be further
+    // improved as we inspect the gadget's properties while building the context
+    // menu.
+    this.setType(WiringOverlay.POSSIBLE);
+}
+
+WiringOverlay.CURRENT     = 1;
+WiringOverlay.RECOMMENDED = 2;
+WiringOverlay.POSSIBLE    = 3;
+WiringOverlay.WIRING_NONE   = 0;
+WiringOverlay.WIRING_SINGLE = 1;
+WiringOverlay.WIRING_MULTI  = 2;
+
+WiringOverlay.prototype.setType = function(/* int */type)
+{
+    switch(type)
+    {
+    case WiringOverlay.CURRENT:
+        this.element.className = 'nomadWiringOverlayCurrent';
+        this.type = type;
+        break;
+    case WiringOverlay.RECOMMENDED:
+        this.element.className = 'nomadWiringOverlayRecommended';
+        this.type = type;
+        break;
+    case WiringOverlay.POSSIBLE:
+        this.element.className = 'nomadWiringOverlayPossible';
+        this.type = type;
+        break;
+    }
+}
+
+WiringOverlay.prototype.destroy = function()
+{
+    if (this.popupMenu) {
+        dojo.forEach(this.popupMenu.getChildren(),
+                     function(menuItem){
+                         if (menuItem.popup) {
+                             menuItem.popup.destroyRecursive();
+                         }
+                     }
+                    );
+        this.popupMenu.destroyRecursive();
+        this.popupMenu = null;
+    }
+    if (this.tooltip) {
+        this.tooltip.destroy();
+        this.tooltip = null;
+    }
+    dojo.body().removeChild(this.element);
+    this.gadget = null;
+    this.element = null;
+}
+
+WiringOverlay.prototype.enable = function(/* int */zIndex)
+{
+    // Get the overlay ready so that the user can interact with it.  If zIndex
+    // is specified, then this is the level to which we need to raise the overlay
+    // so that it isn't hidden by some other window
+    if (zIndex) {
+        this.element.style.zIndex = zIndex;
+    }
+    if (!this.publish) {
+        this.popupMenu = this.createListenerContextMenu();
+    } else {
+        this.popupMenu = this.createPublisherContextMenu();
+    }
+
+    this.tooltip = this.createTooltip();
+}
+
+WiringOverlay.prototype.createTooltip = function()
+{
+    var label = null;
+    switch (this.type) {
+    case WiringOverlay.CURRENT:
+        if (this.publish) {
+            label = 'This gadget publishes the topic '+this.topic+' which is currently bound to the selected property.'
+        } else {
+            label = 'This gadget currently listens to the topic '+this.topic+' which is currently published by the selected property.'
+        }
+        break;
+    case WiringOverlay.RECOMMENDED:
+        if (this.publish) {
+            label = 'This gadget publishes the topic '+mashupMaker.getWiringManager().wiringProperty.defaultTopic()+' which is recommended for binding to the selected property.'
+        } else {
+            label = 'This gadget by default listens to the topic '+this.topic+' which is currently published by the selected property.  However, it is not currently listening for this topic.'
+        }
+        break;
+    case WiringOverlay.POSSIBLE:
+        if (this.publish) {
+            label = 'This gadget publishes other topics that may be bound to the selected property.'
+        } else {
+            label = 'This gadget is able to listen to the topic '+this.topic+' but it does not currently do so.'
+        }
+        break;
+    }
+
+    if (!label) {
+        return;
+    }
+
+    if (this.publish) {
+        label += '  Caution should be used when selecting a non-recommended topic for binding.'
+    } else if (this.type == WiringOverlay.POSSIBLE) {
+        label += '  Caution should be used when asking a gadget to listen for a non-recommended topic.'
+    }
+    label += '  Bring up a context menu for further options.'
+
+    var tooltip = new dijit.Tooltip({
+        label: label,
+        connectId: [this.element.id]
+    });
+    tooltip.domNode.id = "overlayTooltip";
+    return tooltip;
+}
+
+WiringOverlay.prototype.createPublisherContextMenu = function()
+{
+    // this function builds the context menu for the overlay and also initializes
+    // the type for the overlay
+    var topic = this.topic;
+    if (topic === null) {
+        return null;
+    }
+
+    var menu = new dijit.Menu({
+        id: 'wiring_publishing_menu'+this.gadget.getId(),
+        targetNodeIds: [this.element.id]
+    });
+    if (!menu) {
+        return null;
+    }
+
+    var properties = this.gadget.OpenAjax._spec.property;
+    var wiringManager = mashupMaker.getWiringManager();
+    var boundGadget = null;
+    var oldTopic = null;
+    if (wiringManager.wiringProperty) {
+        boundGadget = mashupMaker.getWidgetModelFromID(getPropertyInfo(wiringManager.wiringProperty, "singleBoundGadget"));
+        oldTopic = getPropertyInfo(wiringManager.wiringProperty, "topic");
+    }
+    var newType = this.type,
+        currType = this.type;
+    // use topicList to make sure that even if a topic is published more than
+    // once by the gadget, that it still only appears once on the list
+    var topicList = {};
+    for ( var name in properties ) {
+        var property = properties[ name ];
+        var state = null;
+//        if (property.publish()) {
+//            var publishedTopic = property.defaultTopic();
+        if ( property.sharedAs ) {
+            var publishedTopic = property.sharedAs;
+            if (publishedTopic === null || topicList[publishedTopic]) {
+                continue;
+            }
+            // assign menuitem.initChecked prior to menu.startup()
+            var menuitem = null;
+            menuitem = new nomad.widget.CheckmarkMenuItem({
+                label: 'Publishes topic '+publishedTopic,
+                onClick: dojo.hitch(wiringManager, "registerWiringChange", wiringManager.wiringProperty, publishedTopic, oldTopic, this.gadget)
+            });
+            topicList[publishedTopic] = menuitem;
+            var checkable = publishedTopic == this.topic;
+            // see if the overlay's type can be improved
+            if (checkable) {
+                if (!boundGadget) {
+                    newType = WiringOverlay.CURRENT;
+                } else if (boundGadget == this.gadget) {
+                    newType = WiringOverlay.CURRENT;
+                    menuitem.initChecked = true;
+                } else if (publishedTopic == wiringManager.wiringProperty.defaultTopic()) {
+                    newType = WiringOverlay.RECOMMENDED;
+                }
+            } else if (publishedTopic == wiringManager.wiringProperty.defaultTopic()) {
+                newType = WiringOverlay.RECOMMENDED;
+            }
+            if (newType < currType) {
+                currType = newType;
+            }
+            menu.addChild(menuitem);
+        }
+    }
+    if (currType < this.type) {
+        this.setType(currType);
+    }
+    menu.startup();
+    return menu;
+}
+WiringOverlay.prototype.createListenerContextMenu = function()
+{
+    var topic = this.topic;
+    if (!topic || topic.length == 0) {
+        return;
+    }
+
+    var menu = new dijit.Menu({
+        id: 'wiring_listener_menu'+this.gadget.getId(),
+        targetNodeIds: [this.element.id]
+    });
+    if (!menu) {
+        return null;
+    }
+
+    var properties = this.gadget._spec.property;
+    var wiringProperty = mashupMaker.getWiringManager().wiringProperty;
+    var newType = this.type,
+        currType = this.type;
+    for ( var name in properties ) {
+        var property = properties[ name ];
+        var state = null;
+//        if (property.listen() && !property.hidden()) {
+        if ( property.sharedAs && !property.hidden ) {
+            if (getPropertyInfo(property, "topic") == topic) {
+                if (getPropertyInfo(property, "singleBoundGadget")) {
+                    if (getPropertyInfo(property, "singleBoundGadget") == wiringProperty.getGadget().getId()) {
+                        state = WiringOverlay.WIRING_SINGLE;
+                        newType = WiringOverlay.CURRENT;
+//                    } else if (property.defaultTopic() == topic) {
+                    } else if (property.sharedAs == topic) {
+                        state = WiringOverlay.WIRING_NONE;
+                        newType = WiringOverlay.RECOMMENDED;
+                    }
+                } else {
+                    state = WiringOverlay.WIRING_MULTI;
+                    newType = WiringOverlay.CURRENT;
+                }
+//            } else if (property.defaultTopic() == topic) {
+            } else if (property.sharedAs == topic) {
+                state = WiringOverlay.WIRING_NONE;
+                newType = WiringOverlay.RECOMMENDED;
+            } else {
+                // XXX should we allow a publisher to publish a non-recommended topic
+                // to any ol' listener?  For now we'll allow it
+                state = WiringOverlay.WIRING_NONE;
+            }
+
+            if (state != null) {
+                var popupmenu = this.createListenerSubmenu(topic, property, getPropertyInfo(property, "topic"), state);
+                var menuitem = new dijit.PopupMenuItem({
+                    label: 'binding for property '+property.name,
+                    popup: popupmenu
+                });
+                // see if the overlay's type can be improved
+                if (newType < currType) {
+                    currType = newType;
+                }
+                menu.addChild(menuitem);
+            }
+        }
+    }
+    if (currType < this.type) {
+        this.setType(currType);
+    }
+
+    menu.startup();
+    return menu;
+}
+WiringOverlay.prototype.createListenerSubmenu = function(topic, property, originalTopic, /* int */checkedState)
+{
+    var menu = new dijit.Menu({
+        id: 'wiring_listener_popup_'+this.gadget.getId()+'_'+property.name
+    });
+    if (!menu) {
+        return null;
+    }
+
+    var wiringManager = mashupMaker.getWiringManager();
+
+    // assign menuitem.initChecked prior to menu.startup()
+    var menuitem = null;
+    menuitem = new nomad.widget.CheckmarkMenuItem({
+        label: 'Listen for all '+topic+' topics',
+        onClick: dojo.hitch(wiringManager, "registerWiringChange", property, topic, originalTopic, null)
+    });
+    menuitem.initChecked = checkedState == WiringOverlay.WIRING_MULTI;
+    menu.addChild(menuitem);
+    menuitem = new nomad.widget.CheckmarkMenuItem({
+        label: 'Listen for no '+topic+' topics',
+        onClick: dojo.hitch(wiringManager, "registerWiringChange", property, "", originalTopic, null)
+    });
+    menuitem.initChecked = checkedState == WiringOverlay.WIRING_NONE;
+    menu.addChild(menuitem);
+    menuitem = new nomad.widget.CheckmarkMenuItem({
+        label: 'Bind to source gadget only',
+        handleEveryClick: true,
+        onClick: dojo.hitch(wiringManager, "registerWiringChange", property, topic, originalTopic, wiringManager.wiringProperty.getGadget())
+    });
+    menuitem.initChecked = checkedState == WiringOverlay.WIRING_SINGLE;
+    menu.addChild(menuitem);
+    // need to call startup here as startup won't filter down through a
+    // dijit.PopupMenuItem to its submenu
+    menu.startup();
+    return menu;
+}
+
+getPropertyInfo = function(property, /* string */key)
+{
+  // In order to make the overlays look and work correctly, we'll sometimes need
+  // to know about any pending changes to the property that may not have taken
+  // affect, yet.  This is especially true when trying to get the overlay
+  // type correct and to have the context menus initialize with the currently
+  // selected item correctly identified.
+  if (!property || !key) {
+    return;
+  }
+  
+  var change = mashupMaker.getWiringManager().getWiringChange(property);
+  switch (key) {
+    case "topic":
+      if (change) {
+        return change.newTopic;
+      }
+//      return property.topic();
+      return property.sharedAs;
+    case "singleBoundGadget":
+      if (change) {
+        return change.publishingGadget.getId();
+      }
+      return property.getSingleBoundGadget();    // XXX JHP TODO
+    default:
+      return null;
+  }
+}
+
+/**
+ * The Wiring Manager class encapsulates the work that needs to happen each time
+ * the property dialog rolls up so that the user can select gadgets to wire
+ * to the current gadget.
+ *
+ * @class WiringManager
+ */
+function  WiringManager()
+{
+  this._wireableGadgets = new Array();
+  this._subscribedTopics = null;
+  this._publishedTopics = null;
+  this._changeArray = null;
+}
+
+WiringManager.prototype.addGadget = function(gadget)
+{
+    if (!gadget) {
+        return;
+    }
+
+    // if the gadget publishes or subscribes to any topics, find out which and
+    // remember them
+//  var properties = gadget.getProperties();
+//  if ( properties ) {
+//      for (var i = 0; i < properties.length; i++) {
+//        var property = properties[i];
+//        if (property.listen() || property.publish()) {
+//          this._wireableGadgets[gadget.gID] = gadget;
+//          break;
+//        }
+//      }
+//  }
+    for ( var name in gadget.OpenAjax._spec.property ) {
+        var prop = gadget.OpenAjax._spec.property[ name ];
+        if ( prop.sharedAs ) {
+            this._wireableGadgets[ gadget.OpenAjax.getId() ] = gadget;
+            break;
+        }
+    }
+}
+
+WiringManager.prototype.buildTopicsLists = function()
+{
+    if (this._publishedTopics || this._subscribedTopics) {
+        return;
+    }
+    this._publishedTopics = new Array();
+    this._subscribedTopics = new Array();
+    for (var gID in this._wireableGadgets) {
+        var gadget = this._wireableGadgets[gID];
+      
+        var props = gadget.OpenAjax._spec.property;
+        for ( var name in props ) {
+            var topic = props[ name ].sharedAs;
+            if ( topic ) {
+                if ( ! this._publishedTopics[ topic ] ) {
+                    this._publishedTopics[ topic ] = {};
+                }
+                // make sure that a gadget only appears once on the list
+                if ( ! this._publishedTopics[ topic ][ gID ] ) {
+                    this._publishedTopics[ topic ][ gID ] = gadget;
+                }
+                
+                if ( ! this._subscribedTopics[ topic ] ) {
+                    this._subscribedTopics[ topic ] = {};
+                }
+                // make sure that a gadget only appears once on the list
+                if ( ! this._subscribedTopics[ topic ][ gID ] ) {
+                    this._subscribedTopics[ topic ][ gID ] = gadget;
+                }
+            }
+        }
+    }
+
+
+
+//    // if the gadget publishes or subscribes to any topics, find out which and
+//    // remember them
+//    var topicInfo = gadget.getTopicInfo();
+//    if (topicInfo) {
+//        // topicInfo is an object that contains two arrays, topics that the gadget
+//        // listens for and topics that the gadget publishes
+//        var topicsArray = topicInfo.publishes;
+//        if (topicsArray && topicsArray.length > 0) {
+//            var topicsLength = topicsArray.length;
+//            for (var j = 0; j < topicsLength; j++) {
+//                var topic = topicInfo.publishes[j];
+//          if (!this._publishedTopics[topic]) {
+//            this._publishedTopics[topic] = {};
+//                }
+//                // make sure that a gadget only appears once on the list
+//          if (!this._publishedTopics[topic][gadget.getId()]) {
+//            this._publishedTopics[topic][gadget.getId()] = gadget;
+//                }
+//            }
+//        }
+//
+//        topicsArray = topicInfo.subscribes;
+//        if (topicsArray && topicsArray.length > 0) {
+//            topicsLength = topicsArray.length;
+//            for (var j = 0; j < topicsLength; j++) {
+//                var topic = topicInfo.subscribes[j];
+//          if (!this._subscribedTopics[topic]) {
+//            this._subscribedTopics[topic] = {}
+//                }
+//                // make sure that a gadget only appears once on the list
+//          if (!this._subscribedTopics[topic][gadget.gID]) {
+//            this._subscribedTopics[topic][gadget.gID] = gadget;
+//          }
+//                }
+//            }
+//        }
+//    }
+}
+
+WiringManager.prototype.removeGadget = function(gadget)
+{
+    if (!gadget) {
+        return;
+    }
+
+    // if the gadget publishes or subscribes to any topics, find out which and
+  if (this._wireableGadgets[gadget.gID]) {
+    delete this._wireableGadgets[gadget.gID];
+    }
+}
+
+WiringManager.prototype.findGadgets = function(/* string */topic, /* boolean */publish)
+{
+    // If topic is specified, only gadgets related to that topic will be returned.
+    // If no topic, then all gadgets meeting the publish/listen requirement will
+    // be returned.
+    var results = new Array();
+    var topicArray = null;
+    var searchArray = null;
+
+    if (topic) {
+        searchArray = publish ? this._publishedTopics[topic] : this._subscribedTopics[topic];
+    } else {
+        topicArray = publish ? this._publishedTopics : this._subscribedTopics;
+    }
+    if (topicArray) {
+        for (var topic in topicArray) {
+            searchArray = topicArray[topic];
+            for (var gadgetId in searchArray) {
+              // since the same gadget can publish/subscribe to multiple topics,
+              // make sure that they are on the result list only once
+              if (!results[gadgetId]) {
+                results[gadgetId] = searchArray[gadgetId];
+              }
+            }
+        }
+    } else if (searchArray) {
+        for (var gadgetId in searchArray) {
+            if (searchArray[gadgetId]) {
+                results.push(searchArray[gadgetId]);
+            }
+        }
+    }
+    return results;
+}
+
+WiringManager.prototype.highlightTopic = function(/* string */topic, /* boolean */publishers, /* gadget */ignoreGadget)
+{
+    // overlay all of the gadgets that publish/subscribe the given topic and
+    // give them a type of WiringOverlay.CURRENT
+    if (!topic || topic.length == 0) {
+        return;
+    }
+
+    this._overlayGadgets(this.findGadgets(topic, publishers), topic, publishers, ignoreGadget);
+    if (this.overlays && this.overlays.length) {
+        var numOverlays = this.overlays.length;
+        for (var i = 0; i < numOverlays; i++) {
+            var overlay = this.overlays[i];
+            overlay.setType(WiringOverlay.CURRENT);
+        }
+    }
+}
+WiringManager.prototype.highlightGadgets = function(/* array */gadgets, /* string */topic, /* boolean */publishers)
+{
+    if (!gadgets) {
+        return;
+    }
+
+    this._overlayGadgets(gadgets, topic, publishers, null);
+    if (this.overlays && this.overlays.length) {
+        var numOverlays = this.overlays.length;
+        for (var i = 0; i < numOverlays; i++) {
+            var overlay = this.overlays[i];
+            overlay.setType(WiringOverlay.CURRENT);
+        }
+    }
+}
+WiringManager.prototype._overlayPotentialPublishers = function()
+{
+    // create overlays for all gadgets that could publish to the current
+    // wiring property, ignoring the gadget that contains the current wiring
+    // property
+  this._overlayGadgets(this.findGadgets(null, true), getPropertyInfo(this.wiringProperty, "topic"), true, this.wiringProperty.getGadget());
+}
+WiringManager.prototype._overlayPotentialListeners = function()
+{
+    // create overlays for all gadgets that could publish to the current
+    // wiring property, ignoring the gadget that contains the current wiring
+    // property
+    this._overlayGadgets(this.findGadgets(null, false), this.wiringProperty.defaultTopic(), false, this.wiringProperty.getGadget());
+}
+WiringManager.prototype.unhighlightTopic = function()
+{
+    this.unhighlightGadgets();
+}
+WiringManager.prototype.unhighlightGadgets = function()
+{
+    dojo.forEach(this.overlays,
+                 function(overlay, index, array) {
+                     overlay.destroy();
+                     delete overlay;
+                 }
+                );
+    this.overlays = null;
+}
+
+WiringManager.prototype._overlayGadgets = function(/* array of gadgets */gadgetArray, topic, /* boolean */publishers, /* gadget */ignoreGadget)
+{
+    var overlays = new Array();
+    var currGadget;
+    if (typeof ignoreGadget === "undefined") {
+        currGadget = null;
+    } else {
+        currGadget = ignoreGadget;
+    }
+    
+    for (gadgetId in gadgetArray) {
+        var gadget = gadgetArray[gadgetId];
+        if (gadget != currGadget) {
+            var overlay = new WiringOverlay(gadget, topic, publishers);
+            overlays.push(overlay);
+        }
+    }
+    this.overlays = overlays;
+}
+
+WiringManager.prototype.stopWiringProperty = function()
+{
+    // Either the user has completed the wiring session or cancelled it.  But
+    // the dialog hasn't been dismissed, yet, so more wiring sessions could happen
+    // with the wiring gadget so keep the wiring changes around for now.
+    this.unhighlightTopic();
+}
+
+WiringManager.prototype.notifyWiringPropertyComplete = function()
+{
+    mashupMaker.hub.publish("nomad-wiring-property-complete", null);
+    this.stopWiringProperty();
+}
+
+WiringManager.prototype.wirePropertyToGadget = function(property, /* boolean */selectAPublishingGadget)
+{
+    var topic = null;
+    if (selectAPublishingGadget) {
+        topic = getPropertyInfo(property, "topic");
+    } else {
+        topic = property.defaultTopic();
+    }
+    if (topic == null) {
+        this.notifyWiringPropertyComplete();
+        return;
+    }
+    this.wiringProperty = property;
+
+    // Build overlays for each gadget that listen for topic and since they need
+    // to be clickable, set their zIndex to the zIndex of the dialog underlay.
+    // If the user is being asked to selectAPublishingGadget, only overlay
+    // gadgets that publish topics.  Otherwise we'll only overlay gadgets that
+    // could listen for the topic that the given property publishes.
+    if (selectAPublishingGadget) {
+        this._overlayPotentialPublishers();
+    } else {
+        this._overlayPotentialListeners();
+        //    this.highlightTopic(topic, selectAPublishingGadget, property.getGadget());
+    }
+    var dialogUnderlays = dojo.query("BODY > .dijitDialogUnderlayWrapper");
+    var zIndex = 0;
+    if (dialogUnderlays && dialogUnderlays.length) {
+        // have to ask for z-index this way, doesn't exist in the node.style object
+        zIndex = dojo.style(dialogUnderlays[0], "zIndex");
+        if (zIndex && zIndex.length) {
+            zIndex = parseInt(zIndex);
+        }
+    }
+    if (this.overlays && this.overlays.length) {
+        var numOverlays = this.overlays.length;
+        for (var i = 0; i < numOverlays; i++) {
+            var overlay = this.overlays[i];
+            overlay.enable(zIndex);
+        }
+    }
+}
+
+WiringManager.prototype.registerWiringChange = function(property, newTopic, originalTopic, publishingGadget)
+{
+    // Build a list of wiring changes that happened while this property editing
+    // session was in affect.  These will either be forgotten if the user decides
+    // to cancel or they will be committed when the changes are saved.
+    // These changes will be changes affecting the subscriptions that property
+    // has (i.e. topic subscribing to, gadget bound to, etc) since wiring doesn't
+    // affect publishing.
+    if (!property || newTopic == null || typeof publishingGadget === "undefined") {
+        return;
+    }
+
+    if (!this._changeArray) {
+        this._changeArray = new Array();
+    }
+    // Come up with a unique key.  We need to know if the change affects the input
+    // topic or the output topic of the property, too, since it is possible that
+    // a property will both listen and publish and the user might change both
+    // wirings.
+    var uniqueKey = property.getGadget().getId()+'_'+property.name;
+    this._changeArray[uniqueKey] = {property: property, newTopic: newTopic, oldTopic: originalTopic, publishingGadget: publishingGadget};
+
+    if (newTopic != originalTopic) {
+        var found = false;
+        var changedGadget = property.getGadget();
+//        var gadgetProperties = changedGadget.getProperties();
+//        for (var i = 0; i < gadgetProperties.length; i++) {
+//            var gadgetProperty = gadgetProperties[i];
+//            if (gadgetProperty.listen()) {
+//                if (gadgetProperty.name() != property.name() &&
+//                    gadgetProperty.topic() == originalTopic) {
+//                    // gadget still has a property that listens for this topic so keep
+//                    // it in the list
+//                    found = true;
+//                    break;
+//                }
+//            }
+//        }
+        var gadgetProperties = changedGadget.OpenAjax._spec.property;
+        for ( var name in gadgetProperties ) {
+            var gadgetProperty = gadgetProperties[ name ];
+            if ( gadgetProperty.sharedAs ) {
+                if ( name != property.name &&
+                    gadgetProperty.sharedAs == originalTopic) {
+                    // gadget still has a property that listens for this topic so keep
+                    // it in the list
+                    found = true;
+                    break;
+                }
+            }
+        }
+        // if this gadget no longer listens to oldTopic, remove it from the list
+        // of listeners
+        if (!found) {
+      delete this._subscribedTopics[originalTopic][changedGadget.gID];
+        }
+        // if this gadget isn't already on the list for newTopic, add it
+    if (!this._subscribedTopics[newTopic]) {
+      this._subscribedTopics[newTopic] = {};
+        }
+    if (!this._subscribedTopics[newTopic][changedGadget.getId()]) {
+      this._subscribedTopics[newTopic][changedGadget.getId()] = changedGadget;
+        }
+    }
+
+    this.notifyWiringPropertyComplete();
+}
+
+WiringManager.prototype.cancelWiringChanges = function()
+{
+    // This is called when the property dialog is dismissed so none of the
+    // accumulated changes should occur.
+    this.unhighlightGadgets();
+
+    this._changeArray = null;
+    this._publishedTopics = null;
+    this._subscribedTopics = null;
+    this.wiringProperty = null;
+}
+
+WiringManager.prototype.commitWiringChanges = function()
+{
+    var changeObj = null;
+    for (var property in this._changeArray) {
+        changeObj = this._changeArray[property];
+        changeObj.property.topic(changeObj.newTopic, changeObj.publishingGadget);
+    }
+    this.unhighlightGadgets();
+
+    this._changeArray = null;
+    this._publishedTopics = null;
+    this._subscribedTopics = null;
+    this.wiringProperty = null;
+}
+
+WiringManager.prototype.getWiringChange = function(property)
+{
+    if (!this._changeArray) {
+        return null;
+    }
+    var uniqueKey = property.getGadget().getId()+'_'+property.name;
+    if (this._changeArray[uniqueKey]) {
+        return this._changeArray[uniqueKey];
+    }
+    return null;
+}
+
+/**
+ * The Mashup Maker class encapsulate the reponsibility of the mashup canvas such as
+ * loading and creating gadgets and associating the gadgets with a layout.
+ *
+ * @class MashupMaker
+ */
+
+function MashupMaker()
+{
+    this.models = new Array();
+    this.isIE      = (navigator.userAgent.indexOf('MSIE')  != -1);
+    this._features = { editor: {file: 'editor.js'}};
+
+    // Not really used in the core code, yet...but we can now pass debug=true
+    // through newmashup.php to stop refimpldojo.js from loading.  If that
+    // happens, this member variable will be set.  So if we want to add more
+    // logging, etc. that we don't want to get rid of but isn't really necessary
+    // in the release, we can key off of this.
+    this._debug = false;
+
+    //config (for now need trailing '/')      
+
+    /*
+     * Resolving the base URL for gadgets
+     */
+    var index;
+    var loc = document.location.href.toString();
+    if ( document.location.search ) {
+        index = loc.indexOf( document.location.search );
+        loc = loc.substr( 0, index + 1 );
+    }
+    index = loc.lastIndexOf('/');
+    if (index != -1) {
+        OpenAjax.widget.baseURI = loc.substr(0, index + 1);
+    } else {
+        alert("Illegal location href:" + loc);
+    }
+    OpenAjax.widget.frameworkURI = OpenAjax.widget.baseURI + "../src/";
+
+    if (! this.propertyEditorURL) {
+        // if not property editor specified default to the simple one
+        this.propertyEditorURL = OpenAjax.widget.baseURI + 'gadgets/propertyeditor/propertyeditor_oam.xml';        
+    }
+    this.wiringManager = new WiringManager();
+
+    // instantiate managed hub instance
+    this.loader = new OpenAjax.widget.Loader({
+            ManagedHub: {
+                onPublish: this.onWidgetPublish,
+                onSubscribe: this.onWidgetSubscribe,
+                onSecurityAlert: this.onWidgetSecurityAlert,
+                scope: this
+            }
+    });
+    this.hub = this.loader.hub;
+}
+
+MashupMaker.prototype.onWidgetPublish = function( topic, message, pcont, scont )
+{
+    var pid = pcont ? pcont.getClientID() : "manager";
+    var sid = scont ? scont.getClientID() : "manager";
+    console.log( ">> onPublish: from=" + pid + " to=" + sid + " t=" + topic + " d=" + JSON.stringify(message) );
+    if ( this.publishManagers && this.publishManagers.length > 0 ) {
+        for ( var i = 0; i < this.publishManagers.length; i++ ) {
+            try {
+                this.publishManagers[i]( topic, message, pcont, scont );
+            } catch (e) {}
+        }
+    }
+    return true;
+}
+
+MashupMaker.prototype.onWidgetSubscribe = function( topic, container )
+{
+    var id = container ? container.getClientID() : "manager";
+    console.log( "++ onSubscribe: w=" + id + "  t=" + topic );
+    if ( this.subscribeManagers && this.subscribeManagers.length > 0 ) {
+        for ( var i = 0; i < this.subscribeManagers.length; i++ ) {
+            try {
+                this.subscribeManagers[i]( topic, container );
+            } catch (e) {}
+        }
+    }
+    return true;
+}
+
+MashupMaker.prototype.onWidgetSecurityAlert = function( source, alertType )
+{
+    // XXX TODO
+}
+
+MashupMaker.prototype.addPubSubManagerCallback = function( type, callback )
+{
+    switch( type ) {
+        case 'publish' :
+            if ( ! this.publishManagers ) {
+                this.publishManagers = [];
+            }
+            this.publishManagers.push( callback );
+            break;
+
+        case 'subscribe' :
+            if ( ! this.subscribeManagers ) {
+                this.subscribeManagers = [];
+            }
+            this.subscribeManagers.push( callback );
+            break;
+    }
+}
+
+MashupMaker.prototype.removePubSubManagerCallback = function( type, callback )
+{
+    var cbs;
+    if ( type == 'publish' ) {
+        cbs = this.publishManagers;
+    } else if ( type == 'subscribe' ) {
+        cbs = this.subscribeManagers;
+    } else {
+        return;
+    }
+    
+    for ( var i = 0; i < cbs.length; i++ ) {
+        if ( cbs[i] === callback ) {
+            cbs.splice( i, 1 );
+            break;
+        }
+    }
+}
+
+MashupMaker.prototype.getFeature = function(feature, loadedCB)
+{
+    if (this._features[feature]) {
+        if (! this._features[feature].loaded) {
+            var head = document.getElementsByTagName('head').item(0);
+            var scriptBlock = document.createElement('SCRIPT');
+            scriptBlock.src = this._features[feature].file;
+            head.appendChild(scriptBlock);        
+            this._featureCB = loadedCB;
+            this._pendingFeature = feature;
+        } else {
+            if (loadedCB) {
+                loadedCB(this._features[feature].instance);
+            }
+        }
+    }
+}
+
+MashupMaker.prototype.featureLoadedCB = function(instance)
+{
+    this._features[this._pendingFeature].loaded = true;
+    this._features[this._pendingFeature].feature = instance;
+    if (this._featureCB) {
+        this._featureCB(instance);
+    }
+}
+
+MashupMaker.prototype.createGadget = function( url, targetDOM, id, nochrome, positionInfo, privileged )
+{
+    if ( ! targetDOM ) {
+        targetDOM = this.getDefaultGadgetContainer();
+    }
+    
+//    <table class="gadgetContainer" _widgetid="gID_4a0c4ba6cc238" style="" cellspacing="0" cellpadding="0">
+//	    <tbody>
+//	        <tr>
+//	            <td>
+//            		<div class="gadgetBoxHeader"><div></div></div>
+//            		<div class="gadgetBoxContent">
+//            		    <div class="gadgetHeader">
+//            		        <IMG CLASS="absDeleteImg" SRC="gadgets/layout/images/deleteIcon_11x11.gif">
+//            		        <IMG ID="gID_4a0c4ba6cc238_propMenuTarget" CLASS="absPropEditImg" SRC="gadgets/layout/images/prop_edit.gif">
+//            		        <DIV CLASS="gadgetTitle">ColorPalette</DIV>
+//            		    </div>
+//            		    <div class="gadgetBody" id="gID_4a0c4ba6cc238_gadgetBody" style="width:208px;height:148px;">
+//            		        <SPAN>
+//            		            <iframe id="gID_4a0c4ba6cc238_frame" class="gadgetFrame" name="gID_4a0c4ba6cc238_frame" frameborder="0" scrolling="no" style="width:100%;height:100%"></iframe>
+//            		            <script>
+//                                    var __gID_4a0c4ba6cc238_data = [{"topic":"color","publish":"true","default":"#ffffff","name":"color","datatype":"String"}];
+//                                    var __gID_4a0c4ba6cc238_views = ["default"];
+//                                    mashupMaker.createGadgetInstance(
+//                                            'gID_4a0c4ba6cc238',
+//                                            null,
+//                                            __gID_4a0c4ba6cc238_data,
+//	                                        __gID_4a0c4ba6cc238_views,
+//	                                        'http://www.openajax.org/2008_InteropFest/mashupapp/gadgets/samples/gadgets/colorpalette/colorpalette_oam.xml',
+//	                                        'page',
+//	                                        { url: 'http://c50.openajax.org/2008_InteropFest/mashupapp/gadgets/samples/showGadget.php?url=http%3A%2F%2Fwww.openajax.org%2F2008_InteropFest%2Fmashupapp%2Fgadgets%2Fsamples%2Fgadgets%2Fcolorpalette%2Fcolorpalette_oam.xml',
+//	                                          frameID: 'gID_4a0c4ba6cc238_frame'
+//                                            }
+//                                    );
+//
+//                                </script>
+//                            </SPAN>
+//                        </div>
+//            		</div>
+//            		<div class="gadgetBoxFooter"><div></div></div>
+//            	</td>
+//            </tr>
+//        </tbody>
+//	</table>
+    
+    if ( ! id ) {
+        id = "gID_" + ((0x7fffffff * Math.random()) | 0).toString(16);
+    }
+	
+	var response = '' +
+        '<table class="gadgetContainer" _widgetid="' + id + '" style="" cellspacing="0" cellpadding="0">' +
+        '    <tbody>' +
+        '        <tr>' +
+        '            <td>';
+    if ( ! nochrome ) {
+        response +=
+        '            <div class="gadgetBoxHeader"><div></div></div>' +
+        '                <div class="gadgetBoxContent">' +
+        '                   <div class="gadgetHeader">' +
+        '                       <IMG CLASS="absDeleteImg" SRC="gadgets/layout/images/delete.png">' +
+        //'                       <IMG ID="' + id + '_propMenuTarget" CLASS="absPropEditImg" SRC="gadgets/layout/images/prop_edit.gif">' +
+        '                       <DIV CLASS="gadgetTitle">...loading...</DIV>' +
+        '                   </div>';
+    }
+    response +=
+        '                   <div class="gadgetBody" id="' + id + '_gadgetBody">' +
+        '                   </div>';
+    if ( ! nochrome ) {
+        response +=
+        '               </div>' +
+        '               <div class="gadgetBoxFooter"><div></div></div>';
+    }
+    response +=
+        '           </td>' +
+        '        </tr>' +
+        '    </tbody>' +
+        '</table>';
+    
+    var temp = document.createElement('DIV');
+    temp.innerHTML = response;
+    var containers = dojo.query(".gadgetContainer", temp);
+    var gadgetContainer = (containers && containers.length > 0) ? containers[0] : null;
+
+    var dropInfo = positionInfo || null;
+
+    if (gadgetContainer) {
+        this.layout.setLayoutStyles(gadgetContainer);
+        if (dropInfo) {
+            gadgetContainer.style.left = dropInfo.x;
+            gadgetContainer.style.top = dropInfo.y;
+            this._insertWidget( targetDOM, null, gadgetContainer, 'child' );
+        } else {
+            this._insertWidget( targetDOM, null, gadgetContainer, 'child' );
+        }
+    }
+    
+    delete temp;
+    
+    var mm = this;
+    this.loader.loadMetadata({
+        url: url,
+        onComplete: function( spec )
+        {
+            // Look through the spec for references to Dojo.  If it is the same
+            // version as our "local" version, then replace with location of
+            // our Dojo build.
+            for ( var libname in spec.library ) {
+                if ( libname.toLowerCase() === "dojo" ) {
+                    var lib = spec.library[ libname ];
+                    var ver = lib.version.split(".");
+                    if ( dojo.version.major == ver[0] && dojo.version.minor == ver[1] ) {
+                        // update 'src' to point to our local Dojo
+                        lib.src = dojo.baseUrl.match(/(.+\/)[^\/]+\/?$/)[1];
+                        // if lib.src is relative, make absolute
+                        if ( lib.src.charAt(0) !== "/" && ! lib.src.match(/^http(s)?\:/) ) {
+                            lib.src = OpenAjax.widget.baseURI + lib.src;
+                        }
+                        
+                        // Some JS files may be XD versions of Dojo files --
+                        // rename to remove the "xd".
+                        // Also, remember the index of "dojo.js"; we'll use
+                        // that later when adding in "refimpldojo.js".
+                        var dojoJsIdx = -1;
+                        for ( var i = 0; i < spec.require.length; i++ ) {
+                            var req = spec.require[i];
+                            if ( req._library_ !== "dojo" || req.type !== "javascript" ) {
+                                continue;
+                            }
+                            req.src = req.src.replace( /(.+)\.xd\.js$/, "$1.js" );
+                            if ( dojoJsIdx === -1 && req.src.match( /^(.*\/)?dojo\.js$/ ) ) {
+                                dojoJsIdx = i;
+                            }
+                        }
+                        
+                        // Add "refimpldojo.js" as a require, right after
+                        // "dojo.js".
+                        var arr = spec.require.slice( 0, dojoJsIdx + 1 );
+                        var end = spec.require.slice( dojoJsIdx + 1 );
+                        arr.push({
+                            _library_: "dojo",
+                            src: "dojo/refimpldojo.js",
+                            type: "javascript"
+                        });
+                        spec.require = arr.concat( end );
+                    }
+                    break;
+                }
+            }
+            
+            mm.loader.create({
+                id: id,
+                spec: spec,
+                target: id + "_gadgetBody",
+                sandbox: true,
+                onComplete: function( widget )
+                {
+                    // (2) create the widget model -- used by MashupMaker...
+    
+                    // bind widget model to hub -- use __<ID> in order to avoid conflict when
+                    // binding widget instance (which uses <ID>)
+    //                this.hub.bind( "__" + id );
+    
+    //                var widgetModel = null;
+    //                if ( type == "google" ) {
+    //                    widgetModel = new OpenAjax.widget.GoogleGadgetModel( id, properties, views, data.url, data.frameID );
+    //                } else {
+    //                    widgetModel = new OpenAjax.widget.WidgetModel( id, properties, views );
+    //                }
+    //
+    //                if ( specurl != null ) {
+    //                    widgetModel.setSpecUrl( specurl );
+    //                }
+    
+                    var container = dojo.query(".gadgetContainer[_widgetid=\"" + id + "\"]");
+                    mm.layout.setLayoutStyles(container[0]);
+                    widget.OpenAjax._site = new GadgetSite(container[0], id/*, views*/);    // XXX JHP TODO handle views
+                    
+                    // set title
+                    if ( ! nochrome ) {
+                        dojo.query( ".gadgetTitle", container[0] )[0].innerHTML = widget.OpenAjax._spec.name;
+                    }
+                    
+                    // add "gadgetFrame" class to widget iframe
+                    dojo.query( "iframe", container[0] ).addClass( "gadgetFrame" );
+    
+                    // make sure that the widget container is on top of the other windows on
+                    // the canvas
+                    mm.layout.putOnTop( container );
+    
+                    mm.models[id] = widget;   // XXX not needed - use OpenAjax.widget.byId()
+                    mm.wiringManager.addGadget( widget );
+    //                widgetModel.type = type;
+    
+                    // keep a reference to the Widget instance inside the WidgetModel
+                    // (only for 'fragment' [non-sandboxed] widgets)
+    //                widgetModel.widget = widget;
+    
+    
+                    // XXX from sandboxedWidgetLoaded
+                    console.log('widget loaded id='+id);
+                    
+                    widget.OpenAjax._loaded = true;
+                },
+                onError: function( error )
+                {
+                    // XXX handle error better
+                    console.log(" !!! failed to create widget instance " + id + " :: " + url );
+                }
+            });
+        },
+        onError: function( error )
+        {
+            // XXX handle error
+            console.error( error );
+        }
+    });
+}
+
+MashupMaker.prototype._insertWidget = function( parentElement, referenceElement, widgetContainer, position )
+{
+    // pull out any scripts -- we handle those below
+//    var scripts = [];
+//    var elems = widgetContainer.getElementsByTagName('SCRIPT');
+//    for ( var i = 0; i < elems.length; i++ ) {
+//        scripts.push( elems[i].parentNode.removeChild( elems[i] ) );
+//    }
+    
+    if ( position == 'before' ) {
+        parentElement.insertBefore( widgetContainer, referenceElement );
+    } else {
+        parentElement.appendChild( widgetContainer );
+    }
+
+    // now that the content has been added to the page, run any scripts
+//    for ( var j = 0; j < scripts.length; j++ ) {
+//        if ( typeof window.execScript === 'function' ) {
+//            window.execScript( scripts[j].text );
+//        } else {
+//            (function() { eval.call( window, scripts[j].innerHTML ); } )();
+//        }
+//    }
+}
+
+
+// XXX this is the old version
+MashupMaker.prototype.__createGadget = function(url, targetDOM, id, callback, argobj, nochrome, positionInfo)
+{
+    if ( ! targetDOM ) {
+        targetDOM = this.getDefaultGadgetContainer();
+    }
+    var resourceUri = OpenAjax.widget.baseURI + 'insertGadget.php?url=' + encodeURIComponent(url);
+    if ( id ) {
+        resourceUri += '&id=' + id;
+    }
+    if ( nochrome ) {
+        resourceUri += '&nochrome=' + Boolean(nochrome).toString();
+    }
+    if ( this._debug ) {
+        resourceUri += '&debug=true';
+    }
+    var mm = this;
+    var bindArgs = {
+        preventCache: false,
+        handleAs: 'text',
+        url:  resourceUri,
+        sync: true,
+        load: function(response) {
+            var temp = document.createElement('DIV');
+            temp.innerHTML = response;
+            var containers = dojo.query(".gadgetContainer", temp);
+            var gadgetContainer = null;
+            if (containers && containers.length > 0) {
+                gadgetContainer = containers[0];
+            }
+
+            var frames = temp.getElementsByTagName('IFRAME');
+            if (frames.length) {
+                var frame = frames.item(0);
+                mm._creatingGadget = {frame: frame, callback: callback, argobj: argobj}
+            }
+            var dropInfo = null;
+            if (typeof positionInfo != 'undefined') {
+                dropInfo = positionInfo;
+            }
+            if (gadgetContainer) {
+                mm.layout.setLayoutStyles(gadgetContainer);
+                if (dropInfo) {
+                    gadgetContainer.style.left = dropInfo.x;
+                    gadgetContainer.style.top = dropInfo.y;
+                    this.insertWidget( targetDOM, null, gadgetContainer, 'child' );
+                } else {
+                    this.insertWidget( targetDOM, null, gadgetContainer, 'child' );
+                }
+            }
+            delete temp;
+        },
+        error: function(error, request) {
+            alert(error);
+        },
+        insertWidget: function( parentElement, referenceElement, widgetContainer, position ) {
+            // pull out any scripts -- we handle those below
+            var scripts = [];
+            var elems = widgetContainer.getElementsByTagName('SCRIPT');
+            for ( var i = 0; i < elems.length; i++ ) {
+                scripts.push( elems[i].parentNode.removeChild( elems[i] ) );
+            }
+            
+            if ( position == 'before' ) {
+                parentElement.insertBefore( widgetContainer, referenceElement );
+            } else {
+                parentElement.appendChild( widgetContainer );
+            }
+
+            // now that the content has been added to the page, run any scripts
+            for ( var j = 0; j < scripts.length; j++ ) {
+                if ( typeof window.execScript === 'function' ) {
+                    window.execScript( scripts[j].text );
+                } else {
+                    (function() { eval.call( window, scripts[j].innerHTML ); } )();
+                }
+            }
+        }
+    };
+    dojo.xhrGet(bindArgs);
+}
+
+MashupMaker.prototype.getDefaultGadgetContainer = function()
+{
+    var dgc = document.getElementById('__replaceablecontent__');
+    if ( ! dgc ) {
+        if (document.body) {
+            dgc = document.createElement('DIV');
+            dgc.setAttribute('id', '__replaceablecontent__');
+            document.body.appendChild(dgc);
+        }
+    }
+    return dgc;
+}
+
+/**
+ * @param {String} id  The ID to be used for the created widget.
+ * @param {Function} widgetClass  Name of widget class.  If not specified,
+ *          uses OpenAjax.widget.Widget.
+ * @param {array} properties  Array of properties for the widget -- these are
+ *          either read from persistent storage or the defaults as specified
+ *          in the widget spec.
+ * @param {array} views  Array of view names
+ * @param {String} specurl  URL for the widget specification file.
+ * @param {String} type  Widget type.  Supported values are 'fragment' or 'page'.
+ *          If omitted, defaults to 'fragment'.
+ * @param {Object} data  A data object that is specific to the given 'type'
+ * @param {Object} dimensions  Initial dimensions of widget - {w, h}
+ *
+ * @returns the widget instance
+ * @type Object
+ */
+MashupMaker.prototype.createGadgetInstance = function( id, widgetClass,
+        properties, views, specurl, type, data, dimensions )
+{
+    // (1) create the object that is used by the widget...
+
+    if ( type != "google" ) { // don't create widget instance for Google Gadgets
+        // bind widget instance to hub
+        //AP this.hub.bind( id );
+    
+        if ( ! type ) {
+            type = 'fragment';
+        }
+        var widget = null;
+    
+        switch ( type ) {
+            case 'fragment' :
+                widget = OpenAjax.widget.Widget.createWidgetObjectInstance( id,
+                        widgetClass, properties, null, dimensions, views );
+                break;
+        
+            case 'page' :
+                // Use SMash to connect to 'page' widgets
+                function smashLoadError( id, error ) {
+                    // XXX handle smash error
+                    alert( 'The widget ' + id + ' failed to load (' + error + ')' );
+                }
+                //AP var newURI = smash.prepareForLoad({ clientName: id, uri: data.url, commErrorCallback: smashLoadError });
+        
+                // set iframe URL (load sandboxed gadget)
+                dojo.byId( data.frameID ).src = newURI;
+                
+                break;
+        
+            default :
+                throw 'unsupported widget type';
+        }
+        
+        // listen for when this widget gets loaded
+        var callback = function( success, subHandle ) {
+            if ( !success ) {
+                // XXX handle error
+                alert( "subscribe failed" );
+            }
+        };
+        this.hub.subscribe( "openajax.widget." + id + "._loaded",
+                callback, dojo.hitch(this, this.sandboxedWidgetLoaded) );
+    }
+
+    // (2) create the widget model -- used by MashupMaker...
+    
+    // bind widget model to hub -- use __<ID> in order to avoid conflict when
+    // binding widget instance (which uses <ID>)
+    this.hub.bind( "__" + id );
+
+    var widgetModel = null;
+    if ( type == "google" ) {
+        widgetModel = new OpenAjax.widget.GoogleGadgetModel( id, properties, views, data.url, data.frameID );
+    } else {
+        widgetModel = new OpenAjax.widget.WidgetModel( id, properties, views );
+    }
+
+    if ( specurl != null ) {
+        widgetModel.setSpecUrl( specurl );
+    }
+
+    var container = dojo.query(".gadgetContainer[_widgetid=\""+widgetModel.getId()+"\"]");
+    this.layout.setLayoutStyles(container[0]);
+    widgetModel._site = new GadgetSite(container[0], id, views);
+
+    // make sure that the widget container is on top of the other windows on
+    // the canvas
+    this.layout.putOnTop(widgetModel.getSite().getContainer());
+
+    this.models[id] = widgetModel;
+    this.wiringManager.addGadget(widgetModel);
+    widgetModel.type = type;
+    
+    // keep a reference to the Widget instance inside the WidgetModel
+    // (only for 'fragment' [non-sandboxed] widgets)
+    widgetModel.widget = widget;
+    
+    return widget;
+}
+
+MashupMaker.prototype.onload = function(event, debug)
+{
+    this.hub.publish( 'openajax.widget.mashup.load', null );
+
+    // cycle through all 'fragment' widgets and call their __onLoad() method
+    for ( var id in this.models ) {
+        var w = this.models[ id ].widget;
+        if ( w && typeof w.__onLoad === 'function' ) {
+            w.__onLoad();
+        }
+    }
+
+    this._debug = debug;
+}
+
+MashupMaker.prototype.handleWidgetResize = function( widgetID )
+{
+    if ( ! widgetID ) {
+        return;
+    }
+    var widget = this.getWidgetModelFromID( widgetID );
+    var dimensions = widget.OpenAjax._site.getDimensions();
+    widget.OpenAjax.adjustDimensions( dimensions );    // XXX need a better API for this?
+}
+
+MashupMaker.prototype.deleteGadget = function( widgetID )
+{
+    // notify widget instance of removal -- before removing widget from canvas
+    // we have to wait for acknowledgment that it has run its 'onUnload'
+    // callback.
+    var widget = this.models[ widgetID ];
+    if ( widget.OpenAjax._loaded ) {
+        widget.OpenAjax._unload( dojo.hitch( this, this.finishDeleteGadget ) );
+    } else {
+        this.finishDeleteGadget( widgetID );
+    }
+}
+
+MashupMaker.prototype.finishDeleteGadget = function( widgetID )
+{
+    var widgetModel = this.models[ widgetID ];
+
+    this.wiringManager.removeGadget( widgetModel );
+
+    var site = widgetModel.OpenAjax._site;
+    if ( site ) {
+        var container = site.getContainer();
+        // We cannot delete the widget container directly right now, since one
+        // of the methods up the stack is a SMash method running from the
+        // tunnel.html. If we delete the container, we delete the tunnel IFRAME,
+        // which means that when this method returns to the SMash code, the
+        // Javascript environment has been destroyed and hilarity ensues. So
+        // instead, we use a setTimeout with an interval of zero to allow this
+        // stream of code to conclude, and then delete the widget container.
+        setTimeout( function() {
+            container.parentNode.removeChild(container);
+            delete container;
+        }, 0 );
+    }
+
+    delete this.models[ widgetID ];
+}
+
+/**
+ * If the widgetID belongs to a widget of type 'page', we'll disconnect the
+ * widget from smash and tell the widget that it has been removed.  The gadget's
+ * IFRAME src will also be changed to force its document to unload.  The
+ * widgetModel for the widget will still live on, though.  maybeDisconnectWidget
+ * should be called before moving the gadgetContainer in the DOM otherwise smash
+ * will complain on browsers where IFRAMEs reload when moved in the DOM (like
+ * Firefox).
+ *
+ * @param {String} widgetID  The ID of the widget to disconnect
+ *
+ * @returns whether the widget was actually disconnected such that a
+ *          maybeReconnectWidget would be necessary
+ * @type boolean
+ */
+MashupMaker.prototype.maybeDisconnectWidget = function( widgetID, callback )
+{
+    var widgetModel = this.models[ widgetID ];
+
+    // If this isn't a 'page' type of widget, ignore.  We only want to be able
+    // to disconnect a widget in certain instances and we should never have to
+    // disconnect a non 'page' widget.  One such instance is when moving a
+    // 'page' widget in the DOM since on FF this causes a reload of IFRAMES that
+    // smash doesn't like.
+    if ( widgetModel.type != 'page' ) {
+        return false;
+    }
+
+    var that = this;
+    this.hub.subscribe( 'openajax.widget.' + widgetID + '._removed',
+            function( success, subHandle, callback ) {
+                if ( ! success ) {
+                    // something went wrong -- log the error and finish deletion
+                    console.log( "ERROR: failed to subscribe to '_removed'" );
+                    dojo.hitch( that, That.finishDisconnectWidget, callback );
+                }
+            },
+            dojo.hitch( that, that.finishDisconnectWidget, callback )
+    );
+    // notify widget instance of removal
+    widgetModel.fireEvent( "remove" );
+    return true;
+}
+
+MashupMaker.prototype.finishDisconnectWidget = function( disconnectCallback, subHandle, topic, data )
+{
+    // don't need to listen on this topic anymore
+    subHandle.unsubscribe();
+
+    // pull widget ID from topic
+    var widgetID = topic.split('.')[2];
+    smash.prepareForUnload( widgetID );
+    dojo.byId( widgetID + "_frame" ).src="about:blank";
+
+    // don't delete the widget model since we need info from it to reconnect
+
+    // We cannot allow the gadgetContainer to move around right now, since one
+    // of the methods up the stack is a SMash method running from the
+    // tunnel.html. If we move/remove the container, we delete the tunnel IFRAME,
+    // which means that when this method returns to the SMash code, the
+    // Javascript environment has been destroyed and hilarity ensues. So
+    // instead, we use a setTimeout with an interval of zero to allow this
+    // stream of code to conclude, and then call the callback.  We are assuming
+    // that the callback is going to move/remove the gadgetContainer otherwise
+    // way disconnect the gadget?
+    setTimeout( function(){disconnectCallback();}, 0 );
+}
+
+/**
+ * After maybeDisconnectWidget is called, the caller should reconnect widgets
+ * only after allowing the disconnected widgets' frames to unload.  This is
+ * because smash has logic in the frames' onunload handler.  So this is
+ * probably best done doing something like setTimeout(reconnectMyWidgetsFunc, 0)
+ * to set it up after the onunload events in the event queue.
+ *
+ * @param {String} widgetID  The ID of the widget to reconnect
+ *
+ */
+MashupMaker.prototype.maybeReconnectWidget = function( widgetID )
+{
+    // XXX We should also probably only do this if we can determine if the
+    // widgetModel has already been disconnected.  Currently this doesn't do
+    // anything so commenting it out.
+    var widgetModel = this.models[ widgetID ];
+//    if (widgetModel.connHandle.isConnected()) {
+//      return;
+//    }
+
+    // If this isn't a 'page' type of widget, ignore.  We only want to be able
+    // to reconnect a widget that has been disconnected and we should never have
+    // to disconnect a non 'page' widget.
+    if ( widgetModel.type != 'page' ) {
+        return;
+    }
+
+    // (2) create the object that is used by the widget...
+
+    // bind widget instance to hub
+    this.hub.bind( widgetID );
+
+    // Use SMash to connect to 'page' widgets
+    function smashLoadError( widgetID, error ) {
+        // XXX handle smash error
+        alert( 'The widget ' + widgetID + ' failed to load (' + error + ')' );
+    }
+
+    // set iframe URL (load sandboxed gadget), pass in the current widget
+    // properties so that user changes aren't lost
+    var properties = widgetModel.getPropertiesDatums();
+    var propertiesJSON = JSON.stringify(properties);
+
+    var showGadgetUrl =
+        OpenAjax.widget.baseURI+'showGadget.php?url='
+        + encodeURI(widgetModel.getSpecUrl()
+        + '&properties='+ propertiesJSON);
+        
+    var newURI = smash.prepareForLoad({ clientName: widgetID, uri: showGadgetUrl,
+            commErrorCallback: smashLoadError });
+
+    dojo.byId( widgetID + "_frame" ).src = newURI;
+}
+
+/**
+ * @param {OpenAjax.widget.Widget} sandboxedWidget  Sandboxed widget instance
+ * @param {DOM:Element} container  DOM content related to given widget instance
+ */
+MashupMaker.prototype.sandboxedWidgetLoaded = function( subHandle, topic, dataString )
+{
+    // pull widget ID from topic
+    var widgetID = topic.split('.')[2];
+    var widgetModel = this.models[ widgetID ];
+
+    console.log('widget loaded id='+widgetID);
+
+    // now that widget is loaded, don't need to listen on this topic anymore
+    subHandle.unsubscribe();
+
+    if (this._creatingGadget) {
+        // fire an 'insert' event
+        widgetModel.fireEvent( 'insert' );
+
+        var callback = this._creatingGadget.callback;
+        if ( callback && typeof callback === "function" ) {
+            console.log('createGadget calling callback id='+widgetID);
+            callback( /*sandboxedWidget*/ null, this._creatingGadget.argobj );
+        }
+        
+        this._creatingGadget = null;
+    }
+
+    widgetModel.loaded = true;
+}
+
+MashupMaker.prototype.openGadgetView = function( widgetID, viewName )
+{
+    var widgetModel = this.models[ widgetID ];
+    widgetModel.fireEvent( "_showView", viewName );
+}
+
+MashupMaker.prototype.editGadget = function( widgetID )
+{
+    var widget = OpenAjax.widget.byId( widgetID );
+    if ( widget.views && dojo.indexOf( widget.views, "edit" ) != -1 ) {    // XXX 'views' should exist; shouldn't need to check for it
+        // widget has an 'edit' content view
+        widget.fireEvent( "_showView", "edit" );
+    } else {
+        // show standard property editor
+        this._generatePropertyEditor( widget );
+    }
+}
+
+MashupMaker.prototype.shareGadget = function( widgetID )
+{
+    var widgetModel = this.models[ widgetID ];
+    var script = "&lt;script src=\"" + OpenAjax.widget.baseURI + "embedWidget.php?specURL=" 
+                 + widgetModel.getSpecUrl() + "\"&gt;&lt;/script&gt;";
+    var dialogDiv = dojo.byId('__OAA_shareDialog_container');
+    dojo.parser.parse(dialogDiv);
+    dojo.byId("__OAA_shareDialog_script_tag").innerHTML = script;
+    dijit.byId("__OAA_share_dialog").show();
+    return;
+}
+
+MashupMaker.prototype._generatePropertyEditor = function( widget )
+{
+    if (this.propertyEditorURL)  {
+        var widgetProps = widget.OpenAjax._spec.property;
+        //if there are no properties, then show an alert
+        var hasProps = false;
+        for ( var n in widgetProps ) {    // XXX is there a better way to do this?
+            hasProps = true;
+            break;
+        }
+        if ( ! widgetProps || ! hasProps ) {
+            alert( "No properties to edit!" );
+            return;
+        }
+        var propDlg = dijit.byId('propertyDialog');
+        var propDlgContents = dojo.byId(propDlg.id+'_Contents');
+        var d = new Date();
+        var t = d.getTime();
+        var gid = 'gID_' + t;
+//        var argobj = {gid:gid, editGadgetID: widget.OpenAjax.getId()};
+        console.log('_generatePropertyEditor gid='+gid);
+        if (propDlgContents) {
+          if (!propDlg.propertyEditor) {
+              var sid = this.hub.subscribe( "nomad-propertyEditor-ready",
+                      function( topic, data ) {
+                          this.hub.unsubscribe( sid );
+                          this._completePropertyEditor( widget.OpenAjax.getId() );
+                      },
+                      this
+              );
+              mashupMaker.createGadget(this.propertyEditorURL, propDlgContents, gid, 
+                                       true, null, true);
+          } else {
+              this._completePropertyEditor( widget.OpenAjax.getId() );
+          }
+        }
+    } else {
+        throw 'No property editor defined';
+    }
+}
+
+/**
+ * @param {OpenAjax.widget.Widget} propEditorWidget  Property Editor widget instance (may be null)
+ * @param obj  Callback object that contains ID of Property Editor widget ('gid')
+               and ID of widget whose properties we are editing
+ */
+MashupMaker.prototype._completePropertyEditor = function( editGadgetID )
+{
+    console.log( '_completePropertyEditor gid=' + this.propertyEditor.OpenAjax.getId() );
+    var propDlg = dijit.byId('propertyDialog');
+    var propDlgContents = dojo.byId(propDlg.id+'_Contents');
+    if (propDlgContents) {
+        if (!propDlg.propertyEditor) {
+//            propDlg.propertyEditor = propEditorWidget;
+            propDlg.propertyEditor = this.propertyEditor;
+        }
+        // some widgets add tooltips which will tweak the body size in an
+        // undetectable way and scrollbars will show seemingly without reason
+        // so get rid of scrollbars with overflow hidden
+        var widget = this.getWidgetModelFromID( editGadgetID );
+        var propDlgContainerID = propDlg.propertyEditor.OpenAjax.getId() + 'propertyEditor';
+        propDlg.propertyEditor.editGadget( widget, propDlgContainerID, false, propDlg );
+        propDlg.show();
+    }
+}
+
+MashupMaker.prototype.getWidgetModelFromID = function( id )
+{
+//    return this.models[ id ];
+    // XXX delete this function and replace with OpenAjax.widget.byId()
+    return OpenAjax.widget.byId( id );
+}
+
+MashupMaker.prototype.exportElement = function(root, pruneCB) 
+{
+    if (! root && ! this.root) {
+        root = document.getElementById('__replaceablecontent__');
+        if (! root) {
+            root = document.body;
+        }
+    } else {
+        root = root ? root : (this.root ? this.root : document.body);
+    }
+
+    var clone = root.cloneNode(true);
+
+    var gadgets = this.layout.getGadgets(clone);
+    for (var i = 0; i < gadgets.length; i++) {
+        var gadgetInfo = gadgets[i];
+        var gadget = gadgetInfo.gadget;
+        if ( ! gadget.getSite() ) {
+            continue;
+        }
+        if (pruneCB) {
+            pruneCB(gadget, gadgetInfo.site);
+            continue;
+        }
+        var site = gadgetInfo.site;
+        if (! site) {
+            continue;
+        } 
+        var body = site.getBody();
+        var gadgetParent = body;
+        var nextSibling = null;
+        /*
+         * remove gadget container chrome
+         */
+        while ( gadgetParent.parentNode ) {
+            if ( gadgetParent.className == "gadgetContainer" ) {
+                temp = gadgetParent.parentNode;
+                nextSibling = gadgetParent.nextSibling;
+                temp.removeChild(gadgetParent);
+                gadgetParent = temp;
+                break;
+            } else {
+                gadgetParent = gadgetParent.parentNode;
+            }
+        }
+        var properties = gadget.getProperties();
+        var newWidget = gadgetParent.ownerDocument.createElement('SPAN');
+        // need to insert the replacement span into the same place in the DOM
+        // from which we removed the gadget container in case it was amongst
+        // text nodes, in a table, etc.
+        gadgetParent.insertBefore(newWidget, nextSibling);
+        newWidget.className = 'widget';
+        newWidget.setAttribute('id', gadget.getId());
+        newWidget.setAttribute('url', gadget.getSpecUrl());
+        
+        var dimensions = gadget.getSite().getDimensions();
+        newWidget.setAttribute('width', dimensions['width'] + 'px');
+        newWidget.setAttribute('height', dimensions['height'] + 'px');
+
+        var position = gadget.getSite().getPosition();
+        newWidget.setAttribute('top', position.y + 'px');
+        newWidget.setAttribute('left', position.x + 'px');
+
+        if ( properties ) {
+            var newProperties = gadgetParent.ownerDocument.createElement('SPAN');
+            newWidget.appendChild(newProperties);
+            newProperties.className = 'properties';
+            newProperties.setAttribute('name', 'userproperties');
+            for (var j = 0; j < properties.length; j++) {
+                var prop = properties[j];
+                var newProperty = gadgetParent.ownerDocument.createElement('SPAN');
+                newProperty.className = 'property';
+                newProperties.appendChild(newProperty);
+                newProperty.setAttribute('name', prop.name());
+                newProperty.setAttribute('datatype', prop.type());
+                newProperty.setAttribute('publish', prop.publish());
+                newProperty.setAttribute('subscribe', prop.subscribe());
+                newProperty.setAttribute('topic', prop.topic());
+                var sbgId = prop.getSingleBoundGadget();
+                if ( sbgId ) {
+                    newProperty.setAttribute('singlebound', sbgId);
+                }
+                var propValue = prop.evanescent() == "true" ? "" : prop.encodedValue();
+                var tnode = gadgetParent.ownerDocument.createTextNode(propValue);
+                newProperty.appendChild(tnode);
+            }
+        }        
+    }
+    return clone;
+}
+
+MashupMaker.prototype.getDragManager = function() {
+    return this._dragInProgress;
+}
+
+MashupMaker.prototype.setDragManager = function(/* DragManager*/ dragManager) {
+    this._dragInProgress = dragManager;
+}
+
+MashupMaker.prototype.startDND = function(event, dragItem) {
+    dijit.byId('searchResults')._toggleDropDown();
+    
+    this.setDragManager(new DragManager(event, dragItem, null, null));
+    this.layout.dragPaletteItem(this.getDragManager().dndNode, event.pageX, event.pageY, dojo.hitch(this, this.stopDND));
+    dojo.stopEvent(event);
+    return;
+}
+
+MashupMaker.prototype.dropCallback = function(/* event */ event, /* drop item */ item) {
+    return;
+}
+
+MashupMaker.prototype.stopDND = function(/* boolean */dropSuccessful, /* object */dropInfo) {
+  var dragManager = mashupMaker.getDragManager();
+  // if the drop occurred (drag not cancelled) then create a gadget at the
+  // drop location
+  if (dropSuccessful) {
+    this.createGadget(dragManager.getDragItem().itemUrl, null, null, false, dropInfo);
+  }
+  this.getDragManager().cancelDrag();
+  this.setDragManager(null);
+  dijit.byId('searchResults')._toggleDropDown();
+
+  /* XXX do I need to set focus back to the palette item that was dragged when
+   * the palette reappers?
+   */
+  return;
+}
+
+MashupMaker.prototype.getGadgets = function() {
+    var root = document.getElementById('__replaceablecontent__');
+    if (! root) {
+        root = document.body;
+    }
+
+    return this.layout.getGadgets(root);
+}
+
+MashupMaker.prototype.getWiringManager = function() {
+    if (!this.wiringManager) {
+        this.wiringManager = new WiringManager();
+    }
+    return this.wiringManager;
+}
+
+MashupMaker.prototype.getRepositoryList = function(callback) {
+    if (!this._repositoryList) {
+        //AP OpenAjax.widget.baseURI+
+      var resourceUri = 'http://www.openajax.org/samples/mashupapp/repository/oscontroller.php?action=getRepositories';
+      var that = this;
+      var bindArgs = {
+          handleAs: 'json',
+          url:  resourceUri,
+          sync: true,
+          load: function(response) {
+              that._repositoryList = response;
+              callback(response);
+          },
+          error: function(error, request) {
+              console.log('Error retrieving repository list: \n'+error.message);
+          }
+      };
+      dojo.xhrGet(bindArgs);
+    }
+    callback(this._repositoryList);
+}
+
+MashupMaker.prototype.getDebug = function() {
+    return this._debug;
+}
+
+MashupMaker.prototype.setEditorWidget = function(editorWidget) {
+    this.layout.setEditorWidget(editorWidget);
+}
+
+if (typeof Node == 'undefined') {
+    Node = {};
+    Node.ELEMENT_NODE = 1;
+    Node.TEXT_NODE    = 3;
+}
+
+var mashupMaker = new MashupMaker((typeof mashupArgs != 'undefined' ? mashupArgs : null));
+mashupMaker.propertyEditorURL = OpenAjax.widget.baseURI + 'nomad/propertyeditor/propertyeditor_oam.xml';        
diff --git a/UNGProject/js/widget.html b/UNGProject/js/widget.html
new file mode 100644
index 0000000000000000000000000000000000000000..9df8a5f750f04568b9547df803370af074913b48
--- /dev/null
+++ b/UNGProject/js/widget.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+   "http://www.w3.org/TR/html4/strict.dtd">
+
+<!--
+        Copyright 2009 OpenAjax Alliance
+
+        Licensed under the Apache License, Version 2.0 (the "License"); 
+        you may not use this file except in compliance with the License. 
+        You may obtain a copy of the License at
+        
+                http://www.apache.org/licenses/LICENSE-2.0
+
+        Unless required by applicable law or agreed to in writing, software 
+        distributed under the License is distributed on an "AS IS" BASIS, 
+        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+        See the License for the specific language governing permissions and 
+        limitations under the License.
+-->
+
+<html lang="en">
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>widget</title>
+    
+    <script src="loader.js"></script>
+    
+	<script>
+	    (function() {
+        
+        var scriptsLoaded = false,
+            windowLoaded = false;
+        
+        function onWindowLoad( event ) {
+            windowLoaded = true;
+            loadWidget();
+        }
+        function onScriptsLoad( success, error ) {
+            // XXX handle error (success == false)
+            scriptsLoaded = true;
+            loadWidget();
+        }
+        function loadWidget() {
+            if ( scriptsLoaded && windowLoaded ) {
+    	        OpenAjax.widget._createRemoteWidget( document.getElementById("oaa_widget") );
+            }
+        }
+        
+        function queryURLParam( param ) {
+            var result = new RegExp( "[\\?&]" + param + "=([^&#]*)" ).exec( window.location.search );
+            if ( result ) {
+                return decodeURIComponent( result[1].replace( /\+/g, "%20" ) );
+            }
+            return null;
+        }
+        
+        window.onload = onWindowLoad;
+
+        var head = document.getElementsByTagName('HEAD').item(0);
+        
+        var base = document.createElement( "base" );
+        base.setAttribute( "href", queryURLParam( "oawb" ) );
+        head.appendChild( base );
+
+        // load OpenAjax Hub files
+        var scripts;
+        var oaaHubJS = queryURLParam( "oawh" );
+        var m = oaaHubJS.match( /openajax(?:ManagedHub-.+|-mashup)\.js$/i );
+        if ( m ) {
+            var hubRoot = oaaHubJS.substring( 0, m.index );
+            var baseName = oaaHubJS.substring( m.index );
+            switch ( baseName.toLowerCase() ) {
+                case "openajaxmanagedhub-all.js":
+                    scripts = [ { src: hubRoot + "OpenAjaxManagedHub-all.js" } ];
+                    break;
+                case "openajaxmanagedhub-core.js":
+                    scripts = [ { src: hubRoot + "OpenAjaxManagedHub-core.js" },
+                                { src: hubRoot + "json2.js" },
+                    	        { src: hubRoot + "crypto.js" },
+                    	        { src: hubRoot + "iframe.js" },
+                    	        { src: hubRoot + "FIM.js" } ];
+                    break;
+                case "openajaxmanagedhub-std.js":
+                    scripts = [ { src: hubRoot + "OpenAjaxManagedHub-std.js" },
+                                { src: hubRoot + "FIM.js" } ];
+                    break;
+                case "openajax-mashup.js":
+                    scripts = [ { src: hubRoot + "OpenAjax-mashup.js" },
+                    	        { src: hubRoot + "containers/iframe/json2.js" },
+                    	        { src: hubRoot + "containers/iframe/crypto.js" },
+                    	        { src: hubRoot + "containers/iframe/iframe.js" },
+                    	        { src: hubRoot + "containers/iframe/FIM.js" } ];
+                    break;
+            }
+        }
+        
+        // load "loader.js" -- assume it is a sibling of this file
+        scripts.push( { src: /(.+:\/\/.+\/)/.exec( window.location.href )[1] + "loader.js" } );
+        
+        __openajax_widget__._loadScripts( scripts, false, onScriptsLoad );
+
+        })();
+	</script>
+    
+    <style>
+        body {
+            margin: 0;
+        }
+    </style>
+</head>
+<body>
+    <div id="oaa_widget"></div>
+</body>
+</html>
diff --git a/UNGProject/openajaxhub/release/all/OpenAjaxManagedHub-all.js b/UNGProject/openajaxhub/release/all/OpenAjaxManagedHub-all.js
new file mode 100644
index 0000000000000000000000000000000000000000..8e888734f9dafb2266929d6fce7e23e9a794f9d3
--- /dev/null
+++ b/UNGProject/openajaxhub/release/all/OpenAjaxManagedHub-all.js
@@ -0,0 +1,2448 @@
+var OpenAjax=OpenAjax||{};
+if(!OpenAjax.hub){
+OpenAjax.hub=function(){
+var _1={};
+var _2="org.openajax.hub.";
+return {implementer:"http://openajax.org",implVersion:"2.0.7",specVersion:"2.0",implExtraData:{},libraries:_1,registerLibrary:function(_3,_4,_5,_6){
+_1[_3]={prefix:_3,namespaceURI:_4,version:_5,extraData:_6};
+this.publish(_2+"registerLibrary",_1[_3]);
+},unregisterLibrary:function(_7){
+this.publish(_2+"unregisterLibrary",_1[_7]);
+delete _1[_7];
+}};
+}();
+OpenAjax.hub.Error={BadParameters:"OpenAjax.hub.Error.BadParameters",Disconnected:"OpenAjax.hub.Error.Disconnected",Duplicate:"OpenAjax.hub.Error.Duplicate",NoContainer:"OpenAjax.hub.Error.NoContainer",NoSubscription:"OpenAjax.hub.Error.NoSubscription",NotAllowed:"OpenAjax.hub.Error.NotAllowed",WrongProtocol:"OpenAjax.hub.Error.WrongProtocol",IncompatBrowser:"OpenAjax.hub.Error.IncompatBrowser"};
+OpenAjax.hub.SecurityAlert={LoadTimeout:"OpenAjax.hub.SecurityAlert.LoadTimeout",FramePhish:"OpenAjax.hub.SecurityAlert.FramePhish",ForgedMsg:"OpenAjax.hub.SecurityAlert.ForgedMsg"};
+OpenAjax.hub._debugger=function(){
+};
+OpenAjax.hub.ManagedHub=function(_8){
+if(!_8||!_8.onPublish||!_8.onSubscribe){
+throw new Error(OpenAjax.hub.Error.BadParameters);
+}
+this._p=_8;
+this._onUnsubscribe=_8.onUnsubscribe?_8.onUnsubscribe:null;
+this._scope=_8.scope||window;
+if(_8.log){
+var _9=this;
+this._log=function(_a){
+try{
+_8.log.call(_9._scope,"ManagedHub: "+_a);
+}
+catch(e){
+OpenAjax.hub._debugger();
+}
+};
+}else{
+this._log=function(){
+};
+}
+this._subscriptions={c:{},s:null};
+this._containers={};
+this._seq=0;
+this._active=true;
+this._isPublishing=false;
+this._pubQ=[];
+};
+OpenAjax.hub.ManagedHub.prototype.subscribeForClient=function(_b,_c,_d){
+this._assertConn();
+if(this._invokeOnSubscribe(_c,_b)){
+return this._subscribe(_c,this._sendToClient,this,{c:_b,sid:_d});
+}
+throw new Error(OpenAjax.hub.Error.NotAllowed);
+};
+OpenAjax.hub.ManagedHub.prototype.unsubscribeForClient=function(_e,_f){
+this._unsubscribe(_f);
+this._invokeOnUnsubscribe(_e,_f);
+};
+OpenAjax.hub.ManagedHub.prototype.publishForClient=function(_10,_11,_12){
+this._assertConn();
+this._publish(_11,_12,_10);
+};
+OpenAjax.hub.ManagedHub.prototype.disconnect=function(){
+this._active=false;
+for(var c in this._containers){
+this.removeContainer(this._containers[c]);
+}
+};
+OpenAjax.hub.ManagedHub.prototype.getContainer=function(_13){
+var _14=this._containers[_13];
+return _14?_14:null;
+};
+OpenAjax.hub.ManagedHub.prototype.listContainers=function(){
+var res=[];
+for(var c in this._containers){
+res.push(this._containers[c]);
+}
+return res;
+};
+OpenAjax.hub.ManagedHub.prototype.addContainer=function(_15){
+this._assertConn();
+var _16=_15.getClientID();
+if(this._containers[_16]){
+throw new Error(OpenAjax.hub.Error.Duplicate);
+}
+this._containers[_16]=_15;
+};
+OpenAjax.hub.ManagedHub.prototype.removeContainer=function(_17){
+var _18=_17.getClientID();
+if(!this._containers[_18]){
+throw new Error(OpenAjax.hub.Error.NoContainer);
+}
+_17.remove();
+delete this._containers[_18];
+};
+OpenAjax.hub.ManagedHub.prototype.subscribe=function(_19,_1a,_1b,_1c,_1d){
+this._assertConn();
+this._assertSubTopic(_19);
+if(!_1a){
+throw new Error(OpenAjax.hub.Error.BadParameters);
+}
+_1b=_1b||window;
+if(!this._invokeOnSubscribe(_19,null)){
+this._invokeOnComplete(_1c,_1b,null,false,OpenAjax.hub.Error.NotAllowed);
+return;
+}
+var _1e=this;
+function _1f(_20,_21,sd,_22){
+if(_1e._invokeOnPublish(_20,_21,_22,null)){
+try{
+_1a.call(_1b,_20,_21,_1d);
+}
+catch(e){
+OpenAjax.hub._debugger();
+_1e._log("caught error from onData callback to Hub.subscribe(): "+e.message);
+}
+}
+};
+var _23=this._subscribe(_19,_1f,_1b,_1d);
+this._invokeOnComplete(_1c,_1b,_23,true);
+return _23;
+};
+OpenAjax.hub.ManagedHub.prototype.publish=function(_24,_25){
+this._assertConn();
+this._assertPubTopic(_24);
+this._publish(_24,_25,null);
+};
+OpenAjax.hub.ManagedHub.prototype.unsubscribe=function(_26,_27,_28){
+this._assertConn();
+if(!_26){
+throw new Error(OpenAjax.hub.Error.BadParameters);
+}
+this._unsubscribe(_26);
+this._invokeOnUnsubscribe(null,_26);
+this._invokeOnComplete(_27,_28,_26,true);
+};
+OpenAjax.hub.ManagedHub.prototype.isConnected=function(){
+return this._active;
+};
+OpenAjax.hub.ManagedHub.prototype.getScope=function(){
+return this._scope;
+};
+OpenAjax.hub.ManagedHub.prototype.getSubscriberData=function(_29){
+this._assertConn();
+var _2a=_29.split(".");
+var sid=_2a.pop();
+var sub=this._getSubscriptionObject(this._subscriptions,_2a,0,sid);
+if(sub){
+return sub.data;
+}
+throw new Error(OpenAjax.hub.Error.NoSubscription);
+};
+OpenAjax.hub.ManagedHub.prototype.getSubscriberScope=function(_2b){
+this._assertConn();
+var _2c=_2b.split(".");
+var sid=_2c.pop();
+var sub=this._getSubscriptionObject(this._subscriptions,_2c,0,sid);
+if(sub){
+return sub.scope;
+}
+throw new Error(OpenAjax.hub.Error.NoSubscription);
+};
+OpenAjax.hub.ManagedHub.prototype.getParameters=function(){
+return this._p;
+};
+OpenAjax.hub.ManagedHub.prototype._sendToClient=function(_2d,_2e,sd,_2f){
+if(!this.isConnected()){
+return;
+}
+if(this._invokeOnPublish(_2d,_2e,_2f,sd.c)){
+sd.c.sendToClient(_2d,_2e,sd.sid);
+}
+};
+OpenAjax.hub.ManagedHub.prototype._assertConn=function(){
+if(!this.isConnected()){
+throw new Error(OpenAjax.hub.Error.Disconnected);
+}
+};
+OpenAjax.hub.ManagedHub.prototype._assertPubTopic=function(_30){
+if(!_30||_30===""||(_30.indexOf("*")!=-1)||(_30.indexOf("..")!=-1)||(_30.charAt(0)==".")||(_30.charAt(_30.length-1)==".")){
+throw new Error(OpenAjax.hub.Error.BadParameters);
+}
+};
+OpenAjax.hub.ManagedHub.prototype._assertSubTopic=function(_31){
+if(!_31){
+throw new Error(OpenAjax.hub.Error.BadParameters);
+}
+var _32=_31.split(".");
+var len=_32.length;
+for(var i=0;i<len;i++){
+var p=_32[i];
+if((p==="")||((p.indexOf("*")!=-1)&&(p!="*")&&(p!="**"))){
+throw new Error(OpenAjax.hub.Error.BadParameters);
+}
+if((p=="**")&&(i<len-1)){
+throw new Error(OpenAjax.hub.Error.BadParameters);
+}
+}
+};
+OpenAjax.hub.ManagedHub.prototype._invokeOnComplete=function(_33,_34,_35,_36,_37){
+if(_33){
+try{
+_34=_34||window;
+_33.call(_34,_35,_36,_37);
+}
+catch(e){
+OpenAjax.hub._debugger();
+this._log("caught error from onComplete callback: "+e.message);
+}
+}
+};
+OpenAjax.hub.ManagedHub.prototype._invokeOnPublish=function(_38,_39,_3a,_3b){
+try{
+return this._p.onPublish.call(this._scope,_38,_39,_3a,_3b);
+}
+catch(e){
+OpenAjax.hub._debugger();
+this._log("caught error from onPublish callback to constructor: "+e.message);
+}
+return false;
+};
+OpenAjax.hub.ManagedHub.prototype._invokeOnSubscribe=function(_3c,_3d){
+try{
+return this._p.onSubscribe.call(this._scope,_3c,_3d);
+}
+catch(e){
+OpenAjax.hub._debugger();
+this._log("caught error from onSubscribe callback to constructor: "+e.message);
+}
+return false;
+};
+OpenAjax.hub.ManagedHub.prototype._invokeOnUnsubscribe=function(_3e,_3f){
+if(this._onUnsubscribe){
+var _40=_3f.slice(0,_3f.lastIndexOf("."));
+try{
+this._onUnsubscribe.call(this._scope,_40,_3e);
+}
+catch(e){
+OpenAjax.hub._debugger();
+this._log("caught error from onUnsubscribe callback to constructor: "+e.message);
+}
+}
+};
+OpenAjax.hub.ManagedHub.prototype._subscribe=function(_41,_42,_43,_44){
+var _45=_41+"."+this._seq;
+var sub={scope:_43,cb:_42,data:_44,sid:this._seq++};
+var _46=_41.split(".");
+this._recursiveSubscribe(this._subscriptions,_46,0,sub);
+return _45;
+};
+OpenAjax.hub.ManagedHub.prototype._recursiveSubscribe=function(_47,_48,_49,sub){
+var _4a=_48[_49];
+if(_49==_48.length){
+sub.next=_47.s;
+_47.s=sub;
+}else{
+if(typeof _47.c=="undefined"){
+_47.c={};
+}
+if(typeof _47.c[_4a]=="undefined"){
+_47.c[_4a]={c:{},s:null};
+this._recursiveSubscribe(_47.c[_4a],_48,_49+1,sub);
+}else{
+this._recursiveSubscribe(_47.c[_4a],_48,_49+1,sub);
+}
+}
+};
+OpenAjax.hub.ManagedHub.prototype._publish=function(_4b,_4c,_4d){
+if(this._isPublishing){
+this._pubQ.push({t:_4b,d:_4c,p:_4d});
+return;
+}
+this._safePublish(_4b,_4c,_4d);
+while(this._pubQ.length>0){
+var pub=this._pubQ.shift();
+this._safePublish(pub.t,pub.d,pub.p);
+}
+};
+OpenAjax.hub.ManagedHub.prototype._safePublish=function(_4e,_4f,_50){
+this._isPublishing=true;
+var _51=_4e.split(".");
+this._recursivePublish(this._subscriptions,_51,0,_4e,_4f,_50);
+this._isPublishing=false;
+};
+OpenAjax.hub.ManagedHub.prototype._recursivePublish=function(_52,_53,_54,_55,msg,_56){
+if(typeof _52!="undefined"){
+var _57;
+if(_54==_53.length){
+_57=_52;
+}else{
+this._recursivePublish(_52.c[_53[_54]],_53,_54+1,_55,msg,_56);
+this._recursivePublish(_52.c["*"],_53,_54+1,_55,msg,_56);
+_57=_52.c["**"];
+}
+if(typeof _57!="undefined"){
+var sub=_57.s;
+while(sub){
+var sc=sub.scope;
+var cb=sub.cb;
+var d=sub.data;
+if(typeof cb=="string"){
+cb=sc[cb];
+}
+cb.call(sc,_55,msg,d,_56);
+sub=sub.next;
+}
+}
+}
+};
+OpenAjax.hub.ManagedHub.prototype._unsubscribe=function(_58){
+var _59=_58.split(".");
+var sid=_59.pop();
+if(!this._recursiveUnsubscribe(this._subscriptions,_59,0,sid)){
+throw new Error(OpenAjax.hub.Error.NoSubscription);
+}
+};
+OpenAjax.hub.ManagedHub.prototype._recursiveUnsubscribe=function(_5a,_5b,_5c,sid){
+if(typeof _5a=="undefined"){
+return false;
+}
+if(_5c<_5b.length){
+var _5d=_5a.c[_5b[_5c]];
+if(!_5d){
+return false;
+}
+this._recursiveUnsubscribe(_5d,_5b,_5c+1,sid);
+if(!_5d.s){
+for(var x in _5d.c){
+return true;
+}
+delete _5a.c[_5b[_5c]];
+}
+}else{
+var sub=_5a.s;
+var _5e=null;
+var _5f=false;
+while(sub){
+if(sid==sub.sid){
+_5f=true;
+if(sub==_5a.s){
+_5a.s=sub.next;
+}else{
+_5e.next=sub.next;
+}
+break;
+}
+_5e=sub;
+sub=sub.next;
+}
+if(!_5f){
+return false;
+}
+}
+return true;
+};
+OpenAjax.hub.ManagedHub.prototype._getSubscriptionObject=function(_60,_61,_62,sid){
+if(typeof _60!="undefined"){
+if(_62<_61.length){
+var _63=_60.c[_61[_62]];
+return this._getSubscriptionObject(_63,_61,_62+1,sid);
+}
+var sub=_60.s;
+while(sub){
+if(sid==sub.sid){
+return sub;
+}
+sub=sub.next;
+}
+}
+return null;
+};
+OpenAjax.hub._hub=new OpenAjax.hub.ManagedHub({onSubscribe:function(_64,_65){
+return true;
+},onPublish:function(_66,_67,_68,_69){
+return true;
+}});
+OpenAjax.hub.subscribe=function(_6a,_6b,_6c,_6d){
+if(typeof _6b==="string"){
+_6c=_6c||window;
+_6b=_6c[_6b]||null;
+}
+return OpenAjax.hub._hub.subscribe(_6a,_6b,_6c,null,_6d);
+};
+OpenAjax.hub.unsubscribe=function(_6e){
+return OpenAjax.hub._hub.unsubscribe(_6e);
+};
+OpenAjax.hub.publish=function(_6f,_70){
+OpenAjax.hub._hub.publish(_6f,_70);
+};
+OpenAjax.hub.registerLibrary("OpenAjax","http://openajax.org/hub","2.0",{});
+}
+OpenAjax.hub.InlineContainer=function(hub,_71,_72){
+if(!hub||!_71||!_72||!_72.Container||!_72.Container.onSecurityAlert){
+throw new Error(OpenAjax.hub.Error.BadParameters);
+}
+var _73=_72.Container.scope||window;
+var _74=false;
+var _75=[];
+var _76=0;
+var _77=null;
+if(_72.Container.log){
+var log=function(msg){
+try{
+_72.Container.log.call(_73,"InlineContainer::"+_71+": "+msg);
+}
+catch(e){
+OpenAjax.hub._debugger();
+}
+};
+}else{
+log=function(){
+};
+}
+this._init=function(){
+hub.addContainer(this);
+};
+this.getHub=function(){
+return hub;
+};
+this.sendToClient=function(_78,_79,_7a){
+if(_74){
+var sub=_75[_7a];
+try{
+sub.cb.call(sub.sc,_78,_79,sub.d);
+}
+catch(e){
+OpenAjax.hub._debugger();
+_77._log("caught error from onData callback to HubClient.subscribe(): "+e.message);
+}
+}
+};
+this.remove=function(){
+if(_74){
+_7b();
+}
+};
+this.isConnected=function(){
+return _74;
+};
+this.getClientID=function(){
+return _71;
+};
+this.getPartnerOrigin=function(){
+if(_74){
+return window.location.protocol+"//"+window.location.hostname;
+}
+return null;
+};
+this.getParameters=function(){
+return _72;
+};
+this.connect=function(_7c,_7d,_7e){
+if(_74){
+throw new Error(OpenAjax.hub.Error.Duplicate);
+}
+_74=true;
+_77=_7c;
+if(_72.Container.onConnect){
+try{
+_72.Container.onConnect.call(_73,this);
+}
+catch(e){
+OpenAjax.hub._debugger();
+log("caught error from onConnect callback to constructor: "+e.message);
+}
+}
+_7f(_7d,_7e,_7c,true);
+};
+this.disconnect=function(_80,_81,_82){
+if(!_74){
+throw new Error(OpenAjax.hub.Error.Disconnected);
+}
+_7b();
+if(_72.Container.onDisconnect){
+try{
+_72.Container.onDisconnect.call(_73,this);
+}
+catch(e){
+OpenAjax.hub._debugger();
+log("caught error from onDisconnect callback to constructor: "+e.message);
+}
+}
+_7f(_81,_82,_80,true);
+};
+this.subscribe=function(_83,_84,_85,_86,_87){
+_88();
+_89(_83);
+if(!_84){
+throw new Error(OpenAjax.hub.Error.BadParameters);
+}
+var _8a=""+_76++;
+var _8b=false;
+var msg=null;
+try{
+var _8c=hub.subscribeForClient(this,_83,_8a);
+_8b=true;
+}
+catch(e){
+_8a=null;
+msg=e.message;
+}
+_85=_85||window;
+if(_8b){
+_75[_8a]={h:_8c,cb:_84,sc:_85,d:_87};
+}
+_7f(_86,_85,_8a,_8b,msg);
+return _8a;
+};
+this.publish=function(_8d,_8e){
+_88();
+_8f(_8d);
+hub.publishForClient(this,_8d,_8e);
+};
+this.unsubscribe=function(_90,_91,_92){
+_88();
+if(typeof _90==="undefined"||_90===null){
+throw new Error(OpenAjax.hub.Error.BadParameters);
+}
+var sub=_75[_90];
+if(!sub){
+throw new Error(OpenAjax.hub.Error.NoSubscription);
+}
+hub.unsubscribeForClient(this,sub.h);
+delete _75[_90];
+_7f(_91,_92,_90,true);
+};
+this.getSubscriberData=function(_93){
+_88();
+return _94(_93).d;
+};
+this.getSubscriberScope=function(_95){
+_88();
+return _94(_95).sc;
+};
+function _7f(_96,_97,_98,_99,_9a){
+if(_96){
+try{
+_97=_97||window;
+_96.call(_97,_98,_99,_9a);
+}
+catch(e){
+OpenAjax.hub._debugger();
+_77._log("caught error from onComplete callback: "+e.message);
+}
+}
+};
+function _7b(){
+for(var _9b in _75){
+hub.unsubscribeForClient(this,_75[_9b].h);
+}
+_75=[];
+_76=0;
+_74=false;
+};
+function _88(){
+if(!_74){
+throw new Error(OpenAjax.hub.Error.Disconnected);
+}
+};
+function _8f(_9c){
+if((_9c==null)||(_9c==="")||(_9c.indexOf("*")!=-1)||(_9c.indexOf("..")!=-1)||(_9c.charAt(0)==".")||(_9c.charAt(_9c.length-1)==".")){
+throw new Error(OpenAjax.hub.Error.BadParameters);
+}
+};
+function _89(_9d){
+if(!_9d){
+throw new Error(OpenAjax.hub.Error.BadParameters);
+}
+var _9e=_9d.split(".");
+var len=_9e.length;
+for(var i=0;i<len;i++){
+var p=_9e[i];
+if((p==="")||((p.indexOf("*")!=-1)&&(p!="*")&&(p!="**"))){
+throw new Error(OpenAjax.hub.Error.BadParameters);
+}
+if((p=="**")&&(i<len-1)){
+throw new Error(OpenAjax.hub.Error.BadParameters);
+}
+}
+};
+function _94(_9f){
+var sub=_75[_9f];
+if(sub){
+return sub;
+}
+throw new Error(OpenAjax.hub.Error.NoSubscription);
+};
+this._init();
+};
+OpenAjax.hub.InlineHubClient=function(_a0){
+if(!_a0||!_a0.HubClient||!_a0.HubClient.onSecurityAlert||!_a0.InlineHubClient||!_a0.InlineHubClient.container){
+throw new Error(OpenAjax.hub.Error.BadParameters);
+}
+var _a1=_a0.InlineHubClient.container;
+var _a2=_a0.HubClient.scope||window;
+if(_a0.HubClient.log){
+var log=function(msg){
+try{
+_a0.HubClient.log.call(_a2,"InlineHubClient::"+_a1.getClientID()+": "+msg);
+}
+catch(e){
+OpenAjax.hub._debugger();
+}
+};
+}else{
+log=function(){
+};
+}
+this._log=log;
+this.connect=function(_a3,_a4){
+_a1.connect(this,_a3,_a4);
+};
+this.disconnect=function(_a5,_a6){
+_a1.disconnect(this,_a5,_a6);
+};
+this.getPartnerOrigin=function(){
+return _a1.getPartnerOrigin();
+};
+this.getClientID=function(){
+return _a1.getClientID();
+};
+this.subscribe=function(_a7,_a8,_a9,_aa,_ab){
+return _a1.subscribe(_a7,_a8,_a9,_aa,_ab);
+};
+this.publish=function(_ac,_ad){
+_a1.publish(_ac,_ad);
+};
+this.unsubscribe=function(_ae,_af,_b0){
+_a1.unsubscribe(_ae,_af,_b0);
+};
+this.isConnected=function(){
+return _a1.isConnected();
+};
+this.getScope=function(){
+return _a2;
+};
+this.getSubscriberData=function(_b1){
+return _a1.getSubscriberData(_b1);
+};
+this.getSubscriberScope=function(_b2){
+return _a1.getSubscriberScope(_b2);
+};
+this.getParameters=function(){
+return _a0;
+};
+};
+var OpenAjax=OpenAjax||{};
+OpenAjax.hub=OpenAjax.hub||{};
+OpenAjax.gadgets=typeof OpenAjax.gadgets==="object"?OpenAjax.gadgets:typeof gadgets==="object"?gadgets:{};
+OpenAjax.gadgets.rpctx=OpenAjax.gadgets.rpctx||{};
+(function(){
+if(typeof gadgets==="undefined"){
+if(typeof oaaConfig==="undefined"){
+var _b3=document.getElementsByTagName("script");
+var _b4=/openajax(?:managedhub-(?:all|core).*|-mashup)\.js$/i;
+for(var i=_b3.length-1;i>=0;i--){
+var src=_b3[i].getAttribute("src");
+if(!src){
+continue;
+}
+var m=src.match(_b4);
+if(m){
+var _b5=_b3[i].getAttribute("oaaConfig");
+if(_b5){
+try{
+oaaConfig=eval("({ "+_b5+" })");
+}
+catch(e){
+}
+}
+break;
+}
+}
+}
+if(typeof oaaConfig!=="undefined"&&oaaConfig.gadgetsGlobal){
+gadgets=OpenAjax.gadgets;
+}
+}
+})();
+if(!OpenAjax.hub.IframeContainer){
+(function(){
+OpenAjax.hub.IframeContainer=function(hub,_b6,_b7){
+_b8(arguments);
+var _b9=this;
+var _ba=_b7.Container.scope||window;
+var _bb=false;
+var _bc={};
+var _bd;
+var _be;
+var _bf=_b7.IframeContainer.timeout||15000;
+var _c0;
+if(_b7.Container.log){
+var log=function(msg){
+try{
+_b7.Container.log.call(_ba,"IframeContainer::"+_b6+": "+msg);
+}
+catch(e){
+OpenAjax.hub._debugger();
+}
+};
+}else{
+log=function(){
+};
+}
+this._init=function(){
+hub.addContainer(this);
+_be=OpenAjax.hub.IframeContainer._rpcRouter.add(_b6,this);
+_bd=_114(_b7,_ba,log);
+var _c1=_b7.IframeContainer.clientRelay;
+var _c2=OpenAjax.gadgets.rpc.getRelayChannel();
+if(_b7.IframeContainer.tunnelURI){
+if(_c2!=="wpm"&&_c2!=="ifpc"){
+throw new Error(OpenAjax.hub.Error.IncompatBrowser);
+}
+}else{
+log("WARNING: Parameter 'IframeContaienr.tunnelURI' not specified. Connection will not be fully secure.");
+if(_c2==="rmr"&&!_c1){
+_c1=OpenAjax.gadgets.rpc.getOrigin(_b7.IframeContainer.uri)+"/robots.txt";
+}
+}
+_c3();
+OpenAjax.gadgets.rpc.setupReceiver(_be,_c1);
+_c4();
+};
+this.sendToClient=function(_c5,_c6,_c7){
+OpenAjax.gadgets.rpc.call(_be,"openajax.pubsub",null,"pub",_c5,_c6,_c7);
+};
+this.remove=function(){
+_c8();
+clearTimeout(_c0);
+OpenAjax.gadgets.rpc.removeReceiver(_be);
+var _c9=document.getElementById(_be);
+_c9.parentNode.removeChild(_c9);
+OpenAjax.hub.IframeContainer._rpcRouter.remove(_be);
+};
+this.isConnected=function(){
+return _bb;
+};
+this.getClientID=function(){
+return _b6;
+};
+this.getPartnerOrigin=function(){
+if(_bb){
+var _ca=OpenAjax.gadgets.rpc.getReceiverOrigin(_be);
+if(_ca){
+return (/^([a-zA-Z]+:\/\/[^:]+).*/.exec(_ca)[1]);
+}
+}
+return null;
+};
+this.getParameters=function(){
+return _b7;
+};
+this.getHub=function(){
+return hub;
+};
+this.getIframe=function(){
+return document.getElementById(_be);
+};
+function _b8(_cb){
+var hub=_cb[0],_b6=_cb[1],_b7=_cb[2];
+if(!hub||!_b6||!_b7||!_b7.Container||!_b7.Container.onSecurityAlert||!_b7.IframeContainer||!_b7.IframeContainer.parent||!_b7.IframeContainer.uri){
+throw new Error(OpenAjax.hub.Error.BadParameters);
+}
+};
+this._handleIncomingRPC=function(_cc,_cd,_ce){
+switch(_cc){
+case "pub":
+hub.publishForClient(_b9,_cd,_ce);
+break;
+case "sub":
+var _cf="";
+try{
+_bc[_ce]=hub.subscribeForClient(_b9,_cd,_ce);
+}
+catch(e){
+_cf=e.message;
+}
+return _cf;
+case "uns":
+var _d0=_bc[_ce];
+hub.unsubscribeForClient(_b9,_d0);
+delete _bc[_ce];
+return _ce;
+case "con":
+_d1();
+return true;
+case "dis":
+_c4();
+_c8();
+if(_b7.Container.onDisconnect){
+try{
+_b7.Container.onDisconnect.call(_ba,_b9);
+}
+catch(e){
+OpenAjax.hub._debugger();
+log("caught error from onDisconnect callback to constructor: "+e.message);
+}
+}
+return true;
+}
+};
+this._onSecurityAlert=function(_d2){
+_d3(_113[_d2]);
+};
+function _c3(){
+var _d4=document.createElement("span");
+_b7.IframeContainer.parent.appendChild(_d4);
+var _d5="<iframe id=\""+_be+"\" name=\""+_be+"\" src=\"javascript:'<html></html>'\"";
+var _d6="";
+var _d7=_b7.IframeContainer.iframeAttrs;
+if(_d7){
+for(var _d8 in _d7){
+switch(_d8){
+case "style":
+for(var _d9 in _d7.style){
+_d6+=_d9+":"+_d7.style[_d9]+";";
+}
+break;
+case "className":
+_d5+=" class=\""+_d7[_d8]+"\"";
+break;
+default:
+_d5+=" "+_d8+"=\""+_d7[_d8]+"\"";
+}
+}
+}
+_d6+="visibility:hidden;";
+_d5+=" style=\""+_d6+"\"></iframe>";
+_d4.innerHTML=_d5;
+var _da;
+if(_b7.IframeContainer.tunnelURI){
+_da="&parent="+encodeURIComponent(_b7.IframeContainer.tunnelURI)+"&forcesecure=true";
+}else{
+_da="&oahParent="+encodeURIComponent(OpenAjax.gadgets.rpc.getOrigin(window.location.href));
+}
+var _db="";
+if(_be!==_b6){
+_db="&oahId="+_be.substring(_be.lastIndexOf("_")+1);
+}
+document.getElementById(_be).src=_b7.IframeContainer.uri+"#rpctoken="+_bd+_da+_db;
+};
+function _d1(){
+function _dc(_dd){
+if(_dd){
+_bb=true;
+clearTimeout(_c0);
+document.getElementById(_be).style.visibility="visible";
+if(_b7.Container.onConnect){
+try{
+_b7.Container.onConnect.call(_ba,_b9);
+}
+catch(e){
+OpenAjax.hub._debugger();
+log("caught error from onConnect callback to constructor: "+e.message);
+}
+}
+}
+};
+OpenAjax.gadgets.rpc.call(_be,"openajax.pubsub",_dc,"cmd","con");
+};
+function _c8(){
+if(_bb){
+_bb=false;
+document.getElementById(_be).style.visibility="hidden";
+for(var s in _bc){
+hub.unsubscribeForClient(_b9,_bc[s]);
+}
+_bc={};
+}
+};
+function _d3(_de){
+try{
+_b7.Container.onSecurityAlert.call(_ba,_b9,_de);
+}
+catch(e){
+OpenAjax.hub._debugger();
+log("caught error from onSecurityAlert callback to constructor: "+e.message);
+}
+};
+function _c4(){
+_c0=setTimeout(function(){
+_d3(OpenAjax.hub.SecurityAlert.LoadTimeout);
+_b9._handleIncomingRPC=function(){
+};
+},_bf);
+};
+this._init();
+};
+OpenAjax.hub.IframeHubClient=function(_df){
+if(!_df||!_df.HubClient||!_df.HubClient.onSecurityAlert){
+throw new Error(OpenAjax.hub.Error.BadParameters);
+}
+var _e0=this;
+var _e1=_df.HubClient.scope||window;
+var _e2=false;
+var _e3={};
+var _e4=0;
+var _e5;
+if(_df.HubClient.log){
+var log=function(msg){
+try{
+_df.HubClient.log.call(_e1,"IframeHubClient::"+_e5+": "+msg);
+}
+catch(e){
+OpenAjax.hub._debugger();
+}
+};
+}else{
+log=function(){
+};
+}
+this._init=function(){
+var _e6=OpenAjax.gadgets.util.getUrlParameters();
+if(!_e6.parent){
+var _e7=_e6.oahParent+"/robots.txt";
+OpenAjax.gadgets.rpc.setupReceiver("..",_e7);
+}
+if(_df.IframeHubClient&&_df.IframeHubClient.requireParentVerifiable&&OpenAjax.gadgets.rpc.getReceiverOrigin("..")===null){
+OpenAjax.gadgets.rpc.removeReceiver("..");
+throw new Error(OpenAjax.hub.Error.IncompatBrowser);
+}
+OpenAjax.hub.IframeContainer._rpcRouter.add("..",this);
+_e5=OpenAjax.gadgets.rpc.RPC_ID;
+if(_e6.oahId){
+_e5=_e5.substring(0,_e5.lastIndexOf("_"));
+}
+};
+this.connect=function(_e8,_e9){
+if(_e2){
+throw new Error(OpenAjax.hub.Error.Duplicate);
+}
+function _ea(_eb){
+if(_eb){
+_e2=true;
+if(_e8){
+try{
+_e8.call(_e9||window,_e0,true);
+}
+catch(e){
+OpenAjax.hub._debugger();
+log("caught error from onComplete callback to connect(): "+e.message);
+}
+}
+}
+};
+OpenAjax.gadgets.rpc.call("..","openajax.pubsub",_ea,"con");
+};
+this.disconnect=function(_ec,_ed){
+if(!_e2){
+throw new Error(OpenAjax.hub.Error.Disconnected);
+}
+_e2=false;
+var _ee=null;
+if(_ec){
+_ee=function(_ef){
+try{
+_ec.call(_ed||window,_e0,true);
+}
+catch(e){
+OpenAjax.hub._debugger();
+log("caught error from onComplete callback to disconnect(): "+e.message);
+}
+};
+}
+OpenAjax.gadgets.rpc.call("..","openajax.pubsub",_ee,"dis");
+};
+this.getPartnerOrigin=function(){
+if(_e2){
+var _f0=OpenAjax.gadgets.rpc.getReceiverOrigin("..");
+if(_f0){
+return (/^([a-zA-Z]+:\/\/[^:]+).*/.exec(_f0)[1]);
+}
+}
+return null;
+};
+this.getClientID=function(){
+return _e5;
+};
+this.subscribe=function(_f1,_f2,_f3,_f4,_f5){
+_f6();
+_f7(_f1);
+if(!_f2){
+throw new Error(OpenAjax.hub.Error.BadParameters);
+}
+_f3=_f3||window;
+var _f8=""+_e4++;
+_e3[_f8]={cb:_f2,sc:_f3,d:_f5};
+function _f9(_fa){
+if(_fa!==""){
+delete _e3[_f8];
+}
+if(_f4){
+try{
+_f4.call(_f3,_f8,_fa==="",_fa);
+}
+catch(e){
+OpenAjax.hub._debugger();
+log("caught error from onComplete callback to subscribe(): "+e.message);
+}
+}
+};
+OpenAjax.gadgets.rpc.call("..","openajax.pubsub",_f9,"sub",_f1,_f8);
+return _f8;
+};
+this.publish=function(_fb,_fc){
+_f6();
+_fd(_fb);
+OpenAjax.gadgets.rpc.call("..","openajax.pubsub",null,"pub",_fb,_fc);
+};
+this.unsubscribe=function(_fe,_ff,_100){
+_f6();
+if(!_fe){
+throw new Error(OpenAjax.hub.Error.BadParameters);
+}
+if(!_e3[_fe]||_e3[_fe].uns){
+throw new Error(OpenAjax.hub.Error.NoSubscription);
+}
+_e3[_fe].uns=true;
+function _101(_102){
+delete _e3[_fe];
+if(_ff){
+try{
+_ff.call(_100||window,_fe,true);
+}
+catch(e){
+OpenAjax.hub._debugger();
+log("caught error from onComplete callback to unsubscribe(): "+e.message);
+}
+}
+};
+OpenAjax.gadgets.rpc.call("..","openajax.pubsub",_101,"uns",null,_fe);
+};
+this.isConnected=function(){
+return _e2;
+};
+this.getScope=function(){
+return _e1;
+};
+this.getSubscriberData=function(_103){
+_f6();
+if(_e3[_103]){
+return _e3[_103].d;
+}
+throw new Error(OpenAjax.hub.Error.NoSubscription);
+};
+this.getSubscriberScope=function(_104){
+_f6();
+if(_e3[_104]){
+return _e3[_104].sc;
+}
+throw new Error(OpenAjax.hub.Error.NoSubscription);
+};
+this.getParameters=function(){
+return _df;
+};
+this._handleIncomingRPC=function(_105,_106,data,_107){
+if(_105==="pub"){
+if(_e3[_107]&&!_e3[_107].uns){
+try{
+_e3[_107].cb.call(_e3[_107].sc,_106,data,_e3[_107].d);
+}
+catch(e){
+OpenAjax.hub._debugger();
+log("caught error from onData callback to subscribe(): "+e.message);
+}
+}
+}
+if(_106==="con"){
+return true;
+}
+return false;
+};
+function _f6(){
+if(!_e2){
+throw new Error(OpenAjax.hub.Error.Disconnected);
+}
+};
+function _f7(_108){
+if(!_108){
+throw new Error(OpenAjax.hub.Error.BadParameters);
+}
+var path=_108.split(".");
+var len=path.length;
+for(var i=0;i<len;i++){
+var p=path[i];
+if((p==="")||((p.indexOf("*")!=-1)&&(p!="*")&&(p!="**"))){
+throw new Error(OpenAjax.hub.Error.BadParameters);
+}
+if((p=="**")&&(i<len-1)){
+throw new Error(OpenAjax.hub.Error.BadParameters);
+}
+}
+};
+function _fd(_109){
+if(!_109||_109===""||(_109.indexOf("*")!=-1)||(_109.indexOf("..")!=-1)||(_109.charAt(0)==".")||(_109.charAt(_109.length-1)==".")){
+throw new Error(OpenAjax.hub.Error.BadParameters);
+}
+};
+this._init();
+};
+OpenAjax.hub.IframeContainer._rpcRouter=function(){
+var _10a={};
+function _10b(){
+var r=_10a[this.f];
+if(r){
+return r._handleIncomingRPC.apply(r,arguments);
+}
+};
+function _10c(_10d,_10e){
+var r=_10a[_10d];
+if(r){
+r._onSecurityAlert.call(r,_10e);
+}
+};
+return {add:function(id,_10f){
+function _110(id,_111){
+if(id===".."){
+if(!_10a[".."]){
+_10a[".."]=_111;
+}
+return;
+}
+var _112=id;
+while(document.getElementById(_112)){
+_112=id+"_"+((32767*Math.random())|0).toString(16);
+}
+_10a[_112]=_111;
+return _112;
+};
+OpenAjax.gadgets.rpc.register("openajax.pubsub",_10b);
+OpenAjax.gadgets.rpc.config({securityCallback:_10c});
+_113[OpenAjax.gadgets.rpc.SEC_ERROR_LOAD_TIMEOUT]=OpenAjax.hub.SecurityAlert.LoadTimeout;
+_113[OpenAjax.gadgets.rpc.SEC_ERROR_FRAME_PHISH]=OpenAjax.hub.SecurityAlert.FramePhish;
+_113[OpenAjax.gadgets.rpc.SEC_ERROR_FORGED_MSG]=OpenAjax.hub.SecurityAlert.ForgedMsg;
+this.add=_110;
+return _110(id,_10f);
+},remove:function(id){
+delete _10a[id];
+}};
+}();
+var _113={};
+function _114(_115,_116,log){
+if(!OpenAjax.hub.IframeContainer._prng){
+var seed=new Date().getTime()+Math.random()+document.cookie;
+OpenAjax.hub.IframeContainer._prng=OpenAjax._smash.crypto.newPRNG(seed);
+}
+var p=_115.IframeContainer||_115.IframeHubClient;
+if(p&&p.seed){
+try{
+var _117=p.seed.call(_116);
+OpenAjax.hub.IframeContainer._prng.addSeed(_117);
+}
+catch(e){
+OpenAjax.hub._debugger();
+log("caught error from 'seed' callback: "+e.message);
+}
+}
+var _118=(p&&p.tokenLength)||6;
+return OpenAjax.hub.IframeContainer._prng.nextRandomB64Str(_118);
+};
+})();
+}
+if(typeof OpenAjax._smash=="undefined"){
+OpenAjax._smash={};
+}
+OpenAjax._smash.crypto={"strToWA":function(str,_119){
+var bin=Array();
+var mask=(1<<_119)-1;
+for(var i=0;i<str.length*_119;i+=_119){
+bin[i>>5]|=(str.charCodeAt(i/_119)&mask)<<(32-_119-i%32);
+}
+return bin;
+},"hmac_sha1":function(_11a,_11b,_11c){
+var ipad=Array(16),opad=Array(16);
+for(var i=0;i<16;i++){
+ipad[i]=_11a[i]^909522486;
+opad[i]=_11a[i]^1549556828;
+}
+var hash=this.sha1(ipad.concat(this.strToWA(_11b,_11c)),512+_11b.length*_11c);
+return this.sha1(opad.concat(hash),512+160);
+},"newPRNG":function(_11d){
+var that=this;
+if((typeof _11d!="string")||(_11d.length<12)){
+alert("WARNING: Seed length too short ...");
+}
+var _11e=[43417,15926,18182,33130,9585,30800,49772,40144,47678,55453,4659,38181,65340,6787,54417,65301];
+var _11f=[];
+var _120=0;
+function _121(_122){
+return that.hmac_sha1(_11e,_122,8);
+};
+function _123(_124){
+var _125=_121(_124);
+for(var i=0;i<5;i++){
+_11f[i]^=_125[i];
+}
+};
+_123(_11d);
+return {"addSeed":function(seed){
+_123(seed);
+},"nextRandomOctets":function(len){
+var _126=[];
+while(len>0){
+_120+=1;
+var _127=that.hmac_sha1(_11f,(_120).toString(16),8);
+for(i=0;(i<20)&(len>0);i++,len--){
+_126.push((_127[i>>2]>>(i%4))%256);
+}
+}
+return _126;
+},"nextRandomB64Str":function(len){
+var _128="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+var _129=this.nextRandomOctets(len);
+var _12a="";
+for(var i=0;i<len;i++){
+_12a+=_128.charAt(_129[i]&63);
+}
+return _12a;
+}};
+},"sha1":function(){
+var _12b=function(x,y){
+var lsw=(x&65535)+(y&65535);
+var msw=(x>>16)+(y>>16)+(lsw>>16);
+return (msw<<16)|(lsw&65535);
+};
+var rol=function(num,cnt){
+return (num<<cnt)|(num>>>(32-cnt));
+};
+function _12c(t,b,c,d){
+if(t<20){
+return (b&c)|((~b)&d);
+}
+if(t<40){
+return b^c^d;
+}
+if(t<60){
+return (b&c)|(b&d)|(c&d);
+}
+return b^c^d;
+};
+function _12d(t){
+return (t<20)?1518500249:(t<40)?1859775393:(t<60)?-1894007588:-899497514;
+};
+return function(_12e,_12f){
+_12e[_12f>>5]|=128<<(24-_12f%32);
+_12e[((_12f+64>>9)<<4)+15]=_12f;
+var W=Array(80);
+var H0=1732584193;
+var H1=-271733879;
+var H2=-1732584194;
+var H3=271733878;
+var H4=-1009589776;
+for(var i=0;i<_12e.length;i+=16){
+var a=H0;
+var b=H1;
+var c=H2;
+var d=H3;
+var e=H4;
+for(var j=0;j<80;j++){
+W[j]=((j<16)?_12e[i+j]:rol(W[j-3]^W[j-8]^W[j-14]^W[j-16],1));
+var T=_12b(_12b(rol(a,5),_12c(j,b,c,d)),_12b(_12b(e,W[j]),_12d(j)));
+e=d;
+d=c;
+c=rol(b,30);
+b=a;
+a=T;
+}
+H0=_12b(a,H0);
+H1=_12b(b,H1);
+H2=_12b(c,H2);
+H3=_12b(d,H3);
+H4=_12b(e,H4);
+}
+return Array(H0,H1,H2,H3,H4);
+};
+}()};
+if(!this.JSON){
+JSON={};
+}
+(function(){
+function f(n){
+return n<10?"0"+n:n;
+};
+if(typeof Date.prototype.toJSON!=="function"){
+Date.prototype.toJSON=function(key){
+return this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z";
+};
+String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){
+return this.valueOf();
+};
+}
+var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,_130=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,_131,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r","\"":"\\\"","\\":"\\\\"},rep;
+function _132(_133){
+_130.lastIndex=0;
+return _130.test(_133)?"\""+_133.replace(_130,function(a){
+var c=meta[a];
+return typeof c==="string"?c:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4);
+})+"\"":"\""+_133+"\"";
+};
+function str(key,_134){
+var i,k,v,_135,mind=gap,_136,_137=_134[key];
+if(_137&&typeof _137==="object"&&typeof _137.toJSON==="function"){
+_137=_137.toJSON(key);
+}
+if(typeof rep==="function"){
+_137=rep.call(_134,key,_137);
+}
+switch(typeof _137){
+case "string":
+return _132(_137);
+case "number":
+return isFinite(_137)?String(_137):"null";
+case "boolean":
+case "null":
+return String(_137);
+case "object":
+if(!_137){
+return "null";
+}
+gap+=_131;
+_136=[];
+if(Object.prototype.toString.apply(_137)==="[object Array]"){
+_135=_137.length;
+for(i=0;i<_135;i+=1){
+_136[i]=str(i,_137)||"null";
+}
+v=_136.length===0?"[]":gap?"[\n"+gap+_136.join(",\n"+gap)+"\n"+mind+"]":"["+_136.join(",")+"]";
+gap=mind;
+return v;
+}
+if(rep&&typeof rep==="object"){
+_135=rep.length;
+for(i=0;i<_135;i+=1){
+k=rep[i];
+if(typeof k==="string"){
+v=str(k,_137);
+if(v){
+_136.push(_132(k)+(gap?": ":":")+v);
+}
+}
+}
+}else{
+for(k in _137){
+if(Object.hasOwnProperty.call(_137,k)){
+v=str(k,_137);
+if(v){
+_136.push(_132(k)+(gap?": ":":")+v);
+}
+}
+}
+}
+v=_136.length===0?"{}":gap?"{\n"+gap+_136.join(",\n"+gap)+"\n"+mind+"}":"{"+_136.join(",")+"}";
+gap=mind;
+return v;
+}
+};
+if(typeof JSON.stringify!=="function"){
+JSON.stringify=function(_138,_139,_13a){
+var i;
+gap="";
+_131="";
+if(typeof _13a==="number"){
+for(i=0;i<_13a;i+=1){
+_131+=" ";
+}
+}else{
+if(typeof _13a==="string"){
+_131=_13a;
+}
+}
+rep=_139;
+if(_139&&typeof _139!=="function"&&(typeof _139!=="object"||typeof _139.length!=="number")){
+throw new Error("JSON.stringify");
+}
+return str("",{"":_138});
+};
+}
+if(typeof JSON.parse!=="function"){
+JSON.parse=function(text,_13b){
+var j;
+function walk(_13c,key){
+var k,v,_13d=_13c[key];
+if(_13d&&typeof _13d==="object"){
+for(k in _13d){
+if(Object.hasOwnProperty.call(_13d,k)){
+v=walk(_13d,k);
+if(v!==undefined){
+_13d[k]=v;
+}else{
+delete _13d[k];
+}
+}
+}
+}
+return _13b.call(_13c,key,_13d);
+};
+cx.lastIndex=0;
+if(cx.test(text)){
+text=text.replace(cx,function(a){
+return "\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4);
+});
+}
+if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){
+j=eval("("+text+")");
+return typeof _13b==="function"?walk({"":j},""):j;
+}
+throw new SyntaxError("JSON.parse");
+};
+}
+})();
+OpenAjax.gadgets.util=function(){
+function _13e(url){
+var _13f;
+var _140=url.indexOf("?");
+var _141=url.indexOf("#");
+if(_141===-1){
+_13f=url.substr(_140+1);
+}else{
+_13f=[url.substr(_140+1,_141-_140-1),"&",url.substr(_141+1)].join("");
+}
+return _13f.split("&");
+};
+var _142=null;
+var _143=[];
+return {getUrlParameters:function(_144){
+if(_142!==null&&typeof _144==="undefined"){
+return _142;
+}
+var _145={};
+var _146=_13e(_144||document.location.href);
+var _147=window.decodeURIComponent?decodeURIComponent:unescape;
+for(var i=0,j=_146.length;i<j;++i){
+var pos=_146[i].indexOf("=");
+if(pos===-1){
+continue;
+}
+var _148=_146[i].substring(0,pos);
+var _149=_146[i].substring(pos+1);
+_149=_149.replace(/\+/g," ");
+_145[_148]=_147(_149);
+}
+if(typeof _144==="undefined"){
+_142=_145;
+}
+return _145;
+},registerOnLoadHandler:function(_14a){
+_143.push(_14a);
+},runOnLoadHandlers:function(){
+for(var i=0,j=_143.length;i<j;++i){
+_143[i]();
+}
+},"attachBrowserEvent":function(elem,_14b,_14c,_14d){
+if(elem.addEventListener){
+elem.addEventListener(_14b,_14c,_14d);
+}else{
+if(elem.attachEvent){
+elem.attachEvent("on"+_14b,_14c);
+}
+}
+},"removeBrowserEvent":function(elem,_14e,_14f,_150){
+if(elem.removeEventListener){
+elem.removeEventListener(_14e,_14f,_150);
+}else{
+if(elem.detachEvent){
+elem.detachEvent("on"+_14e,_14f);
+}
+}
+}};
+}();
+OpenAjax.gadgets.util.getUrlParameters();
+OpenAjax.gadgets.json=OpenAjax.gadgets.json||{};
+if(!OpenAjax.gadgets.json.stringify){
+OpenAjax.gadgets.json={parse:function(str){
+try{
+return window.JSON.parse(str);
+}
+catch(e){
+return false;
+}
+},stringify:function(obj){
+try{
+return window.JSON.stringify(obj);
+}
+catch(e){
+return null;
+}
+}};
+}
+OpenAjax.gadgets.log=function(_151){
+OpenAjax.gadgets.log.logAtLevel(OpenAjax.gadgets.log.INFO,_151);
+};
+OpenAjax.gadgets.warn=function(_152){
+OpenAjax.gadgets.log.logAtLevel(OpenAjax.gadgets.log.WARNING,_152);
+};
+OpenAjax.gadgets.error=function(_153){
+OpenAjax.gadgets.log.logAtLevel(OpenAjax.gadgets.log.ERROR,_153);
+};
+OpenAjax.gadgets.setLogLevel=function(_154){
+OpenAjax.gadgets.log.logLevelThreshold_=_154;
+};
+OpenAjax.gadgets.log.logAtLevel=function(_155,_156){
+if(_155<OpenAjax.gadgets.log.logLevelThreshold_||!OpenAjax.gadgets.log._console){
+return;
+}
+var _157;
+var _158=OpenAjax.gadgets.log._console;
+if(_155==OpenAjax.gadgets.log.WARNING&&_158.warn){
+_158.warn(_156);
+}else{
+if(_155==OpenAjax.gadgets.log.ERROR&&_158.error){
+_158.error(_156);
+}else{
+if(_158.log){
+_158.log(_156);
+}
+}
+}
+};
+OpenAjax.gadgets.log.INFO=1;
+OpenAjax.gadgets.log.WARNING=2;
+OpenAjax.gadgets.log.ERROR=3;
+OpenAjax.gadgets.log.NONE=4;
+OpenAjax.gadgets.log.logLevelThreshold_=OpenAjax.gadgets.log.INFO;
+OpenAjax.gadgets.log._console=window.console?window.console:window.opera?window.opera.postError:undefined;
+(function(){
+if(!window.__isgadget){
+var _159=false;
+function _15a(){
+if(!_159){
+_159=true;
+OpenAjax.gadgets.util.runOnLoadHandlers();
+OpenAjax.gadgets.util.registerOnLoadHandler=function(_15b){
+setTimeout(_15b,0);
+};
+if(window.detachEvent){
+window.detachEvent("onload",_15a);
+}
+}
+};
+if(window.addEventListener){
+document.addEventListener("DOMContentLoaded",_15a,false);
+window.addEventListener("load",_15a,false);
+}else{
+if(window.attachEvent){
+window.attachEvent("onload",_15a);
+}
+}
+}
+})();
+OpenAjax.gadgets.rpctx=OpenAjax.gadgets.rpctx||{};
+if(!OpenAjax.gadgets.rpctx.frameElement){
+OpenAjax.gadgets.rpctx.frameElement=function(){
+var _15c="__g2c_rpc";
+var _15d="__c2g_rpc";
+var _15e;
+var _15f;
+function _160(_161,from,rpc){
+try{
+if(from!==".."){
+var fe=window.frameElement;
+if(typeof fe[_15c]==="function"){
+if(typeof fe[_15c][_15d]!=="function"){
+fe[_15c][_15d]=function(args){
+_15e(OpenAjax.gadgets.json.parse(args));
+};
+}
+fe[_15c](OpenAjax.gadgets.json.stringify(rpc));
+return;
+}
+}else{
+var _162=document.getElementById(_161);
+if(typeof _162[_15c]==="function"&&typeof _162[_15c][_15d]==="function"){
+_162[_15c][_15d](OpenAjax.gadgets.json.stringify(rpc));
+return;
+}
+}
+}
+catch(e){
+}
+return true;
+};
+return {getCode:function(){
+return "fe";
+},isParentVerifiable:function(){
+return false;
+},init:function(_163,_164){
+_15e=_163;
+_15f=_164;
+return true;
+},setup:function(_165,_166){
+if(_165!==".."){
+try{
+var _167=document.getElementById(_165);
+_167[_15c]=function(args){
+_15e(OpenAjax.gadgets.json.parse(args));
+};
+}
+catch(e){
+return false;
+}
+}
+if(_165===".."){
+_15f("..",true);
+var _168=function(){
+window.setTimeout(function(){
+OpenAjax.gadgets.rpc.call(_165,OpenAjax.gadgets.rpc.ACK);
+},500);
+};
+OpenAjax.gadgets.util.registerOnLoadHandler(_168);
+}
+return true;
+},call:function(_169,from,rpc){
+_160(_169,from,rpc);
+}};
+}();
+}
+OpenAjax.gadgets.rpctx=OpenAjax.gadgets.rpctx||{};
+if(!OpenAjax.gadgets.rpctx.ifpc){
+OpenAjax.gadgets.rpctx.ifpc=function(){
+var _16a=[];
+var _16b=0;
+var _16c;
+var _16d=2000;
+var _16e={};
+function _16f(args){
+var _170=[];
+for(var i=0,j=args.length;i<j;++i){
+_170.push(encodeURIComponent(OpenAjax.gadgets.json.stringify(args[i])));
+}
+return _170.join("&");
+};
+function _171(src){
+var _172;
+for(var i=_16a.length-1;i>=0;--i){
+var ifr=_16a[i];
+try{
+if(ifr&&(ifr.recyclable||ifr.readyState==="complete")){
+ifr.parentNode.removeChild(ifr);
+if(window.ActiveXObject){
+_16a[i]=ifr=null;
+_16a.splice(i,1);
+}else{
+ifr.recyclable=false;
+_172=ifr;
+break;
+}
+}
+}
+catch(e){
+}
+}
+if(!_172){
+_172=document.createElement("iframe");
+_172.style.border=_172.style.width=_172.style.height="0px";
+_172.style.visibility="hidden";
+_172.style.position="absolute";
+_172.onload=function(){
+this.recyclable=true;
+};
+_16a.push(_172);
+}
+_172.src=src;
+window.setTimeout(function(){
+document.body.appendChild(_172);
+},0);
+};
+function _173(arr,_174){
+for(var i=_174-1;i>=0;--i){
+if(typeof arr[i]==="undefined"){
+return false;
+}
+}
+return true;
+};
+return {getCode:function(){
+return "ifpc";
+},isParentVerifiable:function(){
+return true;
+},init:function(_175,_176){
+_16c=_176;
+_16c("..",true);
+return true;
+},setup:function(_177,_178){
+_16c(_177,true);
+return true;
+},call:function(_179,from,rpc){
+var _17a=OpenAjax.gadgets.rpc.getRelayUrl(_179);
+++_16b;
+if(!_17a){
+OpenAjax.gadgets.warn("No relay file assigned for IFPC");
+return;
+}
+var src=null,_17b=[];
+if(rpc.l){
+var _17c=rpc.a;
+src=[_17a,"#",_16f([from,_16b,1,0,_16f([from,rpc.s,"","",from].concat(_17c))])].join("");
+_17b.push(src);
+}else{
+src=[_17a,"#",_179,"&",from,"@",_16b,"&"].join("");
+var _17d=encodeURIComponent(OpenAjax.gadgets.json.stringify(rpc)),_17e=_16d-src.length,_17f=Math.ceil(_17d.length/_17e),_180=0,part;
+while(_17d.length>0){
+part=_17d.substring(0,_17e);
+_17d=_17d.substring(_17e);
+_17b.push([src,_17f,"&",_180,"&",part].join(""));
+_180+=1;
+}
+}
+do{
+_171(_17b.shift());
+}while(_17b.length>0);
+return true;
+},_receiveMessage:function(_181,_182){
+var from=_181[1],_183=parseInt(_181[2],10),_184=parseInt(_181[3],10),_185=_181[_181.length-1],_186=_183===1;
+if(_183>1){
+if(!_16e[from]){
+_16e[from]=[];
+}
+_16e[from][_184]=_185;
+if(_173(_16e[from],_183)){
+_185=_16e[from].join("");
+delete _16e[from];
+_186=true;
+}
+}
+if(_186){
+_182(OpenAjax.gadgets.json.parse(decodeURIComponent(_185)));
+}
+}};
+}();
+}
+OpenAjax.gadgets.rpctx=OpenAjax.gadgets.rpctx||{};
+if(!OpenAjax.gadgets.rpctx.rmr){
+OpenAjax.gadgets.rpctx.rmr=function(){
+var _187=500;
+var _188=10;
+var _189={};
+var _18a;
+var _18b;
+function _18c(_18d,_18e,data,_18f){
+var _190=function(){
+document.body.appendChild(_18d);
+_18d.src="about:blank";
+if(_18f){
+_18d.onload=function(){
+_1a5(_18f);
+};
+}
+_18d.src=_18e+"#"+data;
+};
+if(document.body){
+_190();
+}else{
+OpenAjax.gadgets.util.registerOnLoadHandler(function(){
+_190();
+});
+}
+};
+function _191(_192){
+if(typeof _189[_192]==="object"){
+return;
+}
+var _193=document.createElement("iframe");
+var _194=_193.style;
+_194.position="absolute";
+_194.top="0px";
+_194.border="0";
+_194.opacity="0";
+_194.width="10px";
+_194.height="1px";
+_193.id="rmrtransport-"+_192;
+_193.name=_193.id;
+var _195=OpenAjax.gadgets.rpc.getRelayUrl(_192);
+if(!_195){
+_195=OpenAjax.gadgets.rpc.getOrigin(OpenAjax.gadgets.util.getUrlParameters()["parent"])+"/robots.txt";
+}
+_189[_192]={frame:_193,receiveWindow:null,relayUri:_195,searchCounter:0,width:10,waiting:true,queue:[],sendId:0,recvId:0};
+if(_192!==".."){
+_18c(_193,_195,_196(_192));
+}
+_197(_192);
+};
+function _197(_198){
+var _199=null;
+_189[_198].searchCounter++;
+try{
+var _19a=OpenAjax.gadgets.rpc._getTargetWin(_198);
+if(_198===".."){
+_199=_19a.frames["rmrtransport-"+OpenAjax.gadgets.rpc.RPC_ID];
+}else{
+_199=_19a.frames["rmrtransport-.."];
+}
+}
+catch(e){
+}
+var _19b=false;
+if(_199){
+_19b=_19c(_198,_199);
+}
+if(!_19b){
+if(_189[_198].searchCounter>_188){
+return;
+}
+window.setTimeout(function(){
+_197(_198);
+},_187);
+}
+};
+function _19d(_19e,_19f,from,rpc){
+var _1a0=null;
+if(from!==".."){
+_1a0=_189[".."];
+}else{
+_1a0=_189[_19e];
+}
+if(_1a0){
+if(_19f!==OpenAjax.gadgets.rpc.ACK){
+_1a0.queue.push(rpc);
+}
+if(_1a0.waiting||(_1a0.queue.length===0&&!(_19f===OpenAjax.gadgets.rpc.ACK&&rpc&&rpc.ackAlone===true))){
+return true;
+}
+if(_1a0.queue.length>0){
+_1a0.waiting=true;
+}
+var url=_1a0.relayUri+"#"+_196(_19e);
+try{
+_1a0.frame.contentWindow.location=url;
+var _1a1=_1a0.width==10?20:10;
+_1a0.frame.style.width=_1a1+"px";
+_1a0.width=_1a1;
+}
+catch(e){
+return false;
+}
+}
+return true;
+};
+function _196(_1a2){
+var _1a3=_189[_1a2];
+var _1a4={id:_1a3.sendId};
+if(_1a3){
+_1a4.d=Array.prototype.slice.call(_1a3.queue,0);
+_1a4.d.push({s:OpenAjax.gadgets.rpc.ACK,id:_1a3.recvId});
+}
+return OpenAjax.gadgets.json.stringify(_1a4);
+};
+function _1a5(_1a6){
+var _1a7=_189[_1a6];
+var data=_1a7.receiveWindow.location.hash.substring(1);
+var _1a8=OpenAjax.gadgets.json.parse(decodeURIComponent(data))||{};
+var _1a9=_1a8.d||[];
+var _1aa=false;
+var _1ab=false;
+var _1ac=0;
+var _1ad=(_1a7.recvId-_1a8.id);
+for(var i=0;i<_1a9.length;++i){
+var rpc=_1a9[i];
+if(rpc.s===OpenAjax.gadgets.rpc.ACK){
+_18b(_1a6,true);
+if(_1a7.waiting){
+_1ab=true;
+}
+_1a7.waiting=false;
+var _1ae=Math.max(0,rpc.id-_1a7.sendId);
+_1a7.queue.splice(0,_1ae);
+_1a7.sendId=Math.max(_1a7.sendId,rpc.id||0);
+continue;
+}
+_1aa=true;
+if(++_1ac<=_1ad){
+continue;
+}
+++_1a7.recvId;
+_18a(rpc);
+}
+if(_1aa||(_1ab&&_1a7.queue.length>0)){
+var from=(_1a6==="..")?OpenAjax.gadgets.rpc.RPC_ID:"..";
+_19d(_1a6,OpenAjax.gadgets.rpc.ACK,from,{ackAlone:_1aa});
+}
+};
+function _19c(_1af,_1b0){
+var _1b1=_189[_1af];
+try{
+var _1b2=false;
+_1b2="document" in _1b0;
+if(!_1b2){
+return false;
+}
+_1b2=typeof _1b0["document"]=="object";
+if(!_1b2){
+return false;
+}
+var loc=_1b0.location.href;
+if(loc==="about:blank"){
+return false;
+}
+}
+catch(ex){
+return false;
+}
+_1b1.receiveWindow=_1b0;
+function _1b3(){
+_1a5(_1af);
+};
+if(typeof _1b0.attachEvent==="undefined"){
+_1b0.onresize=_1b3;
+}else{
+_1b0.attachEvent("onresize",_1b3);
+}
+if(_1af===".."){
+_18c(_1b1.frame,_1b1.relayUri,_196(_1af),_1af);
+}else{
+_1a5(_1af);
+}
+return true;
+};
+return {getCode:function(){
+return "rmr";
+},isParentVerifiable:function(){
+return true;
+},init:function(_1b4,_1b5){
+_18a=_1b4;
+_18b=_1b5;
+return true;
+},setup:function(_1b6,_1b7){
+try{
+_191(_1b6);
+}
+catch(e){
+OpenAjax.gadgets.warn("Caught exception setting up RMR: "+e);
+return false;
+}
+return true;
+},call:function(_1b8,from,rpc){
+return _19d(_1b8,rpc.s,from,rpc);
+}};
+}();
+}
+OpenAjax.gadgets.rpctx=OpenAjax.gadgets.rpctx||{};
+if(!OpenAjax.gadgets.rpctx.wpm){
+OpenAjax.gadgets.rpctx.wpm=function(){
+var _1b9,_1ba;
+var _1bb;
+var _1bc=false;
+var _1bd=false;
+function _1be(){
+var hit=false;
+function _1bf(_1c0){
+if(_1c0.data=="postmessage.test"){
+hit=true;
+if(typeof _1c0.origin==="undefined"){
+_1bd=true;
+}
+}
+};
+OpenAjax.gadgets.util.attachBrowserEvent(window,"message",_1bf,false);
+window.postMessage("postmessage.test","*");
+if(hit){
+_1bc=true;
+}
+OpenAjax.gadgets.util.removeBrowserEvent(window,"message",_1bf,false);
+};
+function _1c1(_1c2){
+var rpc=OpenAjax.gadgets.json.parse(_1c2.data);
+if(!rpc||!rpc.f){
+return;
+}
+var _1c3=OpenAjax.gadgets.rpc.getRelayUrl(rpc.f)||OpenAjax.gadgets.util.getUrlParameters()["parent"];
+var _1c4=OpenAjax.gadgets.rpc.getOrigin(_1c3);
+if(!_1bd?_1c2.origin!==_1c4:_1c2.domain!==/^.+:\/\/([^:]+).*/.exec(_1c4)[1]){
+return;
+}
+_1b9(rpc);
+};
+return {getCode:function(){
+return "wpm";
+},isParentVerifiable:function(){
+return true;
+},init:function(_1c5,_1c6){
+_1b9=_1c5;
+_1ba=_1c6;
+_1be();
+if(!_1bc){
+_1bb=function(win,msg,_1c7){
+win.postMessage(msg,_1c7);
+};
+}else{
+_1bb=function(win,msg,_1c8){
+window.setTimeout(function(){
+win.postMessage(msg,_1c8);
+},0);
+};
+}
+OpenAjax.gadgets.util.attachBrowserEvent(window,"message",_1c1,false);
+_1ba("..",true);
+return true;
+},setup:function(_1c9,_1ca,_1cb){
+if(_1c9===".."){
+if(_1cb){
+OpenAjax.gadgets.rpc._createRelayIframe(_1ca);
+}else{
+OpenAjax.gadgets.rpc.call(_1c9,OpenAjax.gadgets.rpc.ACK);
+}
+}
+return true;
+},call:function(_1cc,from,rpc){
+var _1cd=OpenAjax.gadgets.rpc._getTargetWin(_1cc);
+var _1ce=OpenAjax.gadgets.rpc.getRelayUrl(_1cc)||OpenAjax.gadgets.util.getUrlParameters()["parent"];
+var _1cf=OpenAjax.gadgets.rpc.getOrigin(_1ce);
+if(_1cf){
+_1bb(_1cd,OpenAjax.gadgets.json.stringify(rpc),_1cf);
+}else{
+OpenAjax.gadgets.error("No relay set (used as window.postMessage targetOrigin)"+", cannot send cross-domain message");
+}
+return true;
+},relayOnload:function(_1d0,data){
+_1ba(_1d0,true);
+}};
+}();
+}
+if(!OpenAjax.gadgets.rpc){
+OpenAjax.gadgets.rpc=function(){
+var _1d1="__cb";
+var _1d2="";
+var ACK="__ack";
+var _1d3=500;
+var _1d4=10;
+var _1d5={};
+var _1d6={};
+var _1d7={};
+var _1d8={};
+var _1d9=0;
+var _1da={};
+var _1db={};
+var _1dc={};
+var _1dd={};
+var _1de={};
+var _1df={};
+var _1e0=(window.top!==window.self);
+var _1e1=window.name;
+var _1e2=function(){
+};
+var _1e3=0;
+var _1e4=1;
+var _1e5=2;
+var _1e6=(function(){
+function _1e7(name){
+return function(){
+OpenAjax.gadgets.log("gadgets.rpc."+name+"("+OpenAjax.gadgets.json.stringify(Array.prototype.slice.call(arguments))+"): call ignored. [caller: "+document.location+", isChild: "+_1e0+"]");
+};
+};
+return {getCode:function(){
+return "noop";
+},isParentVerifiable:function(){
+return true;
+},init:_1e7("init"),setup:_1e7("setup"),call:_1e7("call")};
+})();
+if(OpenAjax.gadgets.util){
+_1dd=OpenAjax.gadgets.util.getUrlParameters();
+}
+function _1e8(){
+return typeof window.postMessage==="function"?OpenAjax.gadgets.rpctx.wpm:typeof window.postMessage==="object"?OpenAjax.gadgets.rpctx.wpm:navigator.userAgent.indexOf("WebKit")>0?OpenAjax.gadgets.rpctx.rmr:navigator.product==="Gecko"?OpenAjax.gadgets.rpctx.frameElement:OpenAjax.gadgets.rpctx.ifpc;
+};
+function _1e9(_1ea,_1eb){
+var tx=_1ec;
+if(!_1eb){
+tx=_1e6;
+}
+_1de[_1ea]=tx;
+var _1ed=_1df[_1ea]||[];
+for(var i=0;i<_1ed.length;++i){
+var rpc=_1ed[i];
+rpc.t=_1ee(_1ea);
+tx.call(_1ea,rpc.f,rpc);
+}
+_1df[_1ea]=[];
+};
+var _1ef=false,_1f0=false;
+function _1f1(){
+if(_1f0){
+return;
+}
+function _1f2(){
+_1ef=true;
+};
+OpenAjax.gadgets.util.attachBrowserEvent(window,"unload",_1f2,false);
+_1f0=true;
+};
+function _1f3(_1f4,_1f5,_1f6,data,_1f7){
+if(!_1d8[_1f5]||_1d8[_1f5]!==_1f6){
+OpenAjax.gadgets.error("Invalid auth token. "+_1d8[_1f5]+" vs "+_1f6);
+_1e2(_1f5,_1e5);
+}
+_1f7.onunload=function(){
+if(_1db[_1f5]&&!_1ef){
+_1e2(_1f5,_1e4);
+OpenAjax.gadgets.rpc.removeReceiver(_1f5);
+}
+};
+_1f1();
+data=OpenAjax.gadgets.json.parse(decodeURIComponent(data));
+_1ec.relayOnload(_1f5,data);
+};
+function _1f8(rpc){
+if(rpc&&typeof rpc.s==="string"&&typeof rpc.f==="string"&&rpc.a instanceof Array){
+if(_1d8[rpc.f]){
+if(_1d8[rpc.f]!==rpc.t){
+OpenAjax.gadgets.error("Invalid auth token. "+_1d8[rpc.f]+" vs "+rpc.t);
+_1e2(rpc.f,_1e5);
+}
+}
+if(rpc.s===ACK){
+window.setTimeout(function(){
+_1e9(rpc.f,true);
+},0);
+return;
+}
+if(rpc.c){
+rpc.callback=function(_1f9){
+OpenAjax.gadgets.rpc.call(rpc.f,_1d1,null,rpc.c,_1f9);
+};
+}
+var _1fa=(_1d5[rpc.s]||_1d5[_1d2]).apply(rpc,rpc.a);
+if(rpc.c&&typeof _1fa!=="undefined"){
+OpenAjax.gadgets.rpc.call(rpc.f,_1d1,null,rpc.c,_1fa);
+}
+}
+};
+function _1fb(url){
+if(!url){
+return "";
+}
+url=url.toLowerCase();
+if(url.indexOf("//")==0){
+url=window.location.protocol+url;
+}
+if(url.indexOf("://")==-1){
+url=window.location.protocol+"//"+url;
+}
+var host=url.substring(url.indexOf("://")+3);
+var _1fc=host.indexOf("/");
+if(_1fc!=-1){
+host=host.substring(0,_1fc);
+}
+var _1fd=url.substring(0,url.indexOf("://"));
+var _1fe="";
+var _1ff=host.indexOf(":");
+if(_1ff!=-1){
+var port=host.substring(_1ff+1);
+host=host.substring(0,_1ff);
+if((_1fd==="http"&&port!=="80")||(_1fd==="https"&&port!=="443")){
+_1fe=":"+port;
+}
+}
+return _1fd+"://"+host+_1fe;
+};
+function _200(id){
+if(typeof id==="undefined"||id===".."){
+return window.parent;
+}
+id=String(id);
+var _201=window.frames[id];
+if(_201){
+return _201;
+}
+_201=document.getElementById(id);
+if(_201&&_201.contentWindow){
+return _201.contentWindow;
+}
+return null;
+};
+var _1ec=_1e8();
+_1d5[_1d2]=function(){
+OpenAjax.gadgets.warn("Unknown RPC service: "+this.s);
+};
+_1d5[_1d1]=function(_202,_203){
+var _204=_1da[_202];
+if(_204){
+delete _1da[_202];
+_204(_203);
+}
+};
+function _205(_206,_207,_208){
+if(_1db[_206]===true){
+return;
+}
+if(typeof _1db[_206]==="undefined"){
+_1db[_206]=0;
+}
+var _209=document.getElementById(_206);
+if(_206===".."||_209!=null){
+if(_1ec.setup(_206,_207,_208)===true){
+_1db[_206]=true;
+return;
+}
+}
+if(_1db[_206]!==true&&_1db[_206]++<_1d4){
+window.setTimeout(function(){
+_205(_206,_207,_208);
+},_1d3);
+}else{
+_1de[_206]=_1e6;
+_1db[_206]=true;
+}
+};
+function _20a(_20b,rpc){
+if(typeof _1dc[_20b]==="undefined"){
+_1dc[_20b]=false;
+var _20c=OpenAjax.gadgets.rpc.getRelayUrl(_20b);
+if(_1fb(_20c)!==_1fb(window.location.href)){
+return false;
+}
+var _20d=_200(_20b);
+try{
+_1dc[_20b]=_20d.OpenAjax.gadgets.rpc.receiveSameDomain;
+}
+catch(e){
+OpenAjax.gadgets.error("Same domain call failed: parent= incorrectly set.");
+}
+}
+if(typeof _1dc[_20b]==="function"){
+_1dc[_20b](rpc);
+return true;
+}
+return false;
+};
+function _20e(_20f,url,_210){
+if(!/http(s)?:\/\/.+/.test(url)){
+if(url.indexOf("//")==0){
+url=window.location.protocol+url;
+}else{
+if(url.charAt(0)=="/"){
+url=window.location.protocol+"//"+window.location.host+url;
+}else{
+if(url.indexOf("://")==-1){
+url=window.location.protocol+"//"+url;
+}
+}
+}
+}
+_1d6[_20f]=url;
+_1d7[_20f]=!!_210;
+};
+function _1ee(_211){
+return _1d8[_211];
+};
+function _212(_213,_214,_215){
+_214=_214||"";
+_1d8[_213]=String(_214);
+_205(_213,_214,_215);
+};
+function _216(_217,_218){
+function init(_219){
+var _21a=_219?_219.rpc:{};
+var _21b=_21a.parentRelayUrl;
+if(_21b.substring(0,7)!=="http://"&&_21b.substring(0,8)!=="https://"&&_21b.substring(0,2)!=="//"){
+if(typeof _1dd.parent==="string"&&_1dd.parent!==""){
+if(_21b.substring(0,1)!=="/"){
+var _21c=_1dd.parent.lastIndexOf("/");
+_21b=_1dd.parent.substring(0,_21c+1)+_21b;
+}else{
+_21b=_1fb(_1dd.parent)+_21b;
+}
+}
+}
+var _21d=!!_21a.useLegacyProtocol;
+_20e("..",_21b,_21d);
+if(_21d){
+_1ec=OpenAjax.gadgets.rpctx.ifpc;
+_1ec.init(_1f8,_1e9);
+}
+var _21e=_218||_1dd.forcesecure||false;
+_212("..",_217,_21e);
+};
+var _21f={parentRelayUrl:OpenAjax.gadgets.config.NonEmptyStringValidator};
+OpenAjax.gadgets.config.register("rpc",_21f,init);
+};
+function _220(_221,_222,_223){
+var _224=_223||_1dd.forcesecure||false;
+var _225=_222||_1dd.parent;
+if(_225){
+_20e("..",_225);
+_212("..",_221,_224);
+}
+};
+function _226(_227,_228,_229,_22a){
+if(!OpenAjax.gadgets.util){
+return;
+}
+var _22b=document.getElementById(_227);
+if(!_22b){
+throw new Error("Cannot set up gadgets.rpc receiver with ID: "+_227+", element not found.");
+}
+var _22c=_228||_22b.src;
+_20e(_227,_22c);
+var _22d=OpenAjax.gadgets.util.getUrlParameters(_22b.src);
+var _22e=_229||_22d.rpctoken;
+var _22f=_22a||_22d.forcesecure;
+_212(_227,_22e,_22f);
+};
+function _230(_231,_232,_233,_234){
+if(_231===".."){
+var _235=_233||_1dd.rpctoken||_1dd.ifpctok||"";
+if(window["__isgadget"]===true){
+_216(_235,_234);
+}else{
+_220(_235,_232,_234);
+}
+}else{
+_226(_231,_232,_233,_234);
+}
+};
+return {config:function(_236){
+if(typeof _236.securityCallback==="function"){
+_1e2=_236.securityCallback;
+}
+},register:function(_237,_238){
+if(_237===_1d1||_237===ACK){
+throw new Error("Cannot overwrite callback/ack service");
+}
+if(_237===_1d2){
+throw new Error("Cannot overwrite default service:"+" use registerDefault");
+}
+_1d5[_237]=_238;
+},unregister:function(_239){
+if(_239===_1d1||_239===ACK){
+throw new Error("Cannot delete callback/ack service");
+}
+if(_239===_1d2){
+throw new Error("Cannot delete default service:"+" use unregisterDefault");
+}
+delete _1d5[_239];
+},registerDefault:function(_23a){
+_1d5[_1d2]=_23a;
+},unregisterDefault:function(){
+delete _1d5[_1d2];
+},forceParentVerifiable:function(){
+if(!_1ec.isParentVerifiable()){
+_1ec=OpenAjax.gadgets.rpctx.ifpc;
+}
+},call:function(_23b,_23c,_23d,_23e){
+_23b=_23b||"..";
+var from="..";
+if(_23b===".."){
+from=_1e1;
+}
+++_1d9;
+if(_23d){
+_1da[_1d9]=_23d;
+}
+var rpc={s:_23c,f:from,c:_23d?_1d9:0,a:Array.prototype.slice.call(arguments,3),t:_1d8[_23b],l:_1d7[_23b]};
+if(_23b!==".."&&!document.getElementById(_23b)){
+OpenAjax.gadgets.log("WARNING: attempted send to nonexistent frame: "+_23b);
+return;
+}
+if(_20a(_23b,rpc)){
+return;
+}
+var _23f=_1de[_23b];
+if(!_23f){
+if(!_1df[_23b]){
+_1df[_23b]=[rpc];
+}else{
+_1df[_23b].push(rpc);
+}
+return;
+}
+if(_1d7[_23b]){
+_23f=OpenAjax.gadgets.rpctx.ifpc;
+}
+if(_23f.call(_23b,from,rpc)===false){
+_1de[_23b]=_1e6;
+_1ec.call(_23b,from,rpc);
+}
+},getRelayUrl:function(_240){
+var url=_1d6[_240];
+if(url&&url.substring(0,1)==="/"){
+if(url.substring(1,2)==="/"){
+url=document.location.protocol+url;
+}else{
+url=document.location.protocol+"//"+document.location.host+url;
+}
+}
+return url;
+},setRelayUrl:_20e,setAuthToken:_212,setupReceiver:_230,getAuthToken:_1ee,removeReceiver:function(_241){
+delete _1d6[_241];
+delete _1d7[_241];
+delete _1d8[_241];
+delete _1db[_241];
+delete _1dc[_241];
+delete _1de[_241];
+},getRelayChannel:function(){
+return _1ec.getCode();
+},receive:function(_242,_243){
+if(_242.length>4){
+_1ec._receiveMessage(_242,_1f8);
+}else{
+_1f3.apply(null,_242.concat(_243));
+}
+},receiveSameDomain:function(rpc){
+rpc.a=Array.prototype.slice.call(rpc.a);
+window.setTimeout(function(){
+_1f8(rpc);
+},0);
+},getOrigin:_1fb,getReceiverOrigin:function(_244){
+var _245=_1de[_244];
+if(!_245){
+return null;
+}
+if(!_245.isParentVerifiable(_244)){
+return null;
+}
+var _246=OpenAjax.gadgets.rpc.getRelayUrl(_244)||OpenAjax.gadgets.util.getUrlParameters().parent;
+return OpenAjax.gadgets.rpc.getOrigin(_246);
+},init:function(){
+if(_1ec.init(_1f8,_1e9)===false){
+_1ec=_1e6;
+}
+if(_1e0){
+_230("..");
+}
+},_getTargetWin:_200,_createRelayIframe:function(_247,data){
+var _248=OpenAjax.gadgets.rpc.getRelayUrl("..");
+if(!_248){
+return;
+}
+var src=_248+"#..&"+_1e1+"&"+_247+"&"+encodeURIComponent(OpenAjax.gadgets.json.stringify(data));
+var _249=document.createElement("iframe");
+_249.style.border=_249.style.width=_249.style.height="0px";
+_249.style.visibility="hidden";
+_249.style.position="absolute";
+function _24a(){
+document.body.appendChild(_249);
+_249.src="javascript:\"<html></html>\"";
+_249.src=src;
+};
+if(document.body){
+_24a();
+}else{
+OpenAjax.gadgets.util.registerOnLoadHandler(function(){
+_24a();
+});
+}
+return _249;
+},ACK:ACK,RPC_ID:_1e1,SEC_ERROR_LOAD_TIMEOUT:_1e3,SEC_ERROR_FRAME_PHISH:_1e4,SEC_ERROR_FORGED_MSG:_1e5};
+}();
+OpenAjax.gadgets.rpc.init();
+}
+
diff --git a/UNGProject/openajaxhub/src/OpenAjax-mashup.js b/UNGProject/openajaxhub/src/OpenAjax-mashup.js
new file mode 100644
index 0000000000000000000000000000000000000000..86cc3501dbadd8ca7b3159724cbf080df279cd39
--- /dev/null
+++ b/UNGProject/openajaxhub/src/OpenAjax-mashup.js
@@ -0,0 +1,1351 @@
+/*******************************************************************************
+ * OpenAjax-mashup.js
+ *
+ * Reference implementation of the OpenAjax Hub, as specified by OpenAjax Alliance.
+ * Specification is under development at: 
+ *
+ *   http://www.openajax.org/member/wiki/OpenAjax_Hub_Specification
+ *
+ * Copyright 2006-2009 OpenAjax Alliance
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not 
+ * use this file except in compliance with the License. You may obtain a copy 
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0 . Unless 
+ * required by applicable law or agreed to in writing, software distributed 
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * specific language governing permissions and limitations under the License.
+ *
+ ******************************************************************************/
+
+// prevent re-definition of the OpenAjax object
+if ( !window["OpenAjax"] ) {
+
+OpenAjax = new function() {
+    this.hub = {};
+    var h = this.hub;
+    h.implementer = "http://openajax.org";
+    h.implVersion = "2.0";
+    h.specVersion = "2.0";
+    h.implExtraData = {};
+    var libs = {};
+    h.libraries = libs;
+    var ooh = "org.openajax.hub.";
+
+    h.registerLibrary = function(prefix, nsURL, version, extra){
+        libs[prefix] = {
+            prefix: prefix,
+            namespaceURI: nsURL,
+            version: version,
+            extraData: extra 
+        };
+        this.publish(ooh+"registerLibrary", libs[prefix]);
+    }
+    h.unregisterLibrary = function(prefix){
+        this.publish(ooh+"unregisterLibrary", libs[prefix]);
+        delete libs[prefix];
+    }
+}
+
+/**
+ * Error
+ * 
+ * Standard Error names used when the standard functions need to throw Errors.
+ */
+OpenAjax.hub.Error = {
+    // Either a required argument is missing or an invalid argument was provided
+    BadParameters: "OpenAjax.hub.Error.BadParameters",
+    // The specified hub has been disconnected and cannot perform the requested
+    // operation:
+    Disconnected: "OpenAjax.hub.Error.Disconnected",
+    // Container with specified ID already exists:
+    Duplicate: "OpenAjax.hub.Error.Duplicate",
+    // The specified ManagedHub has no such Container (or it has been removed)
+    NoContainer: "OpenAjax.hub.Error.NoContainer",
+    // The specified ManagedHub or Container has no such subscription
+    NoSubscription: "OpenAjax.hub.Error.NoSubscription",
+    // Permission denied by manager's security policy
+    NotAllowed: "OpenAjax.hub.Error.NotAllowed",
+    // Wrong communications protocol identifier provided by Container or HubClient
+    WrongProtocol: "OpenAjax.hub.Error.WrongProtocol"
+};
+
+/**
+ * SecurityAlert
+ * 
+ * Standard codes used when attempted security violations are detected. Unlike
+ * Errors, these codes are not thrown as exceptions but rather passed into the 
+ * SecurityAlertHandler function registered with the Hub instance.
+ */
+OpenAjax.hub.SecurityAlert = {
+    // Container did not load (possible frame phishing attack)
+    LoadTimeout: "OpenAjax.hub.SecurityAlert.LoadTimeout",
+    // Hub suspects a frame phishing attack against the specified container
+    FramePhish: "OpenAjax.hub.SecurityAlert.FramePhish",
+    // Hub detected a message forgery that purports to come to a specified
+    // container
+    ForgedMsg: "OpenAjax.hub.SecurityAlert.ForgedMsg"
+};
+
+/**
+ * Debugging Help
+ *
+ * OpenAjax.hub.enableDebug
+ *
+ *      If OpenAjax.hub.enableDebug is set to true, then the "debugger" keyword
+ *      will get hit whenever a user callback throws an exception, thereby
+ *      bringing up the JavaScript debugger.
+ */
+OpenAjax.hub._debugger = function() {
+    if ( OpenAjax.hub.enableDebug ) debugger; // REMOVE ON BUILD
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Hub interface
+ * 
+ * Hub is implemented on the manager side by ManagedHub and on the client side
+ * by ClientHub.
+ */
+//OpenAjax.hub.Hub = function() {}
+
+/**
+ * Subscribe to a topic.
+ *
+ * @param {String} topic
+ *     A valid topic string. MAY include wildcards.
+ * @param {Function} onData   
+ *     Callback function that is invoked whenever an event is 
+ *     published on the topic
+ * @param {Object} [scope]
+ *     When onData callback or onComplete callback is invoked,
+ *     the JavaScript "this" keyword refers to this scope object.
+ *     If no scope is provided, default is window.
+ * @param {Function} [onComplete]
+ *     Invoked to tell the client application whether the 
+ *     subscribe operation succeeded or failed. 
+ * @param {*} [subscriberData]
+ *     Client application provides this data, which is handed
+ *     back to the client application in the subscriberData
+ *     parameter of the onData callback function.
+ * 
+ * @returns subscriptionID
+ *     Identifier representing the subscription. This identifier is an 
+ *     arbitrary ID string that is unique within this Hub instance
+ * @type {String}
+ * 
+ * @throws {OpenAjax.hub.Error.Disconnected} if this Hub instance is not in CONNECTED state
+ * @throws {OpenAjax.hub.Error.BadParameters} if the topic is invalid (e.g. contains an empty token)
+ */
+//OpenAjax.hub.Hub.prototype.subscribe = function( topic, onData, scope, onComplete, subscriberData ) {}
+
+/**
+ * Publish an event on a topic
+ *
+ * @param {String} topic
+ *     A valid topic string. MUST NOT include wildcards.
+ * @param {*} data
+ *     Valid publishable data. To be portable across different
+ *     Container implementations, this value SHOULD be serializable
+ *     as JSON.
+ *     
+ * @throws {OpenAjax.hub.Error.Disconnected} if this Hub instance is not in CONNECTED state
+ * @throws {OpenAjax.hub.Error.BadParameters} if the topic cannot be published (e.g. contains 
+ *     wildcards or empty tokens) or if the data cannot be published (e.g. cannot be serialized as JSON)
+ */
+//OpenAjax.hub.Hub.prototype.publish = function( topic, data ) {}
+
+/**
+ * Unsubscribe from a subscription
+ *
+ * @param {String} subscriptionID
+ *     A subscriptionID returned by Hub.subscribe()
+ * @param {Function} [onComplete]
+ *     Callback function invoked when unsubscribe completes
+ * @param {Object} [scope]
+ *     When onComplete callback function is invoked, the JavaScript "this"
+ *     keyword refers to this scope object.
+ *     If no scope is provided, default is window.
+ *     
+ * @throws {OpenAjax.hub.Error.Disconnected} if this Hub instance is not in CONNECTED state
+ * @throws {OpenAjax.hub.Error.NoSubscription} if no such subscription is found
+ */
+//OpenAjax.hub.Hub.prototype.unsubscribe = function( subscriptionID, onComplete, scope ) {}
+
+/**
+ * Return true if this Hub instance is in the Connected state.
+ * Else returns false.
+ * 
+ * This function can be called even if the Hub is not in a CONNECTED state.
+ * 
+ * @returns Boolean
+ * @type {Boolean}
+ */
+//OpenAjax.hub.Hub.prototype.isConnected = function() {}
+
+/**
+ * Returns the scope associated with this Hub instance and which will be used
+ * with callback functions.
+ * 
+ * This function can be called even if the Hub is not in a CONNECTED state.
+ * 
+ * @returns scope object
+ * @type {Object}
+ */
+//OpenAjax.hub.Hub.prototype.getScope = function() {}
+
+/**
+ * Returns the subscriberData parameter that was provided when 
+ * Hub.subscribe was called.
+ *
+ * @param {String} subscriptionID
+ *     The subscriberID of a subscription
+ * 
+ * @returns subscriberData
+ * @type {*}
+ * 
+ * @throws {OpenAjax.hub.Error.Disconnected} if this Hub instance is not in CONNECTED state
+ * @throws {OpenAjax.hub.Error.NoSubscription} if there is no such subscription
+ */
+//OpenAjax.hub.Hub.prototype.getSubscriberData = function(subscriptionID) {}
+
+/**
+ * Returns the scope associated with a specified subscription.  This scope will
+ * be used when invoking the 'onData' callback supplied to Hub.subscribe().
+ *
+ * @param {String} subscriberID
+ *     The subscriberID of a subscription
+ * 
+ * @returns scope
+ * @type {*}
+ * 
+ * @throws {OpenAjax.hub.Error.Disconnected} if this Hub instance is not in CONNECTED state
+ * @throws {OpenAjax.hub.Error.NoSubscription} if there is no such subscription
+ */
+//OpenAjax.hub.Hub.prototype.getSubscriberScope = function(subscriberID) {}
+
+/**
+ * Returns the params object associated with this Hub instance.
+ *
+ * @returns params
+ *     The params object associated with this Hub instance
+ * @type {Object}
+ */
+//OpenAjax.hub.Hub.prototype.getParameters = function() {}
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * HubClient interface 
+ * 
+ * Extends Hub interface.
+ * 
+ * A HubClient implementation is typically specific to a particular 
+ * implementation of Container.
+ */
+
+/**
+ * Create a new HubClient. All HubClient constructors MUST have this 
+ * signature.
+ * @constructor
+ * 
+ * @param {Object} params 
+ *    Parameters used to instantiate the HubClient.
+ *    Once the constructor is called, the params object belongs to the
+ *    HubClient. The caller MUST not modify it.
+ *    Implementations of HubClient may specify additional properties
+ *    for the params object, besides those identified below. 
+ * 
+ * @param {Function} params.HubClient.onSecurityAlert
+ *     Called when an attempted security breach is thwarted
+ * @param {Object} [params.HubClient.scope]
+ *     Whenever one of the HubClient's callback functions is called,
+ *     references to "this" in the callback will refer to the scope object.
+ *     If not provided, the default is window.
+ * @param {Function} [params.HubClient.log]
+ *     Optional logger function. Would be used to log to console.log or
+ *     equivalent. 
+ *     
+ * @throws {OpenAjax.hub.Error.BadParameters} if any of the required
+ *     parameters is missing, or if a parameter value is invalid in 
+ *     some way.
+ */
+//OpenAjax.hub.HubClient = function( params ) {}
+
+/**
+ * Requests a connection to the ManagedHub, via the Container
+ * associated with this HubClient.
+ * 
+ * If the Container accepts the connection request, the HubClient's 
+ * state is set to CONNECTED and the HubClient invokes the 
+ * onComplete callback function.
+ * 
+ * If the Container refuses the connection request, the HubClient
+ * invokes the onComplete callback function with an error code. 
+ * The error code might, for example, indicate that the Container 
+ * is being destroyed.
+ * 
+ * In most implementations, this function operates asynchronously, 
+ * so the onComplete callback function is the only reliable way to
+ * determine when this function completes and whether it has succeeded
+ * or failed.
+ * 
+ * A client application may call HubClient.disconnect and then call
+ * HubClient.connect.
+ * 
+ * @param {Function} [onComplete]
+ *     Callback function to call when this operation completes.
+ * @param {Object} [scope]  
+ *     When the onComplete function is invoked, the JavaScript "this"
+ *     keyword refers to this scope object.
+ *     If no scope is provided, default is window.
+ *
+ * @throws {OpenAjax.hub.Error.Duplicate} if the HubClient is already connected
+ */
+//OpenAjax.hub.HubClient.prototype.connect = function( onComplete, scope ) {}
+
+/**
+ * Disconnect from the ManagedHub
+ * 
+ * Disconnect immediately:
+ * 
+ * 1. Sets the HubClient's state to DISCONNECTED.
+ * 2. Causes the HubClient to send a Disconnect request to the 
+ * 		associated Container. 
+ * 3. Ensures that the client application will receive no more
+ * 		onData or onComplete callbacks associated with this 
+ * 		connection, except for the disconnect function's own
+ * 		onComplete callback.
+ * 4. Automatically destroys all of the HubClient's subscriptions.
+ *
+ * In most implementations, this function operates asynchronously, 
+ * so the onComplete callback function is the only reliable way to
+ * determine when this function completes and whether it has succeeded
+ * or failed.
+ * 
+ * A client application is allowed to call HubClient.disconnect and 
+ * then call HubClient.connect.
+ * 	
+ * @param {Function} [onComplete]
+ *     Callback function to call when this operation completes.
+ * @param {Object} [scope]  
+ *     When the onComplete function is invoked, the JavaScript "this"
+ *     keyword refers to the scope object.
+ *     If no scope is provided, default is window.
+ *
+ * @throws {OpenAjax.hub.Error.Disconnected} if the HubClient is already
+ *     disconnected
+ */
+//OpenAjax.hub.HubClient.prototype.disconnect = function( onComplete, scope ) {}
+
+/**
+ * If DISCONNECTED: Returns null
+ * If CONNECTED: Returns the origin associated with the window containing the
+ * Container associated with this HubClient instance. The origin has the format
+ *  
+ * [protocol]://[host]
+ * 
+ * where:
+ * 
+ * [protocol] is "http" or "https"
+ * [host] is the hostname of the partner page.
+ * 
+ * @returns Partner's origin
+ * @type {String}
+ */
+//OpenAjax.hub.HubClient.prototype.getPartnerOrigin = function() {}
+
+/**
+ * Returns the client ID of this HubClient
+ *
+ * @returns clientID
+ * @type {String}
+ */
+//OpenAjax.hub.HubClient.prototype.getClientID = function() {}
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * OpenAjax.hub.ManagedHub
+ *
+ * Managed hub API for the manager application and for Containers. 
+ * 
+ * Implements OpenAjax.hub.Hub.
+ */
+
+/**
+ * Create a new ManagedHub instance
+ * @constructor
+ *     
+ * This constructor automatically sets the ManagedHub's state to
+ * CONNECTED.
+ * 
+ * @param {Object} params
+ *     Parameters used to instantiate the ManagedHub.
+ *     Once the constructor is called, the params object belongs exclusively to
+ *     the ManagedHub. The caller MUST not modify it.
+ *     
+ * The params object may contain the following properties:
+ * 
+ * @param {Function} params.onPublish
+ *     Callback function that is invoked whenever a 
+ *     data value published by a Container is about
+ *     to be delivered to some (possibly the same) Container.
+ *     This callback function implements a security policy;
+ *     it returns true if the delivery of the data is
+ *     permitted and false if permission is denied.
+ * @param {Function} params.onSubscribe
+ *     Called whenever a Container tries to subscribe
+ *     on behalf of its client.
+ *     This callback function implements a security policy;
+ *     it returns true if the subscription is permitted 
+ *     and false if permission is denied.
+ * @param {Function} [params.onUnsubscribe]
+ *     Called whenever a Container unsubscribes on behalf of its client. 
+ *     Unlike the other callbacks, onUnsubscribe is intended only for 
+ *     informative purposes, and is not used to implement a security
+ *     policy.
+ * @param {Object} [params.scope]
+ *     Whenever one of the ManagedHub's callback functions is called,
+ *     references to the JavaScript "this" keyword in the callback 
+ *     function refer to this scope object
+ *     If no scope is provided, default is window.
+ * @param {Function} [params.log]  Optional logger function. Would
+ *     be used to log to console.log or equivalent.
+ * 
+ * @throws {OpenAjax.hub.Error.BadParameters} if any of the required
+ *     parameters are missing
+ */
+OpenAjax.hub.ManagedHub = function( params )
+{
+    if ( ! params || ! params.onPublish || ! params.onSubscribe )
+        throw new Error( OpenAjax.hub.Error.BadParameters );
+    
+    this._p = params;
+    this._onUnsubscribe = params.onUnsubscribe ? params.onUnsubscribe : null;
+    this._scope = params.scope || window;
+
+    if ( params.log ) {
+        var scope = this._scope;
+        var logfunc = params.log;
+        this._log = function( msg ) {
+            logfunc.call( scope, "ManagedHub: " + msg );
+        };
+    } else {
+        this._log = function() {};
+    }
+
+    this._subscriptions = { c:{}, s:null };
+    this._containers = {};
+
+    // Sequence # used to create IDs that are unique within this hub
+    this._seq = 0;
+
+    this._active = true;
+    
+    this._isPublishing = false;
+    this._pubQ = [];
+}
+
+/**
+ * Subscribe to a topic on behalf of a Container. Called only by 
+ * Container implementations, NOT by manager applications.
+ * 
+ * This function:
+ * 1. Checks with the ManagedHub's onSubscribe security policy
+ *    to determine whether this Container is allowed to subscribe 
+ *    to this topic.
+ * 2. If the subscribe operation is permitted, subscribes to the
+ *    topic and returns the ManagedHub's subscription ID for this
+ *    subscription. 
+ * 3. If the subscribe operation is not permitted, throws
+ *    OpenAjax.hub.Error.NotAllowed.
+ * 
+ * When data is published on the topic, the ManagedHub's 
+ * onPublish security policy will be invoked to ensure that
+ * this Container is permitted to receive the published data.
+ * If the Container is allowed to receive the data, then the
+ * Container's sendToClient function will be invoked.
+ * 
+ * When a Container needs to create a subscription on behalf of
+ * its client, the Container MUST use this function to create
+ * the subscription.
+ * 
+ * @param {OpenAjax.hub.Container} container  
+ *     A Container
+ * @param {String} topic 
+ *     A valid topic
+ * @param {String} containerSubID  
+ *     Arbitrary string ID that the Container uses to 
+ *     represent the subscription. Must be unique within the 
+ *     context of the Container
+ *
+ * @returns managerSubID  
+ *     Arbitrary string ID that this ManagedHub uses to 
+ *     represent the subscription. Will be unique within the 
+ *     context of this ManagedHub
+ * @type {String}
+ * 
+ * @throws {OpenAjax.hub.Error.Disconnected} if this.isConnected() returns false
+ * @throws {OpenAjax.hub.Error.NotAllowed} if subscription request is denied by the onSubscribe security policy
+ * @throws {OpenAjax.hub.Error.BadParameters} if one of the parameters, e.g. the topic, is invalid
+ */
+OpenAjax.hub.ManagedHub.prototype.subscribeForClient = function( container, topic, containerSubID )
+{
+    this._assertConn();
+    // check subscribe permission
+    if ( this._invokeOnSubscribe( topic, container ) ) {
+        // return ManagedHub's subscriptionID for this subscription
+        return this._subscribe( topic, this._sendToClient, this, { c: container, sid: containerSubID } );
+    }
+    throw new Error(OpenAjax.hub.Error.NotAllowed);
+}
+
+/**
+ * Unsubscribe from a subscription on behalf of a Container. Called only by 
+ * Container implementations, NOT by manager application code.
+ * 
+ * This function:
+ * 1. Destroys the specified subscription
+ * 2. Calls the ManagedHub's onUnsubscribe callback function
+ * 
+ * This function can be called even if the ManagedHub is not in a CONNECTED state.
+ * 
+ * @param {OpenAjax.hub.Container} container  
+ *    container instance that is unsubscribing
+ * @param {String} managerSubID  
+ *    opaque ID of a subscription, returned by previous call to subscribeForClient()
+ * 
+ * @throws {OpenAjax.hub.Error.NoSubscription} if subscriptionID does not refer to a valid subscription
+ */
+OpenAjax.hub.ManagedHub.prototype.unsubscribeForClient = function( container, managerSubID )
+{
+    this._unsubscribe( managerSubID );
+    this._invokeOnUnsubscribe( container, managerSubID );
+}
+  
+/**
+ * Publish data on a topic on behalf of a Container. Called only by 
+ * Container implementations, NOT by manager application code.
+ *
+ * @param {OpenAjax.hub.Container} container
+ *      Container on whose behalf data should be published
+ * @param {String} topic
+ *      Valid topic string. Must NOT contain wildcards.
+ * @param {*} data
+ *      Valid publishable data. To be portable across different
+ *      Container implementations, this value SHOULD be serializable
+ *      as JSON.
+ * 
+ * @throws {OpenAjax.hub.Error.Disconnected} if this.isConnected() returns false
+ * @throws {OpenAjax.hub.Error.BadParameters} if one of the parameters, e.g. the topic, is invalid
+ */
+OpenAjax.hub.ManagedHub.prototype.publishForClient = function( container, topic, data )
+{
+    this._assertConn();
+    this._publish( topic, data, container );
+}
+
+/**
+ * Destroy this ManagedHub
+ * 
+ * 1. Sets state to DISCONNECTED. All subsequent attempts to add containers,
+ *  publish or subscribe will throw the Disconnected error. We will
+ *  continue to allow "cleanup" operations such as removeContainer
+ *  and unsubscribe, as well as read-only operations such as 
+ *  isConnected
+ * 2. Remove all Containers associated with this ManagedHub
+ */
+OpenAjax.hub.ManagedHub.prototype.disconnect = function()
+{
+    this._active = false;
+    for (var c in this._containers) {
+        this.removeContainer( this._containers[c] );
+    }
+}
+
+/**
+ * Get a container belonging to this ManagedHub by its clientID, or null
+ * if this ManagedHub has no such container
+ * 
+ * This function can be called even if the ManagedHub is not in a CONNECTED state.
+ * 
+ * @param {String} containerId
+ *      Arbitrary string ID associated with the container
+ *
+ * @returns container associated with given ID
+ * @type {OpenAjax.hub.Container}
+ */
+OpenAjax.hub.ManagedHub.prototype.getContainer = function( containerId ) 
+{
+    var container = this._containers[containerId];
+    return container ? container : null;
+}
+
+/**
+ * Returns an array listing all containers belonging to this ManagedHub.
+ * The order of the Containers in this array is arbitrary.
+ * 
+ * This function can be called even if the ManagedHub is not in a CONNECTED state.
+ * 
+ * @returns container array
+ * @type {OpenAjax.hub.Container[]}
+ */
+OpenAjax.hub.ManagedHub.prototype.listContainers = function() 
+{
+    var res = [];
+    for (var c in this._containers) { 
+        res.push(this._containers[c]);
+    }
+    return res;
+}
+
+/**
+ * Add a container to this ManagedHub.
+ *
+ * This function should only be called by a Container constructor.
+ * 
+ * @param {OpenAjax.hub.Container} container
+ *      A Container to be added to this ManagedHub
+ * 
+ * @throws {OpenAjax.hub.Error.Duplicate} if there is already a Container
+ *      in this ManagedHub whose clientId is the same as that of container
+ * @throws {OpenAjax.hub.Error.Disconnected} if this.isConnected() returns false
+ */
+OpenAjax.hub.ManagedHub.prototype.addContainer = function( container ) 
+{ 
+    this._assertConn();
+    var containerId = container.getClientID();
+    if ( this._containers[containerId] ) {
+        throw new Error(OpenAjax.hub.Error.Duplicate);
+    }
+    this._containers[containerId] = container;
+}
+
+/**
+ * Remove a container from this ManagedHub immediately
+ * 
+ * This function can be called even if the ManagedHub is not in a CONNECTED state.
+ * 
+ * @param {OpenAjax.hub.Container} container  
+ *      A Container to be removed from this ManagedHub
+ *  
+ * @throws {OpenAjax.hub.Error.NoContainer}  if no such container is found
+ */
+OpenAjax.hub.ManagedHub.prototype.removeContainer = function( container )
+{
+    var containerId = container.getClientID();
+    if ( ! this._containers[ containerId ] ) {
+        throw new Error(OpenAjax.hub.Error.NoContainer);
+    }
+    container.remove();
+    delete this._containers[ containerId ];
+}
+
+    /*** OpenAjax.hub.Hub interface implementation ***/
+
+/**
+ * Subscribe to a topic.
+ * 
+ * This implementation of Hub.subscribe is synchronous. When subscribe 
+ * is called:
+ * 
+ * 1. The ManagedHub's onSubscribe callback is invoked. The 
+ * 		container parameter is null, because the manager application, 
+ * 		rather than a container, is subscribing.
+ * 2. If onSubscribe returns true, then the subscription is created.
+ * 3. The onComplete callback is invoked.
+ * 4. Then this function returns.
+ * 
+ * @param {String} topic
+ *     A valid topic string. MAY include wildcards.
+ * @param {Function} onData   
+ *     Callback function that is invoked whenever an event is 
+ *     published on the topic
+ * @param {Object} [scope]
+ *     When onData callback or onComplete callback is invoked,
+ *     the JavaScript "this" keyword refers to this scope object.
+ *     If no scope is provided, default is window.
+ * @param {Function} [onComplete]
+ *     Invoked to tell the client application whether the 
+ *     subscribe operation succeeded or failed. 
+ * @param {*} [subscriberData]
+ *     Client application provides this data, which is handed
+ *     back to the client application in the subscriberData
+ *     parameter of the onData and onComplete callback functions.
+ * 
+ * @returns subscriptionID
+ *     Identifier representing the subscription. This identifier is an 
+ *     arbitrary ID string that is unique within this Hub instance
+ * @type {String}
+ * 
+ * @throws {OpenAjax.hub.Error.Disconnected} if this Hub instance is not in CONNECTED state
+ * @throws {OpenAjax.hub.Error.BadParameters} if the topic is invalid (e.g. contains an empty token)
+ */
+OpenAjax.hub.ManagedHub.prototype.subscribe = function( topic, onData, scope, onComplete, subscriberData ) 
+{
+    this._assertConn();
+    this._assertSubTopic(topic);
+    if ( ! onData ) {
+        throw new Error( OpenAjax.hub.Error.BadParameters );
+    }
+    
+    // check subscribe permission
+    if ( ! this._invokeOnSubscribe( topic, null ) ) {
+        this._invokeOnComplete( onComplete, scope, null, false, OpenAjax.hub.Error.NotAllowed );
+        return;
+    }
+    
+    // on publish event, check publish permissions
+    scope = scope || window;
+    var that = this;
+    function publishCB( topic, data, sd, pcont ) {
+        if ( that._invokeOnPublish( topic, data, pcont, null ) ) {
+            try {
+                onData.call( scope, topic, data, subscriberData );
+            } catch( e ) {
+                OpenAjax.hub._debugger();
+                that._log( "caught error from onData callback to Hub.subscribe(): " + e.message );
+            }
+        }
+    }
+    
+    var subID = this._subscribe( topic, publishCB, scope, subscriberData );
+    
+    this._invokeOnComplete( onComplete, scope, subID, true );
+    return subID;
+}
+
+/**
+ * Publish an event on a topic
+ *
+ * This implementation of Hub.publish is synchronous. When publish 
+ * is called:
+ * 
+ * 1. The target subscriptions are identified.
+ * 2. For each target subscription, the ManagedHub's onPublish
+ * 		callback is invoked. Data is only delivered to a target
+ * 		subscription if the onPublish callback returns true.
+ * 		The pcont parameter of the onPublish callback is null.
+ *      This is because the ManagedHub, rather than a container,
+ *      is publishing the data.
+ * 
+ * @param {String} topic
+ *     A valid topic string. MUST NOT include wildcards.
+ * @param {*} data
+ *     Valid publishable data. To be portable across different
+ *     Container implementations, this value SHOULD be serializable
+ *     as JSON.
+ *     
+ * @throws {OpenAjax.hub.Error.Disconnected} if this Hub instance is not in CONNECTED state
+ * @throws {OpenAjax.hub.Error.BadParameters} if the topic cannot be published (e.g. contains 
+ *     wildcards or empty tokens) or if the data cannot be published (e.g. cannot be serialized as JSON)
+ */
+OpenAjax.hub.ManagedHub.prototype.publish = function( topic, data ) 
+{
+    this._assertConn();
+    this._assertPubTopic(topic);
+    this._publish( topic, data, null );
+}
+
+/**
+ * Unsubscribe from a subscription
+ * 
+ * This implementation of Hub.unsubscribe is synchronous. When unsubscribe 
+ * is called:
+ * 
+ * 1. The subscription is destroyed.
+ * 2. The ManagedHub's onUnsubscribe callback is invoked, if there is one.
+ * 3. The onComplete callback is invoked.
+ * 4. Then this function returns.
+ * 
+ * @param {String} subscriptionID
+ *     A subscriptionID returned by Hub.subscribe()
+ * @param {Function} [onComplete]
+ *     Callback function invoked when unsubscribe completes
+ * @param {Object} [scope]
+ *     When onComplete callback function is invoked, the JavaScript "this"
+ *     keyword refers to this scope object.
+ *     If no scope is provided, default is window.
+ *     
+ * @throws {OpenAjax.hub.Error.Disconnected} if this Hub instance is not in CONNECTED state
+ * @throws {OpenAjax.hub.Error.NoSubscription} if no such subscription is found
+ */
+OpenAjax.hub.ManagedHub.prototype.unsubscribe = function( subscriptionID, onComplete, scope )
+{
+    this._assertConn();
+    if ( typeof subscriptionID === "undefined" || subscriptionID == null ) {
+        throw new Error( OpenAjax.hub.Error.BadParameters );
+    }
+    this._unsubscribe( subscriptionID );
+    this._invokeOnUnsubscribe( null, subscriptionID );
+    this._invokeOnComplete( onComplete, scope, subscriptionID, true );
+}
+
+/**
+ * Returns true if disconnect() has NOT been called on this ManagedHub, 
+ * else returns false
+ * 
+ * @returns Boolean
+ * @type {Boolean}
+ */
+OpenAjax.hub.ManagedHub.prototype.isConnected = function()
+{
+    return this._active;
+}
+
+/**
+* Returns the scope associated with this Hub instance and which will be used
+* with callback functions.
+* 
+* This function can be called even if the Hub is not in a CONNECTED state.
+* 
+* @returns scope object
+* @type {Object}
+ */
+OpenAjax.hub.ManagedHub.prototype.getScope = function()
+{
+    return this._scope;
+}
+
+/**
+ * Returns the subscriberData parameter that was provided when 
+ * Hub.subscribe was called.
+ *
+ * @param subscriberID
+ *     The subscriberID of a subscription
+ * 
+ * @returns subscriberData
+ * @type {*}
+ * 
+ * @throws {OpenAjax.hub.Error.Disconnected} if this Hub instance is not in CONNECTED state
+ * @throws {OpenAjax.hub.Error.NoSubscription} if there is no such subscription
+ */
+OpenAjax.hub.ManagedHub.prototype.getSubscriberData = function( subscriberID )
+{
+    this._assertConn();
+    var path = subscriberID.split(".");
+    var sid = path.pop();
+    var sub = this._getSubscriptionObject( this._subscriptions, path, 0, sid );
+    if ( sub ) 
+        return sub.data;
+    throw new Error( OpenAjax.hub.Error.NoSubscription );
+}
+
+/**
+ * Returns the scope associated with a specified subscription.  This scope will
+ * be used when invoking the 'onData' callback supplied to Hub.subscribe().
+ *
+ * @param subscriberID
+ *     The subscriberID of a subscription
+ * 
+ * @returns scope
+ * @type {*}
+ * 
+ * @throws {OpenAjax.hub.Error.Disconnected} if this Hub instance is not in CONNECTED state
+ * @throws {OpenAjax.hub.Error.NoSubscription} if there is no such subscription
+ */
+OpenAjax.hub.ManagedHub.prototype.getSubscriberScope = function( subscriberID )
+{
+    this._assertConn();
+    var path = subscriberID.split(".");
+    var sid = path.pop();
+    var sub = this._getSubscriptionObject( this._subscriptions, path, 0, sid );
+    if ( sub ) 
+        return sub.scope;
+    throw new Error( OpenAjax.hub.Error.NoSubscription );
+}
+
+/**
+ * Returns the params object associated with this Hub instance.
+ * Allows mix-in code to access parameters passed into constructor that created
+ * this Hub instance.
+ *
+ * @returns params  the params object associated with this Hub instance
+ * @type {Object}
+ */
+OpenAjax.hub.ManagedHub.prototype.getParameters = function()
+{
+    return this._p;
+}
+
+
+/* PRIVATE FUNCTIONS */
+
+/**
+ * Send a message to a container's client. 
+ * This is an OAH subscriber's data callback. It is private to ManagedHub
+ * and serves as an adapter between the OAH 1.0 API and Container.sendToClient.
+ * 
+ * @param {String} topic Topic on which data was published
+ * @param {Object} data  Data to be delivered to the client
+ * @param {Object} sd    Object containing properties 
+ *     c: container to which data must be sent
+ *     sid: subscription ID within that container
+ * @param {Object} pcont  Publishing container, or null if this data was
+ *      published by the manager
+ */
+OpenAjax.hub.ManagedHub.prototype._sendToClient = function(topic, data, sd, pcont) 
+{
+    if (!this.isConnected()) {
+        return;
+    }
+    if ( this._invokeOnPublish( topic, data, pcont, sd.c ) ) {
+        sd.c.sendToClient( topic, data, sd.sid );
+    }
+}
+
+OpenAjax.hub.ManagedHub.prototype._assertConn = function() 
+{
+    if (!this.isConnected()) {
+        throw new Error(OpenAjax.hub.Error.Disconnected);
+    }
+}
+
+OpenAjax.hub.ManagedHub.prototype._assertPubTopic = function(topic) 
+{
+    if ((topic == null) || (topic == "") || (topic.indexOf("*") != -1) ||
+        (topic.indexOf("..") != -1) ||  (topic.charAt(0) == ".") ||
+        (topic.charAt(topic.length-1) == "."))
+    {
+        throw new Error(OpenAjax.hub.Error.BadParameters);
+    }
+}
+
+OpenAjax.hub.ManagedHub.prototype._assertSubTopic = function(topic) 
+{
+    if ( ! topic ) {
+        throw new Error(OpenAjax.hub.Error.BadParameters);
+    }
+    var path = topic.split(".");
+    var len = path.length;
+    for (var i = 0; i < len; i++) {
+        var p = path[i];
+        if ((p == "") ||
+           ((p.indexOf("*") != -1) && (p != "*") && (p != "**"))) {
+            throw new Error(OpenAjax.hub.Error.BadParameters);
+        }
+        if ((p == "**") && (i < len - 1)) {
+            throw new Error(OpenAjax.hub.Error.BadParameters);
+        }
+    }
+}
+
+OpenAjax.hub.ManagedHub.prototype._invokeOnComplete = function( func, scope, item, success, errorCode )
+{
+    if ( func ) { // onComplete is optional
+        try {
+            scope = scope || window;
+            func.call( scope, item, success, errorCode );
+        } catch( e ) {
+            OpenAjax.hub._debugger();
+            this._log( "caught error from onComplete callback: " + e.message );
+        }
+    }
+}
+
+OpenAjax.hub.ManagedHub.prototype._invokeOnPublish = function( topic, data, pcont, scont )
+{
+    try {
+        return this._p.onPublish.call( this._scope, topic, data, pcont, scont );
+    } catch( e ) {
+        OpenAjax.hub._debugger();
+        this._log( "caught error from onPublish callback to constructor: " + e.message );
+    }
+    return false;
+}
+
+OpenAjax.hub.ManagedHub.prototype._invokeOnSubscribe = function( topic, container )
+{
+    try {
+        return this._p.onSubscribe.call( this._scope, topic, container );
+    } catch( e ) {
+        OpenAjax.hub._debugger();
+        this._log( "caught error from onSubscribe callback to constructor: " + e.message );
+    }
+    return false;
+}
+
+OpenAjax.hub.ManagedHub.prototype._invokeOnUnsubscribe = function( container, managerSubID )
+{
+    if ( this._onUnsubscribe ) {
+        var topic = managerSubID.slice( 0, managerSubID.lastIndexOf(".") );
+        try {
+            this._onUnsubscribe.call( this._scope, topic, container );
+        } catch( e ) {
+            OpenAjax.hub._debugger();
+            this._log( "caught error from onUnsubscribe callback to constructor: " + e.message );
+        }
+    }
+}
+
+OpenAjax.hub.ManagedHub.prototype._subscribe = function( topic, onData, scope, subscriberData ) 
+{
+    var handle = topic + "." + this._seq;
+    var sub = { scope: scope, cb: onData, data: subscriberData, sid: this._seq++ };
+    var path = topic.split(".");
+    this._recursiveSubscribe( this._subscriptions, path, 0, sub );
+    return handle;
+}
+
+OpenAjax.hub.ManagedHub.prototype._recursiveSubscribe = function(tree, path, index, sub) 
+{
+    var token = path[index];
+    if (index == path.length) {
+        sub.next = tree.s;
+        tree.s = sub;
+    } else { 
+        if (typeof tree.c == "undefined") {
+             tree.c = {};
+         }
+        if (typeof tree.c[token] == "undefined") {
+            tree.c[token] = { c: {}, s: null }; 
+            this._recursiveSubscribe(tree.c[token], path, index + 1, sub);
+        } else {
+            this._recursiveSubscribe( tree.c[token], path, index + 1, sub);
+        }
+    }
+}
+
+OpenAjax.hub.ManagedHub.prototype._publish = function( topic, data, pcont )
+{
+    // if we are currently handling a publish event, then queue this request
+    // and handle later, one by one
+    if ( this._isPublishing ) {
+        this._pubQ.push( { t: topic, d: data, p: pcont } );
+        return;
+    }
+    
+    this._safePublish( topic, data, pcont );
+    
+    while ( this._pubQ.length > 0 ) {
+        var pub = this._pubQ.shift();
+        this._safePublish( pub.t, pub.d, pub.p );
+    }
+}
+
+OpenAjax.hub.ManagedHub.prototype._safePublish = function( topic, data, pcont )
+{
+    this._isPublishing = true;
+    var path = topic.split(".");
+    this._recursivePublish( this._subscriptions, path, 0, topic, data, pcont );
+    this._isPublishing = false;
+}
+
+OpenAjax.hub.ManagedHub.prototype._recursivePublish = function(tree, path, index, name, msg, pcont) 
+{
+    if (typeof tree != "undefined") {
+        var node;
+        if (index == path.length) {
+            node = tree;
+        } else {
+            this._recursivePublish(tree.c[path[index]], path, index + 1, name, msg, pcont);
+            this._recursivePublish(tree.c["*"], path, index + 1, name, msg, pcont);
+            node = tree.c["**"];
+        }
+        if (typeof node != "undefined") {
+            var sub = node.s;
+            while ( sub ) {
+                var sc = sub.scope;
+                var cb = sub.cb;
+                var d = sub.data;
+                var sid = sub.sid;
+                if (typeof cb == "string") {
+                    // get a function object
+                    cb = sc[cb];
+                }
+                cb.call(sc, name, msg, d, pcont);
+                sub = sub.next;
+            }
+        }
+    }
+}
+
+OpenAjax.hub.ManagedHub.prototype._unsubscribe = function( subscriptionID )
+{
+    var path = subscriptionID.split(".");
+    var sid = path.pop();
+    if ( ! this._recursiveUnsubscribe( this._subscriptions, path, 0, sid ) ) {
+        throw new Error( OpenAjax.hub.Error.NoSubscription );
+    }
+}
+
+/**
+ * @returns 'true' if properly unsubscribed; 'false' otherwise
+ */
+OpenAjax.hub.ManagedHub.prototype._recursiveUnsubscribe = function(tree, path, index, sid) 
+{
+    if ( typeof tree == "undefined" ) {
+        return false;
+    }
+    
+    if (index < path.length) {
+        var childNode = tree.c[path[index]];
+        if ( ! childNode ) {
+            return false;
+        }
+        this._recursiveUnsubscribe(childNode, path, index + 1, sid);
+        if (childNode.s == null) {
+            for (var x in childNode.c) {
+                return true;
+            }
+            delete tree.c[path[index]];    
+        }
+    } else {
+        var sub = tree.s;
+        var sub_prev = null;
+        var found = false;
+        while ( sub ) {
+            if ( sid == sub.sid ) {
+                found = true;
+                if ( sub == tree.s ) {
+                    tree.s = sub.next;
+                } else {
+                    sub_prev.next = sub.next;
+                }
+                break;
+            }
+            sub_prev = sub;
+            sub = sub.next;
+        }
+        if ( ! found ) {
+            return false;
+        }
+    }
+    
+    return true;
+}
+
+OpenAjax.hub.ManagedHub.prototype._getSubscriptionObject = function( tree, path, index, sid )
+{
+    if (typeof tree != "undefined") {
+        if (index < path.length) {
+            var childNode = tree.c[path[index]];
+            return this._getSubscriptionObject(childNode, path, index + 1, sid);
+        }
+
+        var sub = tree.s;
+        while ( sub ) {
+            if ( sid == sub.sid ) {
+                return sub;
+            }
+            sub = sub.next;
+        }
+    }
+    return null;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Container
+ * @constructor
+ * 
+ * Container represents an instance of a manager-side object that contains and
+ * communicates with a single client of the hub. The container might be an inline
+ * container, an iframe FIM container, or an iframe PostMessage container, or
+ * it might be an instance of some other implementation.
+ *
+ * @param {OpenAjax.hub.ManagedHub} hub
+ *    Managed Hub instance
+ * @param {String} clientID
+ *    A string ID that identifies a particular client of a Managed Hub. Unique
+ *    within the context of the ManagedHub.
+ * @param {Object} params  
+ *    Parameters used to instantiate the Container.
+ *    Once the constructor is called, the params object belongs exclusively to
+ *    the Container. The caller MUST not modify it.
+ *    Implementations of Container may specify additional properties
+ *    for the params object, besides those identified below.
+ *    The following params properties MUST be supported by all Container 
+ *    implementations:
+ * @param {Function} params.Container.onSecurityAlert
+ *    Called when an attempted security breach is thwarted.  Function is defined
+ *    as follows:  function(container, securityAlert)
+ * @param {Function} [params.Container.onConnect]
+ *    Called when the client connects to the Managed Hub.  Function is defined
+ *    as follows:  function(container)
+ * @param {Function} [params.Container.onDisconnect]
+ *    Called when the client disconnects from the Managed Hub.  Function is
+ *    defined as follows:  function(container)
+ * @param {Object} [params.Container.scope]
+ *    Whenever one of the Container's callback functions is called, references
+ *    to "this" in the callback will refer to the scope object. If no scope is
+ *    provided, default is window.
+ * @param {Function} [params.Container.log]
+ *    Optional logger function. Would be used to log to console.log or
+ *    equivalent. 
+ *
+ * @throws {OpenAjax.hub.Error.BadParameters}   if required params are not
+ *   present or null
+ * @throws {OpenAjax.hub.Error.Duplicate}   if a Container with this clientID
+ *   already exists in the given Managed Hub
+ * @throws {OpenAjax.hub.Error.Disconnected}   if ManagedHub is not connected
+ */
+//OpenAjax.hub.Container = function( hub, clientID, params ) {}
+
+/**
+ * Send a message to the client inside this container. This function MUST only
+ * be called by ManagedHub. 
+ * 
+ * @param {String} topic
+ *    The topic name for the published message
+ * @param {*} data
+ *    The payload. Can be any JSON-serializable value.
+ * @param {String} containerSubscriptionId
+ *    Container's ID for a subscription, from previous call to
+ *    subscribeForClient()
+ */
+//OpenAjax.hub.Container.prototype.sendToClient = function( topic, data, containerSubscriptionId ) {}
+
+/**
+ * Shut down a container. remove does all of the following:
+ * - disconnects container from HubClient
+ * - unsubscribes from all of its existing subscriptions in the ManagedHub
+ * 
+ * This function is only called by ManagedHub.removeContainer
+ * Calling this function does NOT cause the container's onDisconnect callback to
+ * be invoked.
+ */
+//OpenAjax.hub.Container.prototype.remove = function() {}
+
+/**
+ * Returns true if the given client is connected to the managed hub.
+ * Else returns false.
+ *
+ * @returns true if the client is connected to the managed hub
+ * @type boolean
+ */
+//OpenAjax.hub.Container.prototype.isConnected = function() {}
+
+/**
+ * Returns the clientID passed in when this Container was instantiated.
+ *
+ * @returns The clientID
+ * @type {String}  
+ */
+//OpenAjax.hub.Container.prototype.getClientID = function() {}
+
+/**
+ * If DISCONNECTED:
+ * Returns null
+ * If CONNECTED:
+ * Returns the origin associated with the window containing the HubClient
+ * associated with this Container instance. The origin has the format
+ *  
+ * [protocol]://[host]
+ * 
+ * where:
+ * 
+ * [protocol] is "http" or "https"
+ * [host] is the hostname of the partner page.
+ * 
+ * @returns Partner's origin
+ * @type {String}
+ */
+//OpenAjax.hub.Container.prototype.getPartnerOrigin = function() {}
+
+/**
+ * Returns the params object associated with this Container instance.
+ *
+ * @returns params
+ *    The params object associated with this Container instance
+ * @type {Object}
+ */
+//OpenAjax.hub.Container.prototype.getParameters = function() {}
+
+/**
+ * Returns the ManagedHub to which this Container belongs.
+ *
+ * @returns ManagedHub
+ *         The ManagedHub object associated with this Container instance
+ * @type {OpenAjax.hub.ManagedHub}
+ */
+//OpenAjax.hub.Container.prototype.getHub = function() {}
+
+////////////////////////////////////////////////////////////////////////////////
+
+/*
+ * Unmanaged Hub
+ */
+
+/**
+ * OpenAjax.hub._hub is the default ManagedHub instance that we use to 
+ * provide OAH 1.0 behavior. 
+ */
+OpenAjax.hub._hub = new OpenAjax.hub.ManagedHub({ 
+    onSubscribe: function(topic, ctnr) { return true; },
+    onPublish: function(topic, data, pcont, scont) { return true; }
+});
+
+/**
+ * Subscribe to a topic.
+ *
+ * @param {String} topic
+ *     A valid topic string. MAY include wildcards.
+ * @param {Function|String} onData
+ *     Callback function that is invoked whenever an event is published on the
+ *     topic.  If 'onData' is a string, then it represents the name of a
+ *     function on the 'scope' object.
+ * @param {Object} [scope]
+ *     When onData callback is invoked,
+ *     the JavaScript "this" keyword refers to this scope object.
+ *     If no scope is provided, default is window.
+ * @param {*} [subscriberData]
+ *     Client application provides this data, which is handed
+ *     back to the client application in the subscriberData
+ *     parameter of the onData callback function.
+ * 
+ * @returns {String} Identifier representing the subscription.
+ * 
+ * @throws {OpenAjax.hub.Error.BadParameters} if the topic is invalid
+ *     (e.g.contains an empty token)
+ */
+OpenAjax.hub.subscribe = function(topic, onData, scope, subscriberData) 
+{
+    // resolve the 'onData' function if it is a string
+    if ( typeof onData === "string" ) {
+        scope = scope || window;
+        onData = scope[ onData ] || null;
+    }
+    
+    return OpenAjax.hub._hub.subscribe( topic, onData, scope, null, subscriberData );
+}
+
+/**
+ * Unsubscribe from a subscription.
+ *
+ * @param {String} subscriptionID
+ *     Subscription identifier returned by subscribe()
+ *     
+ * @throws {OpenAjax.hub.Error.NoSubscription} if no such subscription is found
+ */
+OpenAjax.hub.unsubscribe = function(subscriptionID) 
+{
+    return OpenAjax.hub._hub.unsubscribe( subscriptionID );
+}
+
+/**
+ * Publish an event on a topic.
+ *
+ * @param {String} topic
+ *     A valid topic string. MUST NOT include wildcards.
+ * @param {*} data
+ *     Valid publishable data.
+ *     
+ * @throws {OpenAjax.hub.Error.BadParameters} if the topic cannot be published
+ *     (e.g. contains wildcards or empty tokens)
+ */
+OpenAjax.hub.publish = function(topic, data) 
+{
+    OpenAjax.hub._hub.publish(topic, data);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Register the OpenAjax Hub itself as a library.
+OpenAjax.hub.registerLibrary("OpenAjax", "http://openajax.org/hub", "2.0", {});
+
+} // !window["OpenAjax"]
diff --git a/UNGProject/openajaxhub/src/containers/iframe/CommLib.js b/UNGProject/openajaxhub/src/containers/iframe/CommLib.js
new file mode 100644
index 0000000000000000000000000000000000000000..91129768116b529a00d3c94b79512266d1bf51da
--- /dev/null
+++ b/UNGProject/openajaxhub/src/containers/iframe/CommLib.js
@@ -0,0 +1,508 @@
+/*
+ * (C) Copyright IBM Corp. 2007
+ */
+
+var partnerWindowNullError = new Error ("The communication partner's window was set to null.");
+var notInitializedError = new Error ("CommLib was not initialized.");
+/**
+* Communication Library which takes care of the cross domain IFrame communication
+* 
+* Goal: Provide an policy independent communication module for use in experiments such as SEHub or policy for free.
+* 
+* The application using this library should not use any frames with the same name as the tunnelGUID.
+**/
+
+/**
+ * The protocol that is implemented in this object uses the following message types
+ * 
+ * init: Initializes the CommLib. The data exchanged in this message contains configuration parameters.
+ * start: The begining of a multimpart message. The data exchanged in this message is the first part of the multipart message.
+ * part: An intermediate part of a multipart message. The data exchanged in this message is a part of the whole message.
+ * end: The end of a message. If the message is a multipart message, this is the final part. If this is not a multipart message this is the only and therefore also final part.
+ * ok: An acknowledgement message. This is sent back to the communicating partner to inform recieval of the message.
+ * loaded: A message sent by the tunnel iframe to inform the component of the fact that the tunnel is now open.
+ **/
+
+function CommLib(){
+	// polling and queue processing interval
+	var interval=10
+	// The maximul length of a URL. If the message is longer it will be split into different parts.
+	var urlLimit = 4000; 
+	// Keeps track of the sending state of the component.
+	var sending = false; 
+	// The current value of the data behind the Hash. Will be used to discover incoming messages.
+	var currentHash = null; 
+	// The URL of the partner iFrame.
+	var partnerURL = null; 
+	// The name of the window of the partner iFrame.
+	var partnerWindow = null; 
+	// The data that will be send to the partner iFrame.
+	var messageOut = null;
+	// The split version of the outgoing message to make sure that we don't go over the limit of the url length.	 
+	var messageOutParts = []; 
+	// The index of the current message that is being sent.
+	var currentOutPart = 0; 
+	// Unique identifier to track the current message which we are communicating. Currently used to make sure "ok" is mapped to the last send message.
+	var messageNr = 0; 
+	// The incomming message recieved from the partner iFrame.
+	var messageIn = ""; 
+	// This is used to make the object available to the private methods. This is a workaround for an error in the ECMAScript Language Specification which causes this to be set incorrectly for inner functions. See http://www.crockford.com/javascript/private.html
+	var that=this;
+	// A queue for outgoing messages. This queue is used when new send requests are done while we are still sending or recieving a message.
+	var queueOut=[];
+	// Variable storing the identifier for the setInterval if processing an output queue	
+	var queueOutProcess=null;
+	// A queue for incomming messages. This queue is used when new messages arrive but there is no reciepient set yet. This can occur if one of the frames requires a long loading time.
+	var	queueIn=[];
+	// Variable storing the identifier for the setInterval if processing an input queue	
+	var queueInProcess=null;
+	// Variable storing the callback to the recieved function
+	var recieved=null;	
+	// Variable storing the callback to the security listener function
+	var securityListener=null;
+	// Variable storing the initialization 
+	var initialized=false;
+	// The security token used for checking message origin
+	var securityToken=null;
+	/**
+	 * Sends a message to the partner iFrame.
+	 * 
+	 * @param message The textual data that will be send to the partner iFrame
+	 */
+	this.send=function(message){
+		// Queue the message if sending or if there is no communication partner yet
+		if (sending || partnerWindow==null){
+			queueOut[queueOut.length]=message;
+			// Start a timer if no timer has started yet
+			if (queueOut.length==1){
+				queueOutProcess=setInterval(processOutQueue,interval);
+			}
+			return;
+		}
+		//URI encode the message for transport over the fragment
+		var encodedData=encodeURIComponent(message);
+		// Current code ignores messages when already sending		
+		if(!sending){
+			sending = true;
+			messageOut = encodedData || "";
+			sendMessageStart();
+		}
+	}
+
+	/**
+	 * Sets the callback which will be called when a new message has been recieved.
+	 * 
+	 * @param callback The callback to the recieved method;
+	 */
+	this.setRecieved=function(callback){
+		recieved=callback;
+	};
+	
+	/**
+	 * Sets the callback for security errors.
+	 * 
+	 * @param The callback for security errors.
+	 */
+	this.setSecurityListener=function(callback){
+		securityListener=callback;
+	}
+	
+	/**
+	 * Starts listening for incomming messages by polling the data after the #
+	 */
+	this.listen=function(){
+		//console.debug ("CommLib.listen " + window.location.href.split("#")[0]);
+		//Start counter to inspect hash value.
+		setInterval(pollHash, interval);
+	}
+	
+	/**
+	 * Sets the communication partner's info
+	 * @param parWindow The partner window.
+	 * @param parURL The partner URL.
+	 */
+	this.setPartnerWindow=function(parWindow){
+		if (parWindow==null)throw partnerWindowNullError;
+		partnerWindow=parWindow;
+	}
+	
+	/**
+	 * Returns the URL of the partner of this CommLib.
+	 */
+	this.getPartnerURL=function(){
+		return partnerURL;
+	}
+
+	/**
+	 * Returns the security token used by this CommLib.
+	 */
+	this.getSecurityToken=function(){
+		return securityToken;
+	}
+
+	/**
+	 * Processes a the output queue
+	 */
+	function processOutQueue(){
+		// return if not ready to send
+		if (sending || partnerWindow==null)return;
+		// Send the first element in the Array
+		that.send(queueOut.shift());
+		// Stop sending polling when the queue is empty
+		if (queueOut.length==0)clearInterval(queueOutProcess);
+	}
+	
+	/**
+	 * Checks the information after the hash to see if there is a new incomming message.
+	 */
+	function pollHash(){
+		//Can't use location.hash because at least Firefox does a decodeURIComponent on it.
+		var urlParts = window.location.href.split("#");
+		if(urlParts.length == 2){
+			var newHash = urlParts[1];
+			if(newHash != currentHash){
+				try{
+					messageReceived(newHash);
+				}catch(e){
+					//Make sure to not keep processing the error hash value.
+					currentHash = newHash;
+					throw e;
+				}
+				currentHash = newHash;
+			}
+		}
+	}
+	
+	/**
+	 * Processes a the output queue
+	 */
+	function processInQueue(){
+		// return if the reciever method has not been set
+		if (that.recieved==null)return;
+		// Send the first element in the Array
+		that.recieved(queueIn.shift());
+		// Stop polling when the queue is empty
+		if (queueIn.length==0)clearInterval(queueInProcess);
+	}
+
+	/**
+	 * This method boots the sending of a messages. It is responsible for splitting the data in parts if necessary.
+	 */
+	function sendMessageStart(){
+		//Break the message into parts, if necessary.
+		messageOutParts = [];	
+		var reqData = messageOut;
+		var urlLength = partnerURL.length;
+		var partLength = urlLimit - urlLength;
+		var reqIndex = 0;
+	
+		while((reqData.length - reqIndex) + urlLength > urlLimit){
+			var part = reqData.substring(reqIndex, reqIndex + partLength);
+			//Safari will do some extra hex escaping unless we keep the original hex
+			//escaping complete.
+			var percentIndex = part.lastIndexOf("%");
+			if(percentIndex == part.length - 1 || percentIndex == part.length - 2){
+				part = part.substring(0, percentIndex);
+			}
+			messageOutParts.push(part);
+			reqIndex += part.length;
+		}
+		messageOutParts.push(reqData.substring(reqIndex, reqData.length));
+		
+		currentOutPart = 0;
+		sendMessagePart();	
+	}
+	
+	/**
+	 * Sends the current part of the message. This method is required for split messages.
+	 */
+	function sendMessagePart(){
+		if(currentOutPart < messageOutParts.length){
+			messageNr++;
+			//Get the message part.
+			var partData = messageOutParts[currentOutPart];
+	
+			//Get the command.
+			var cmd = "part";
+			if(currentOutPart + 1 == messageOutParts.length){
+				cmd = "end";
+			}else if (currentOutPart == 0){
+				cmd = "start";
+			}
+			
+			setPartnerUrl(cmd, messageNr, partData);
+			currentOutPart++;
+		}
+		else{
+			sending=false;
+			currentOutPart=0;
+		}
+	}
+	
+	/**
+	 * Sets the URL of the partner iFrame. This actually transmits the data to the partner iFrame.
+	 * 
+	 * @param cmd The current command that is being used. @see #messageReceived.
+	 * @param messageNr A counter keeping track of the current message we are sending. This counter is used by both partners to identify which message they are exchanging.
+	 * @param message The actual encoded messag which will be send to the partner.
+	 */
+	function setPartnerUrl(cmd, messageNr, message){
+		if (!initialized)throw notInitializedError;
+		var url = makePartnerUrl(cmd,messageNr,message);
+		//console.debug ("CommLib.setPartnerUrl " + window.location.href.split("#")[0] + " "  + cmd + " " + message);
+		//Safari won't let us replace across domains.
+		if(navigator.userAgent.indexOf("Safari") == -1){
+			partnerWindow.location.replace(url);
+		}else{
+			partnerWindow.location = url;
+		}
+	}
+
+
+	/**
+	 * Creates the full URL that will be sent to the partner. This method adds the command, message number, and data to the partner URL.
+	 * 
+	 * @param cmd The current command that is being used. @see #messageReceived.
+	 * @param messageNr A counter keeping track of the current message we are sending. This counter is used by both partners to identify which message they are exchanging.
+	 * @param message The actual encoded messag which will be send to the partner.	 * 
+	 */	
+	function makePartnerUrl(cmd, messageNr, message){
+		var url = partnerURL + "#" + cmd + ":" + messageNr + ":" + securityToken;
+		if(message){
+			url += ":" + message;
+		}
+		return url;
+	}
+	
+	/**
+	 * Unwraps and decodes the incomming message. 
+	 * @param encodedMessage The data behind the #.
+	 * @return An object representing the decoded data.
+	 */
+	function unpackMessage(encodedMessage){
+		var parts = encodedMessage.split(":");
+		var command = parts[0];
+		messageNr=parts[1];
+		var token=parts[2];
+		encodedMessage = parts[3] || "";
+		var config = null;		
+		if(command == "init"){
+			// initialize security token
+			securityToken=token;
+			var configParts = encodedMessage.split("&");
+			config = {};
+			for(var i = 0; i < configParts.length; i++){
+				var nameValue = configParts[i].split("=");
+				config[decodeURIComponent(nameValue[0])] = decodeURIComponent(nameValue[1]);
+			}
+		}		
+		else{
+			//verify security token
+			if (token!=securityToken){
+				if (securityListener!=null){				
+					securityListener(SecurityErrors.INVALID_TOKEN);
+				}
+				else{
+					throw new Error (SecurityErrors.INVALID_TOKEN_MSG);
+				}
+				return null;
+			}	
+		}
+		return {command: command, message: encodedMessage, config: config, number: messageNr};
+	}
+
+	/**
+	 * Is called when a new message has been detected. I.e., when the data behind the # has changed.
+	 * 
+	 * @param encodedData The URI encoded data which is stored behind the #.
+	 */
+	function messageReceived(encodedData){
+		//console.debug ("CommLib.messageRecieved " + window.location.href.split("#")[0] + " "  + encodedData);
+		var msg = unpackMessage(encodedData);
+		// msg is null when a security error occurs
+		if (msg==null) return;
+		switch(msg.command){
+			case "init":
+				init(msg.config);
+				initialized=true;
+				break;
+			case "ok":
+				sendMessagePart();
+				break;
+			case "start":
+				messageIn = "";
+				messageIn += msg.message;
+				setPartnerUrl("ok", messageNr);
+				break;
+			case "part":
+				messageIn += msg.message;
+				setPartnerUrl("ok", messageNr);
+				break;
+			case "end":
+				messageIn += msg.message;
+				// Needed to be done before the actual message is processed.
+				setPartnerUrl("ok", messageNr);
+				// TODO check the actual impact of this change. It was needed to keep the code running. 
+				// This basically says that recieving a new message before the ACK was recieved is considered as an ACK + the new message.
+				sending=false;
+				if (recieved==null || queueIn.length>0){
+					//Queue the message and start the queue processor
+					queueIn[queueIn.length]=decodeURIComponent(messageIn);
+					// Start a timer if no timer has started yet
+					if (queueIn.length==1){
+						queueInProcess=setInterval(processInQueue,interval);
+					}
+				}				
+				else{
+					recieved(decodeURIComponent(messageIn));
+				}
+				messageIn="";
+				break;				
+		}
+	}
+	
+	function init(config){	
+		// get the partnerURL based on the config information
+		partnerURL=config.pU;
+	}	
+	
+	// Triggers reading the initialization information.
+  pollHash();
+};
+
+
+function CommLibComponent(){
+	// Variable storing the CommLib (Note the setting of the init callback upon creation)
+	var commLib=new CommLib();
+	// GUI which will be used to name the iFrame tunnel.
+	var tunnelGUID="3827816c-f3b1-11db-8314-0800200c9a66"
+
+	/**
+	 * Sets the callback for incomming messages.
+	 * 
+	 * @param The callback for incomming messages.
+	 */
+	this.setRecieved=function(callback){
+		commLib.setRecieved(callback);
+	}
+
+	/**
+	 * Sets the callback for security errors.
+	 * 
+	 * @param The callback for security errors.
+	 */
+	this.setSecurityListener=function(callback){
+		commLib.setSecurityListener(callback);
+	}
+
+	/**
+	 * Sends a message to the partner iFrame.
+	 * 
+	 * @param message The textual data that will be send to the partner iFrame
+	 */	
+	this.send=function(message){
+		return commLib.send(message);
+	}
+
+	/**
+	 * Creates the iFrame though which the communication with the main application is done.
+	 */
+	function createTunnelIFrame(partnerURL,tunnelGUID, securityToken){
+		var iframe = document.createElement("iframe");
+		iframe.src=partnerURL + "#init:0:" + securityToken + ":pU=" + encodeURIComponent(window.location.href.split("#")[0]);
+		iframe.name=tunnelGUID;
+		iframe.id=tunnelGUID;
+		document.body.appendChild(iframe);
+		if (navigator.userAgent.indexOf("Safari") == -1) {
+			iframe.style.position = "absolute";
+		}
+		iframe.style.left = iframe.style.top = "0px";
+		iframe.style.height = iframe.style.width = "1px";
+		iframe.style.visibility = "hidden";
+	}
+
+	/**
+	 * Initializes the communication library based on the information in the config. There are two roles:
+	 * 1. Component: In this role the CommLib resides inside the component and bridges the communication between the domain of the component and the domain of the main application.
+ 	 * 2. Tunnel: In this role the CommLib resides inside the tunnel iFrame and bridges the communication between the domain of the component and the domain of the main application.
+ 	 * In the tunnel role the iFrame is hidden internally in the component but since the iFrame in the component and the main application are in the same domain they can talk to each other. 
+ 	 * This is implemented in this way because of the required iFrame recursion for IE 7.0 See http://tagneto.blogspot.com/2006/10/ie-7-and-iframe-apis-part-2.html.
+ 	 * 
+ 	 * @param config The configuration information on which the lib will base it's initialization.
+	 */
+	function init(){
+		// Generate the tunnel iframe
+		createTunnelIFrame(commLib.getPartnerURL(),tunnelGUID,commLib.getSecurityToken());
+		// Set the partner window
+		commLib.setPartnerWindow(window.frames[tunnelGUID]);
+		// Start listening
+		commLib.listen();
+	}
+	init();		
+};
+
+function CommLibTunnel(){
+	var commLib=new CommLib();
+
+	/**
+	 * Returns the URL of the partner of this CommLib.
+	 */
+	this.getPartnerURL=function(){
+		return commLib.getPartnerURL();
+	}
+
+	/**
+	 * Returns the security token used by this CommLib.
+	 */
+	this.getSecurityToken=function(){
+		return commLib.getSecurityToken();
+	}
+
+	/**
+	 * Sets the callback for incomming messages.
+	 * 
+	 * @param The callback for incomming messages.
+	 */
+	this.setRecieved=function(callback){
+		commLib.setRecieved(callback);
+	}
+	
+	/**
+	 * Sets the callback for security errors.
+	 * 
+	 * @param The callback for security errors.
+	 */
+	this.setSecurityListener=function(callback){
+		commLib.setSecurityListener(callback);
+	}	
+
+	/**
+	 * Sends a message to the partner iFrame.
+	 * 
+	 * @param message The textual data that will be send to the partner iFrame
+	 */	
+	this.send=function(message){
+		return commLib.send(message);
+	}
+	
+	/**
+	 * Initializes the communication library based on the information in the config. There are two roles:
+	 * 1. Component: In this role the CommLib resides inside the component and bridges the communication between the domain of the component and the domain of the main application.
+ 	 * 2. Tunnel: In this role the CommLib resides inside the tunnel iFrame and bridges the communication between the domain of the component and the domain of the main application.
+ 	 * In the tunnel role the iFrame is hidden internally in the component but since the iFrame in the component and the main application are in the same domain they can talk to each other. 
+ 	 * This is implemented in this way because of the required iFrame recursion for IE 7.0 See http://tagneto.blogspot.com/2006/10/ie-7-and-iframe-apis-part-2.html.
+ 	 * 
+ 	 * @param config The configuration information on which the lib will base it's initialization.
+	 */
+	function init(config){	
+		// Set the partner window
+		commLib.setPartnerWindow(parent);
+		// Start listening for incomming messages.
+		commLib.listen();
+	}
+	
+	this.setOnunloadHandler=function(callback){
+		window.onunload=callback;
+	}
+	init();	
+};
diff --git a/UNGProject/openajaxhub/src/containers/iframe/FIM.js b/UNGProject/openajaxhub/src/containers/iframe/FIM.js
new file mode 100644
index 0000000000000000000000000000000000000000..8536e71b8b2f4cd22890d69572f7ad3af9f2b18e
--- /dev/null
+++ b/UNGProject/openajaxhub/src/containers/iframe/FIM.js
@@ -0,0 +1,1958 @@
+/*
+
+        Copyright 2006-2009 OpenAjax Alliance
+
+        Licensed under the Apache License, Version 2.0 (the "License"); 
+        you may not use this file except in compliance with the License. 
+        You may obtain a copy of the License at
+        
+                http://www.apache.org/licenses/LICENSE-2.0
+
+        Unless required by applicable law or agreed to in writing, software 
+        distributed under the License is distributed on an "AS IS" BASIS, 
+        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+        See the License for the specific language governing permissions and 
+        limitations under the License.
+*/
+
+
+// XXX revert r231 - Revision 231 added support for having the client pass back
+// both the initial URI and the current URI, which are different in the case
+// or redirection.  However, in order for this to work, the final client code
+// must set smash._initialClientURI to the initial URI (the URI for the page
+// that did the redirection).  There isn't a clean way to do this with the
+// current Hub 2.0 APIs, so I'm disabling this feature for now.  Search the code
+// for "XXX revert r231".
+
+
+if ( typeof OpenAjax === "undefined" ) {
+    OpenAjax = { hub: {} };
+}
+
+(function(){
+
+OpenAjax.hub.IframeFIMContainer = function( container, hub, clientID, params )
+{
+    this._container = container;
+    this._hub = hub;
+    this._onSecurityAlert = params.Container.onSecurityAlert;
+    this._onConnect = params.Container.onConnect ? params.Container.onConnect : null;
+    this._onDisconnect = params.Container.onDisconnect ? params.Container.onDisconnect : null;
+    this._scope = params.Container.scope || window;
+    this._subs = {};
+    
+    // XXX Need to make sure URI is absolute, or change the "clientURI!=componentURI"
+    // comparison in SEComm.initializationFinished (where 'clientURI' is always
+    // absolute, but 'componentURI' is based on params.IframeContainer.uri and
+    // may be relative, which makes the comparison fail)
+    this._clientURI = params.IframeContainer.uri;
+
+    smash.SEComm.tunnelURI = params.IframeContainer.tunnelURI;
+    smash._loadTimeout = params.IframeContainer.timeout || 15000;
+    
+    if ( params.Container.log ) {
+        var scope = this._scope;
+        var logfunc = params.Container.log;
+        this._log = function( msg ) {
+            logfunc.call( scope, "IframeContainer::" + clientID + ": " + msg );
+        };
+    } else {
+        this._log = function() {};
+    }
+    
+    // configurable goodbyeMessage: protects against malicious unloading of the mashup application
+//    if (params.goodbyeMessage != null) {
+//        smash._goodbyeMessage = params.goodbyeMessage;
+//    }
+    // configurable securityTokenLength
+//    if (params.securityTokenLength != null) {
+//        smash._securityTokenLength = params.securityTokenLength;
+//        smash._computeOtherTokenConstants();
+//    }
+    
+    // create and configure the pseudo-random number generator, used to create
+    // security tokens
+    smash._createPRNG( this, params );
+    
+    smash._ensureSingletonManager();
+    // the 'internal ID' is guaranteed to be unique within the page, not just
+    // the ManagedHub instance
+    this._internalID = smash._singletonManager.generateUniqueClientName( clientID );
+}
+
+OpenAjax.hub.IframeFIMContainer.prototype.getHub = function() {
+	return this._hub;
+};
+
+OpenAjax.hub.IframeFIMContainer.prototype.sendToClient = function( topic, data, subscriptionID )
+{
+    smash._singletonManager.sendToClient( this._internalID, topic, data, [ subscriptionID ] );
+}
+
+OpenAjax.hub.IframeFIMContainer.prototype.remove = function()
+{
+    /**
+     * Cleans up data-strucrures for communication with the given client. Needs to be called prior to unloading of the
+     * client to prevent false positives about 'frame phishing' attacks.
+     * smash.prepareForUnload(clientName: string)
+     */
+    return smash._singletonManager.prepareForUnload( this._internalID );
+}
+
+OpenAjax.hub.IframeFIMContainer.prototype.isConnected = function()
+{
+    return smash._singletonManager.isConnected( this._internalID );
+}
+
+OpenAjax.hub.IframeFIMContainer.prototype.getPartnerOrigin = function()
+{
+    return smash._singletonManager.getPartnerOrigin( this._internalID );
+}
+
+OpenAjax.hub.IframeFIMContainer.prototype.getURI = function()
+{
+    /**
+     * Prepares for loading of a client in a separate iframe. In addition to setting up internal data-structures,
+     * it updates the URI (potentially adding a fragment identifier and URI parameters). 
+     * The updates are necessary to pass values needed to bootstrap communication.
+     *
+     * string smash.prepareForLoad({clientName: string, uri: string, 
+     *  [commErrorCallback:function(clientName:string, error:string)]})
+     * return value of null indicates failure, a non-null return value is the updated URI
+     */
+    var that = this;
+    function errorCallback( clientID, error ) {
+        var alertType = null;
+        switch( error ) {
+			case smash.SecurityErrors.INVALID_TOKEN:
+			case smash.SecurityErrors.TOKEN_VERIFICATION_FAILED:
+			    alertType = OpenAjax.hub.SecurityAlert.ForgedMsg;
+			    break;
+			case smash.SecurityErrors.TUNNEL_UNLOAD:
+			    alertType = OpenAjax.hub.SecurityAlert.FramePhish;
+			    break;
+			case smash.SecurityErrors.COMPONENT_LOAD:
+			    alertType = OpenAjax.hub.SecurityAlert.LoadTimeout;
+			    break;
+        }
+        try {
+            that._onSecurityAlert.call( that._scope, that._container, alertType );
+        } catch( e ) {
+            OpenAjax.hub._debugger();
+            that._log( "caught error from onSecurityAlert callback to constructor: " + e.message );
+        }
+    }
+    var newURI = smash._singletonManager.prepareForLoad({ clientName: this._internalID,
+            uri: this._clientURI, commErrorCallback: errorCallback,
+            oaaContainer: this, log: this._log });
+    
+    if ( newURI && OpenAjax.hub.enableDebug )  newURI += ":debug"; // REMOVE ON BUILD
+
+    return newURI;
+}
+
+//------------------------------------------------------------------------------
+
+OpenAjax.hub.IframeFIMHubClient = function( client, params )
+{
+    // XXX Since server redirection breaks hash communication (the server does
+    // not receive the fragment value, therefore the final URL does not contain
+    // this information), the initial message is transmitted as a URL param.
+    // The SMash code, though, expects messages after the hash.  So we copy
+    // the initial message value into the fragment.
+    var initialMsg = new RegExp( "[\\?&]oahm=([^&#]*)" ).exec( window.location.search );
+    if ( ! initialMsg ) {
+        throw new Error( OpenAjax.hub.Error.WrongProtocol );
+    }
+    initialMsg = initialMsg[1];
+
+    // check communications protocol ID
+    var partnerProtocolID = initialMsg.split( ":", 1 );
+    if ( partnerProtocolID[0] != smash._protocolID ) {
+        throw new Error( OpenAjax.hub.Error.WrongProtocol );
+    }
+    // remove protocol ID from initialMsg, since decodeMessage() doesn't
+    // expect it
+    initialMsg = initialMsg.substring( partnerProtocolID[0].length + 1 );
+    
+    // copy initial message into URL fragment
+    var url = window.location.href + "#" + initialMsg;
+	window.location.replace( url );
+	
+    
+    this._client = client;
+    this._onSecurityAlert = params.HubClient.onSecurityAlert;
+    this._scope = params.HubClient.scope || window;
+    
+    // pull out client id from initial message
+    var re = new RegExp( "\\d{3}.{" + smash._securityTokenLength + "}.{" + smash._securityTokenLength + "}\\d{3}(.*)" );
+    var payload = re.exec( initialMsg )[1];
+    var parts = payload.split(":");
+    var internalID = decodeURIComponent( parts[0] );
+    this._id = internalID.substring( internalID.indexOf("_") + 1 );
+    
+    if ( parts[2] && parts[2] == "debug" )  OpenAjax.hub.enableDebug = true; // REMOVE ON BUILD
+
+    if ( params.HubClient.log ) {
+        var id = this._id;
+        var scope = this._scope;
+        var logfunc = params.HubClient.log;
+        this._log = function( msg ) {
+            logfunc.call( scope, "IframeHubClient::" + id + ": " + msg );
+        };
+    } else {
+        this._log = function() {};
+    }
+    
+    this._connected = false;
+    this._subs = {};
+    this._subIndex = 0;
+    
+    // create and configure the pseudo-random number generator, used to create
+    // security tokens
+    smash._createPRNG( this, params );
+    
+    // configurable initialClientURI: only for those clients which perform URI redirection
+    // at client load time
+// XXX revert r231
+//    if (params.initialClientURI) {
+//        smash._initialClientURI = params.initialClientURI;
+//    }
+}
+
+ /*** OpenAjax.hub.HubClient interface implementation ***/
+
+OpenAjax.hub.IframeFIMHubClient.prototype.connect = function( onComplete, scope )
+{
+    if ( smash._singletonClientHub == null ) {
+        // allow a null clientName since the SMash provider can find it in the fragment.
+        smash._singletonClientHub = new smash.SEHubClient( null, this._log );
+        // set to be notified of security errors
+        var that = this;
+        smash._singletonClientHub.setSecurityErrorCallback( function( errorcode ) {
+            if ( errorcode != smash.SecurityErrors.INVALID_TOKEN ) {
+                that._log( "unknown smash security error: " + errorcode );
+            }
+            try {
+                that._onSecurityAlert.call( that._scope, that._client, OpenAjax.hub.SecurityAlert.ForgedMsg );
+            } catch( e ) {
+                OpenAjax.hub._debugger();
+                that._log( "caught error from onSecurityAlert callback to constructor: " + e.message );
+            }
+        });
+    }
+    
+    var that = this;
+    function cb( success, seHubClient ) {
+        if ( success ) {
+            that._connected = true;
+        }
+        if ( onComplete ) {
+            try {
+                onComplete.call( scope, that._client, success );    // XXX which error to return when success == false?
+            } catch( e ) {
+                OpenAjax.hub._debugger();
+                that._log( "caught error from onComplete callback to HubClient.connect(): " + e.message );
+            }
+        }
+    }
+    smash._singletonClientHub.connect( cb );
+}
+
+OpenAjax.hub.IframeFIMHubClient.prototype.disconnect = function( onComplete, scope )
+{
+    this._connected = false;
+    var that = this;
+    function cb( success, seHubClient ) {
+        // XXX what happens if success == false
+        if ( onComplete ) {
+            try {
+                onComplete.call( scope, that._client, success );    // XXX which error to return when success == false?
+            } catch( e ) {
+                OpenAjax.hub._debugger();
+                that._log( "caught error from onComplete callback to HubClient.disconnect(): " + e.message );
+            }
+        }
+    }
+    smash._singletonClientHub.disconnect( cb );
+}
+
+OpenAjax.hub.IframeFIMHubClient.prototype.getPartnerOrigin = function()
+{
+    return smash._singletonClientHub ? smash._singletonClientHub.getPartnerOrigin() : null;
+}
+
+OpenAjax.hub.IframeFIMHubClient.prototype.getClientID = function()
+{
+    return this._id;
+}
+
+ /*** OpenAjax.hub.Hub interface implementation ***/
+
+OpenAjax.hub.IframeFIMHubClient.prototype.subscribe = function( topic, onData, scope, onComplete, subscriberData )
+{
+    var subID = "" + this._subIndex++;
+
+    var that = this;
+    var completeCallback = ! onComplete ? null :
+            function ( success, subHandle, error ) {
+                try {
+                    onComplete.call( scope, subID, success, error );
+                } catch( e ) {
+                    OpenAjax.hub._debugger();
+                    that._log( "caught error from onComplete callback to HubClient.subscribe(): " + e.message );
+                }
+            };
+    function dataCallback( subHandle, topic, data ) {
+        try {
+            onData.call( scope, topic, data, subscriberData );
+        } catch( e ) {
+            OpenAjax.hub._debugger();
+            that._log( "caught error from onData callback to HubClient.subscribe(): " + e.message );
+        }
+    }
+    this._subs[ subID ] = smash._singletonClientHub.subscribe( topic, completeCallback, dataCallback, scope, subscriberData );
+    return subID;
+}
+
+OpenAjax.hub.IframeFIMHubClient.prototype.publish = function( topic, data )
+{
+    smash._singletonClientHub.publish( topic, data );
+}
+
+OpenAjax.hub.IframeFIMHubClient.prototype.unsubscribe = function( subID, onComplete, scope )
+{
+    if ( ! this._subs[ subID ] ) {
+        throw new Error( OpenAjax.hub.Error.NoSubscription );
+    }
+    var that = this;
+    function cb( success, subHandle ) {
+        delete that._subs[ subID ];
+        if ( onComplete ) {
+            try {
+                onComplete.call( scope, subID, success/*, error*/ );
+            } catch( e ) {
+                OpenAjax.hub._debugger();
+                that._log( "caught error from onComplete callback to HubClient.unsubscribe(): " + e.message );
+            }
+        }
+    };
+    this._subs[ subID ].unsubscribe( cb );
+}
+
+OpenAjax.hub.IframeFIMHubClient.prototype.isConnected = function()
+{
+    return this._connected;
+}
+
+OpenAjax.hub.IframeFIMHubClient.prototype.getScope = function()
+{
+    return this._scope;
+}
+
+OpenAjax.hub.IframeFIMHubClient.prototype.getSubscriberData = function( subID )
+{
+    var sub = this._subs[ subID ];
+    if ( sub ) {
+        return sub.getSubscriberData();
+    }
+    throw new Error( OpenAjax.hub.Error.NoSubscription );
+}
+
+OpenAjax.hub.IframeFIMHubClient.prototype.getSubscriberScope = function( subID )
+{
+    var sub = this._subs[ subID ];
+    if ( sub ) {
+        return sub.getSubscriberScope();
+    }
+    throw new Error( OpenAjax.hub.Error.NoSubscription );
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+if ( typeof OpenAjax._smash == 'undefined' ) { OpenAjax._smash = {}; }
+var smash = OpenAjax._smash;
+
+// Ideally, should use a closure for private (and public) data and functions,
+// but this was easier for the initial SMash refactoring.
+
+smash._singletonManager = undefined; // the singleton that implements all the manager-side SPI
+smash._singletonClientHub = undefined; // the singleton that implements all the client-side SPI
+
+smash._protocolID = "openajax-2.0";
+
+//smash._goodbyeMessage = undefined; // The goodbye message sent when unloading the mashup page. Protects against malicious unloading of the mashup application. If undefined, no message is displayed
+//smash._loadTimeout = 20000; // The default timeout time during loading of a component. The lower the value the higher the security against frame-phishing but also the higer the chance of false detections.
+// XXX revert r231
+//smash._initialClientURI = undefined; // For use by the smash provider loaded by a client. Should only be changed from the default value if the client does URI redirection at load time. Otherwise, we will assume that the current URI was also the initial URI
+
+// --- security token stuff ---
+// configurable pseudo random number generator (prng) to use for generating the security token. 
+// If not set, we use Math.random. 
+// If set, the provided random number generator must support a function nextRandomB64Str(strlength:integer)
+// that returns a string of length strlength, where each character is a "modified Base64 for URL" character.
+// This includes A-Z, a-z, and 0-9 for the first 62 digits, like standard Base64 encoding, but
+// no padding '='. And the '+', '/' characters of standard Base64 are replaced by '-', '_'.
+smash._prng = undefined; 
+smash._securityTokenLength = 6; // configurable security token length. If default value is not used, both manager and clients have to change it to the same value. 
+smash._securityTokenOverhead = null; // the number of characters in a serialized message consumed by the security tokens
+smash._computeOtherTokenConstants = function() {
+	smash._securityTokenOverhead = 2*smash._securityTokenLength;
+	smash._multiplier = Math.pow(10, smash._securityTokenLength-1);
+}
+smash._computeOtherTokenConstants();
+
+smash._createPRNG = function( container, params )
+{
+    if ( ! smash._prng ) {
+        // create pseudo-random number generator with a default seed
+        var seed = new Date().getTime() + Math.random() + document.cookie;
+        smash._prng = smash.crypto.newPRNG( seed );
+    }
+    
+    var p = params.IframeContainer || params.IframeHubClient;
+    if ( p && p.seed ) {
+        try {
+            var extraSeed = p.seed.call( container._scope );
+            smash._prng.addSeed( extraSeed );
+        } catch( e ) {
+            OpenAjax.hub._debugger();
+            container._log( "caught error from 'seed' callback: " + e.message );
+        }
+    }
+}
+
+/**
+ * Randomly generates the security token which will be used to ensure message integrity.
+ */
+smash._keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+smash._generateSecurityToken = function() {
+	var r;
+	if (smash._prng) 
+		r = smash._prng.nextRandomB64Str(smash._securityTokenLength);
+	else {
+		var r1 = Math.random(); // value in (0,1)
+		r = "";
+		// assuming one Math.random() value has enough bits for smash._securityTokenLenght
+		for (var i=0; i<smash._securityTokenLength; i++) {
+			var r2 = r1 * 64; // get the most significant base-64 value
+			var c = Math.floor(r2);
+			r1 = (r2 - c); // the remaining fractional value
+			r = r + smash._keyStr.charAt(c);
+		}
+	}
+	return r;
+}
+
+//------------------------- manager-side implementation ------------------------
+
+/** 
+ * lazy creation of the manager-side singleton
+ */
+smash._ensureSingletonManager = function() {
+	if (smash._singletonManager == null)
+		smash._singletonManager = new smash.SEHub();
+}
+
+/**
+ * Constructor.
+ * The name SEHub is legacy. The provider on the manager-side does not implement any of the hub functionality
+ * other than communication.
+ */
+smash.SEHub = function(){
+	// This is used to make the object available to the private methods. This is a workaround for an error in the ECMAScript Language Specification which causes this to be set incorrectly for inner functions. See http://www.crockford.com/javascript/private.html
+	var that=this;
+	// associative array indexed by componentId. Each element is a ComponentInfo object. 
+	// Component is synonymous with client. componentId is the same as clientName
+	this.componentInfo = [];
+	
+	/**
+	 * Constructor for ComponentInfo objects
+	 */
+	function ComponentInfo(uri, eCallback) {
+		this.uri = uri;
+//		this.state = smash.SEHubConstants.START;
+        this.connected = false;
+		this.errorCallback = eCallback;
+	}
+    
+    // create an ID that is unique within the page
+    this.generateUniqueClientName = function( clientName ) {
+        do {
+            clientName = ((0x7fff * Math.random()) | 0).toString(16) + "_" + clientName;
+        } while ( that.componentInfo[ clientName ] );
+        return clientName;
+    }
+	
+	// securityListener function registered for each component's security events
+	function securityListener(errorType, clientName) {
+//		var errorString = that.getSecurityErrorString(errorType); // get the error as a string
+		var ci = that.componentInfo[clientName];
+		if ( ci != null ) {
+			var errorCallback = ci.errorCallback; // the errorCallback registered by the application
+			if (errorCallback != null) { // if one was registered
+//				errorCallback(clientName, errorString);
+				errorCallback(clientName, errorType);
+			}
+		}
+	}
+
+
+	/** 
+	 * string prepareForLoad({clientName: string, uri: string, 
+	 *  [commErrorCallback:function(clientName:string, error:string)]})
+	 * return value of null indicates failure, a non-null return value is the updated URI
+	 */
+	this.prepareForLoad = function(params) {
+		var clientName = params.clientName; // componentId and clientName are the same thing in this code
+		var componentURI = params.uri;
+		if ((clientName == null) || (componentURI == null))
+			return null;
+		if (that.componentInfo[clientName] != null) {
+			return null;
+		}
+		that.componentInfo[clientName] = new ComponentInfo(componentURI, params.commErrorCallback);
+		that.componentInfo[clientName].seComm = new smash.SEComm(); //The SEComm library used for this component
+		that.componentInfo[clientName].seComm.setSecurityListener(securityListener);
+        that.componentInfo[clientName].oaaContainer = params.oaaContainer;
+        return that.componentInfo[clientName].seComm.prepareForLoad(clientName, componentURI, that, smash._loadTimeout, params.log);
+	}
+
+	/**
+	 * boolean prepareForUnload(clientName: string)
+	 */
+	this.prepareForUnload = function(clientName) {
+		if (!that.componentInfo[clientName]) {
+			// component does not exist.
+			return true;
+		}
+//		// change state. pretty useless, since going to delete anyway
+//		that.componentInfo[clientName].state = smash.SEHubConstants.UNLOADED;
+		that._disconnect( clientName );
+		that.componentInfo[clientName].seComm.prepareForUnload();
+		// remove the relevant objects
+		delete that.componentInfo[clientName];
+		return true;
+	}
+
+	/**
+	 * boolean isConnected(clientName:string)
+	 */
+	this.isConnected = function(clientName) {
+//		if ( that.componentInfo[clientName] && that.componentInfo[clientName].state == smash.SEHubConstants.LOADED )
+		if ( that.componentInfo[clientName] && that.componentInfo[clientName].connected ) {
+		    return true;
+	    }
+		return false;
+	}
+
+	/** 
+	 * sendToClient(clientName:string, topic: string, data:JSON|string, matchingSubs:array of string)
+	 */
+	this.sendToClient = function(clientName, topic, data, matchingSubs) {
+		// send to the component
+		if (that.isConnected(clientName)) {
+			var comms = that.componentInfo[clientName].seComm;
+			if (comms) {
+				comms.distribute(topic, matchingSubs, data);
+			}
+		}
+	}
+
+    /** Callback when component loaded */
+    this.componentLoaded = function(clientName, partnerURL) {
+        if (that.componentInfo[clientName]) {
+//            that.componentInfo[clientName].state = smash.SEHubConstants.LOADED;
+            that.componentInfo[clientName].connected = true;
+            that.componentInfo[clientName].partnerOrigin = new RegExp( "^([a-zA-Z]+://[^:/?#]+).*" ).exec( partnerURL )[1];
+            
+            var oaaContainer = that.componentInfo[ clientName ].oaaContainer;
+            oaaContainer._container.getIframe().style.visibility = "visible";
+            if ( oaaContainer._onConnect ) {
+                try {
+                    oaaContainer._onConnect.call( oaaContainer._scope, oaaContainer._container );
+                } catch( e ) {
+                    OpenAjax.hub._debugger();
+                    oaaContainer._log( "caught error from onConnect callback to constructor: " + e.message );
+                }
+            }
+        }
+    }
+
+    
+    /**
+     * A message received from a component
+     * @param componentId The component that sent the message
+     * @param topic 
+     * @param message The payload of the message (JSON|string)
+     */
+    this.publishInternal = function(componentId, topic, message) {
+        if (that.componentInfo[componentId]) {
+            // component exists
+            var oaaContainer = that.componentInfo[ componentId ].oaaContainer;
+            oaaContainer._hub.publishForClient( oaaContainer._container, topic, message );
+        }
+    }
+
+    /**
+     * A subscribe message received from a component
+     * @param componentId The component that sent the message
+     * @param subId The subscription id
+     * @param topic 
+     */
+    this.subscribeInternal = function(componentId, subId, topic) {
+        var oaaContainer = that.componentInfo[ componentId ].oaaContainer;
+        oaaContainer._subs[ subId ] = oaaContainer._hub.subscribeForClient( oaaContainer._container, topic, subId );
+    }
+
+    /**
+     * A unsubscribe message received from a component
+     * @param componentId The component that sent the message
+     * @param subId
+     * @returns true if unsubscribe was accepted else false
+     */
+    this.unsubscribeInternal = function(componentId, subId) {
+        try {
+            var oaaContainer = that.componentInfo[ componentId ].oaaContainer;
+            var handle = oaaContainer._subs[ subId ];
+            oaaContainer._hub.unsubscribeForClient( oaaContainer._container, handle );
+            return true;
+        } catch( e ) {}
+        return false;
+    }
+    
+    this.disconnect = function( componentId )
+    {
+        that._disconnect( componentId );
+
+        var oaaContainer = that.componentInfo[ componentId ].oaaContainer;
+        if ( oaaContainer._onDisconnect ) {
+            try {
+                oaaContainer._onDisconnect.call( oaaContainer._scope, oaaContainer._container );
+            } catch( e ) {
+                OpenAjax.hub._debugger();
+                oaaContainer._log( "caught error from onDisconnect callback to constructor: " + e.message );
+            }
+        }
+    }
+    
+    this._disconnect = function( componentId )
+    {
+        if ( that.componentInfo[ componentId ].connected ) {
+    	    that.componentInfo[ componentId ].connected = false;
+
+    	    // hide component iframe
+            var oaaContainer = that.componentInfo[ componentId ].oaaContainer;
+            oaaContainer._container.getIframe().style.visibility = "hidden";
+        
+            // unsubscribe from all subs
+            for ( var sub in oaaContainer._subs ) {
+                oaaContainer._hub.unsubscribeForClient( oaaContainer._container, oaaContainer._subs[ sub ] );
+            }
+            oaaContainer._subs = {};
+        }
+    }
+    
+    this.getPartnerOrigin = function( componentId )
+    {
+        if ( that.componentInfo[ componentId ]. connected ) {
+            return that.componentInfo[ componentId ].partnerOrigin;
+        }
+        return null;
+    }
+
+	/**
+	 * Converts a security error code into a readable error message.
+	 * @param error The error code.
+	 */
+//	this.getSecurityErrorString = function(error) {
+//		switch (error) {
+//			case smash.SecurityErrors.INVALID_TOKEN: return smash.SecurityErrors.INVALID_TOKEN_MSG;
+//			case smash.SecurityErrors.TOKEN_VERIFICATION_FAILED: return smash.SecurityErrors.TOKEN_VERIFICATION_FAILED_MSG;
+//			case smash.SecurityErrors.TUNNEL_UNLOAD: return smash.SecurityErrors.TUNNEL_UNLOAD_MSG;
+//			case smash.SecurityErrors.COMPONENT_LOAD: return smash.SecurityErrors.COMPONENT_LOAD_MSG;
+//			default: return "UNKNOWN";
+//		}
+//	}
+	
+	
+	/**
+	 * Sets the unload function which shows the goodbye message.
+	 */	
+//	window.onunload=function(){
+//		if (smash._goodbyeMessage != undefined)
+//			alert(smash._goodbyeMessage);
+//	}
+}
+
+//---------- client-side implementation ----------------------------------------
+
+/**
+ * SEHubClient implementation linking the SECommClient together with the component side logic.
+ */
+smash.SEHubClient = function( clientName, logfunc )
+{
+	//-------- interface implemented by connHandle in Hub 1.1. We use the SEHub instance itself
+	//-------- as the connHandle object for the "manager".
+
+	this.equals = function(anotherConn) { return that === anotherConn; }
+	this.isConnected = function() { return connected; }
+	this.getClientName = function() { return clientName; }
+	
+	this.connect = function( callback ) {
+	    connectCallback = function( success ) {
+	        if ( success ) {
+	            connected = true;
+	        }
+	        callback( success, that );
+	    };
+	    seCommClient.connect( connectCallback );
+	}
+	
+	this.disconnect = function(callback) {
+	    disconnectCallback = function( success ) {
+	        if ( success ) {
+    	        connected = false;
+    		    subHandles = [];    // delete all existing subscriptions
+            }
+            callback( success, that );		    
+	    };
+	    seCommClient.disconnect();
+		return;
+	}
+	
+	/**
+	 * connHandle.subscribe(topic:string, callback:function, eventCallback:function)
+	 * returns a subHandle object, or null if it fails immediately.
+	 */
+	this.subscribe = function(topic, callback, eventCallback, scope, subscriberData) {
+		// keep track of the callback so that the incomming message can be distributed correctly
+		var subId = (subCount + ''); // assign the subscription id - making it a string
+		subCount++;
+		subHandles[subId] = new SubHandle(subId, topic, callback, eventCallback, that, scope, subscriberData);
+		seCommClient.subscribe(subId, topic);
+		return subHandles[subId];
+	}
+	/**
+	 * connHandle.publish(topic:string, data:JSON|string)
+	 */
+	this.publish = function(topic, data) {
+		seCommClient.publish(topic,data);
+		return true;
+	}
+	function SubHandle(subId, topic, callback, eventCallback, sehubClient, scope, subscriberData) {
+		var _isSubscribed = false;
+		var _data = subscriberData;
+		var _scope = scope;
+		var that = this;
+		this.getTopic = function() {
+			return topic;
+		}
+		this.getConnHandle = function() {
+			return sehubClient;
+		}
+		this.equals = function(anotherSubHandle) {
+			if ((anotherSubHandle._getSubId != null) && (typeof anotherSubHandle._getSubId == "function")
+				&& (anotherSubHandle.getConnHandle != null) && (typeof anotherSubHandle.getConnHandle == "function")) {
+					if ((subId === anotherSubHandle._getSubId()) && (sehubClient === anotherSubHandle.getConnHandle()))
+						return true;
+				}
+			return false;
+		}
+		this.isSubscribed = function() {
+			return _isSubscribed;
+		}
+		this.unsubscribe = function(callback) {
+			return sehubClient._unsubscribe(that, callback);
+		}
+		this.getSubscriberData = function() {
+		    return _data;
+		}
+		this.getSubscriberScope = function() {
+		    return _scope;
+		}
+		this._getSubId = function() {
+			return subId;
+		}
+		this._setIsSubscribed = function(value) {
+			_isSubscribed = value;
+		}
+		this._getCallback = function() {
+			return callback;
+		}
+		this._getEventCallback = function() {
+			return eventCallback;
+		}
+	}
+	
+	this.getPartnerOrigin = function() {
+		if ( connected && seCommClient != null ) {
+			var ptu = seCommClient.getParsedTunnelUrl();
+			if ( ptu != null ) {
+			    return ptu.scheme + "://" + ptu.host;
+		    }
+		}
+		return null;
+	}
+	//-------- end of interface implemented by connHandle in Hub 1.1.
+
+	//------- addition public interfaces not part of Hub 1.1 -----
+	/**
+	 * Set a callback to find out about security errors.
+	 * Not part of the OpenAjax Hub 1.1 standard
+	 */
+	this.setSecurityErrorCallback = function(errorcallback) {
+		securityErrorCallback = errorcallback;
+	}
+//	this.getManagerDomain = function() { 
+//		if (seCommClient != null) {
+//			var ptu = seCommClient.getParsedTunnelUrl();
+//			if (ptu != null) return ptu.host;
+//		}
+//		return null;
+//	}
+	
+	//------- private stuff ------
+	/**
+	 * _unsubscribe(subHandle:object, callback:function)
+	 * returns a subHandle object, or null if it fails immediately.
+	 */
+	this._unsubscribe = function(subHandle, callback) {
+		var subId = subHandle._getSubId();
+        if ( ! subHandles[ subId ] ) {
+            throw new Error( OpenAjax.hub.Error.NoSubscription );
+        }
+		subHandles[subId] = undefined;
+		seCommClient.unsubscribe(subId);
+		// no async callback as no confirmation message from manager
+		if (callback != null) {
+			callback(true, subHandle); // function(success:boolean, subHandle:object).
+		}
+		return subHandle;
+	}
+	var securityErrorCallback = undefined; // securityErrorCallback registered by the application in this component/frame
+	// subscriptions: each subscription is assigned an integer id that is unique to this client
+	var subCount = 0;
+	// mapping the subscription ids to the SubHandles
+	var subHandles=[];
+	// SECommClient serving the communication between the SEHub and the SEHub client
+	var seCommClient=new smash.SECommClient( clientName, logfunc );
+//	var state = smash.SEHubConstants.LOADED; // initialize my state to LOADED.
+    var connected = false;
+	// This is used to make the object available to the private methods. This is a workaround for an error in the ECMAScript Language Specification which causes this to be set incorrectly for inner functions. See http://www.crockford.com/javascript/private.html
+	var that=this;
+	var connectCallback = null;
+	var disconnectCallback = null;
+
+	/**
+	 * Processes messages received by the SECommClient
+	 * @param message The actual message.
+	 */
+	function handleIncomingMessage(message)
+	{
+	    if ( ! connected && message.type != smash.SECommMessage.CONNECT_ACK ) {
+	        return;
+	    }
+	    
+		switch (message.type) {
+		case smash.SECommMessage.DISTRIBUTE:
+			if ((message.additionalHeader != null) && (message.additionalHeader.s != null)) {
+				var subs = message.additionalHeader.s;
+				for (var i=0; i < subs.length; i++) {
+					var subId = subs[i];
+					if ((subId != null) && (subHandles[subId] != null)) {
+						var eventCallback = subHandles[subId]._getEventCallback();
+						if (eventCallback != null)
+							eventCallback(subHandles[subId], message.topic, message.payload);
+					}
+				}
+			}
+			break;
+		case smash.SECommMessage.SUBSCRIBE_ACK:
+			if (message.additionalHeader != null) {
+				var subId = message.additionalHeader.subId;
+				var isOk =  message.additionalHeader.isOk;
+				var err = message.additionalHeader.err;
+				if ((subId != null) && (isOk != null)) {
+					if (subHandles[subId] != null) {
+						var callback = subHandles[subId]._getCallback();
+						if (isOk) {
+							subHandles[subId]._setIsSubscribed(true);
+							if (callback != null)
+								callback(true, subHandles[subId]);
+						}
+						else {
+							if (callback != null)
+								callback(false, subHandles[subId], err);
+							subHandles[subId] = undefined; // unsubscribe
+						}
+					}
+				}
+			}
+			// else ignore the message
+			break;
+		case smash.SECommMessage.CONNECT_ACK:
+		    connectCallback( true );
+		    break;
+		case smash.SECommMessage.DISCONNECT_ACK:
+		    disconnectCallback( true );
+		    break;
+		}
+	}
+	function securityListenerCallback(errorcode) {
+//		var errorString = getSecurityErrorString(errorcode);
+		if (securityErrorCallback != null) {
+//			securityErrorCallback(errorString);
+			securityErrorCallback(errorcode);
+		}
+		else {
+			throw new Error(errorString);
+		}
+	}
+//	function getSecurityErrorString(error) {
+//		switch (error) {
+//			case smash.SecurityErrors.INVALID_TOKEN: return smash.SecurityErrors.INVALID_TOKEN_MSG;
+//			default: return "UNKNOWN";
+//		}
+//	}
+    	
+	// Override the SECommClient's received method with our own implementation
+	seCommClient.handleIncomingMessage = handleIncomingMessage;
+	seCommClient.setSecurityListener( securityListenerCallback );
+}
+//-----------------------------------------------------------------------------------------------
+//smash.SEHubConstants = {
+//
+//	// Constants representing states of a component.
+//	// Component State Machine: START -> LOADED -> UNLOADED
+//
+//	START: 0,
+//	LOADED: 1,
+//	UNLOADED: 2
+//
+//};
+//-----------------------------------------------------------------------------------------------
+/**
+ * Constants representing the different types of attacks that can be detected and prevented by the library.
+ */
+smash.SecurityErrors = {
+
+
+	// This error occurs when the CommLib detects a message with a different security token than the one with wich it was initialized.
+	INVALID_TOKEN: 0,
+//	INVALID_TOKEN_MSG: "The sender of the received message could not be verified because the received security token was not correct.",
+	// This error occurs when the SEComm receives a different security token than the one that was sent by the SEComm during the loading of the component.
+	TOKEN_VERIFICATION_FAILED: 1,		
+//	TOKEN_VERIFICATION_FAILED_MSG: "The security token could not be verified. A different security token than the one that was sent during the loading of the component was received after loading.",
+	// Phishing error
+	TUNNEL_UNLOAD: 2,
+//	TUNNEL_UNLOAD_MSG: "The tunnel was unloaded without the component being unloaded by the mashup application. Frame-phishing may have occured after the component was loaded successfully.",
+	// Phishing error before successfull load
+	COMPONENT_LOAD: 3
+//	COMPONENT_LOAD_MSG: "A timeout occured before the communication channel between the component and the mashup application was set up correctly. Frame-phishing may have occured during the loading of the component."
+};
+//-----------------------------------------------------------------------------------------------
+/**
+ * The object implementing the message serializer and deserializer for use in SEComm.
+ * The topic and payload are typically under application control and may contain URI reserved characters.
+ * These will be percent-encoded and decoded, and the application has to deal with the composition issues
+ * if it is passing in data or topics that are already percent-encoded. 
+ */
+
+
+smash.SECommMessage = function(){
+	// The type of the message. A string
+	this.type=null;
+	// The topic of the message. A string
+	this.topic=null;
+	// The remaining header information. A JSON object
+	this.additionalHeader=null;
+	// The payload of the message. A string
+	this.payload=null;
+	// The name used in the name value pair transmission. one character for efficiency. only use a letter or number
+	var typeName="y";
+	var topicName="t";
+	var additionalHeaderName = "h"; // other header information that is not handled by typeName and topicName
+	var payloadName="p";
+
+	/**
+	 * Serializes the message into a string which can be transmitted over a communication channel.
+	 * URI-encodes the topic and payload and uses "=", "&" as separators. The communication channel
+	 * must not perform any URI-encoding as "=", "&" are not reserved for fragments. 
+	 * If using something other than fragment messaging at the communication channel, the serialization
+	 * may need to change.
+	 * @returns The serialized message.
+	 */
+	this.serialize=function(){
+		var returnValue = typeName + "=" + this.type;
+		if (this.topic != null) {
+			var topicString = encodeURIComponent(this.topic);
+			var topicSer = "&" + topicName + "=" + topicString;  
+			returnValue += topicSer;
+		}
+		if (this.additionalHeader != null) {
+			var headerString = encodeURIComponent(JSON.stringify(this.additionalHeader));
+			var headerSer = "&" + additionalHeaderName + "=" + headerString;  
+			returnValue += headerSer;
+		}
+		if (this.payload != null) {
+			var payloadString = encodeURIComponent(this.payload);
+			var payloadSer = "&" + payloadName + "=" + payloadString;  
+			returnValue += payloadSer;
+		}
+		return returnValue;
+	}
+	
+	/**
+	 * Deserializes a serialized message and initializes the objects parameters.
+	 */
+	this.deserialize=function(serializedMessage){
+		var messageParts = serializedMessage.split("&");
+		for(var i = 0; i < messageParts.length; i++){
+			var nameValue = messageParts[i].split("=");
+			switch(nameValue[0]){
+			case typeName:
+				this.type=nameValue[1];
+				break;
+			case topicName:
+				this.topic=decodeURIComponent(nameValue[1]);
+				break;
+			case additionalHeaderName:
+				var headerString = decodeURIComponent(nameValue[1]);
+				this.additionalHeader = JSON.parse(headerString);
+				break;
+			case payloadName:
+				this.payload=decodeURIComponent(nameValue[1]);
+				break;
+			}	
+		}
+	}	
+}
+
+// only use letters or numbers as characters
+
+// CONNECT message
+smash.SECommMessage.CONNECT="con";
+smash.SECommMessage.CONNECT_ACK="cac";
+// DISCONNECT message
+smash.SECommMessage.DISCONNECT="xcon";
+smash.SECommMessage.DISCONNECT_ACK="xac";
+// PUBLISH message: additionalHeader is {f:"S"} or {f:"J"} representing that the payload is a string or JSON, 
+// topic and payload are topic, payload of message
+smash.SECommMessage.PUBLISH="pub"; 
+// DISTRIBUTE message: additionalHeader is {f: string, s:[string, ...]} where f is defined as in the PUBLISH message, 
+// and s representing subIds that should receive this message; topic and payload are as in PUBLISH message 
+smash.SECommMessage.DISTRIBUTE="dis"; 
+// SUSCRIBE message: additionalHeader is {subId: string}, payload==null, topic is subscription topic
+smash.SECommMessage.SUBSCRIBE="sub"; 
+// UNSUBSCRIBE message: additionalHeader is {subId: string}, topic==null, payload==null
+smash.SECommMessage.UNSUBSCRIBE="uns";
+// SUBCRIBE_ACK message: additionalHeader is {subId: string, isOk: boolean, err: string}, topic==null, payload == null
+smash.SECommMessage.SUBSCRIBE_ACK="sac"; 
+
+smash.SECommMessage.ERROR="err"; // TBD
+
+
+//-----------------------------------------------------------------------------------------------
+/**
+ * Definitions of exceptions used by SECom
+ */
+smash.SECommErrors = {};
+smash.SECommErrors.tunnelNotSetError = new Error ("The tunnel URI was not set. Please set the tunnel URI.");
+//smash.SECommErrors.componentNotFoundError = new Error ("The component could not be identified. Please declare the component correctly.");
+//smash.SECommErrors.securityTokenNotVerifiedError = new Error (smash.SecurityErrors.TOKEN_VERIFICATION_FAILED_MSG);
+//smash.SECommErrors.tunnelUnloadError = new Error (smash.SecurityErrors.TUNNEL_UNLOAD_MSG);
+//smash.SECommErrors.componentLoadError = new Error (smash.SecurityErrors.COMPONENT_LOAD_MSG);
+
+/**
+ * Links the SEHub and the SEHubClient together over the communication implemented by CommLib bridge
+ *
+ * TODO: Check if the component loading allows valid HTML.
+ * TODO: Propagate the style of the enclosing tag into the iFrame
+ * TODO: Check if there is a better way than polling to see if the tunnel's commLib has been registered
+ */
+smash.SEComm = function(){
+	// The timer used to delay the phishing message. This makes sure that a page navigation does not cause phishing errors.
+	// Setting it to 1 ms is enough for it not to be triggered on regular page navigations.
+	var unloadTimer=1;
+	// Variable storing the identifier for the setInterval if processing a registrationTimer	
+	var registrationTimerProcess=null;
+	var loadTimeout = 0;
+	var reconnectTimerProcess = null;
+	// The URI of the component being manages by this SEComm.
+	var componentURI=null;
+	// The commLib of the tunnel
+	var commLib=null;
+	// Variable storing the identifier to clear when the setInterval is called
+	var commLibPoll=null;
+	// The HTML id of the component for which this is a SEComm
+	var componentID=null;
+	// A queue for outgoing messages. This queue is used when new send requests are done while we are still sending or receiving a message.
+	var queueOut=[];
+	// Variable storing the identifier for the setInterval if processing an output queue
+	var queueOutProcess=null;
+	// Variable storing a reference to the SEHub which is managing this SEComm
+	var seHUB=null;
+	// The iframe in which the component is loaded
+	var myIframe = null;
+	// The security token used for this component
+	var securityTokenParent=null;
+	// Variable storing the callback to the security listener function
+	var securityListener=null;
+	// This is used to make the object available to the private methods. This is a workaround for an error in the ECMAScript Language Specification which causes this to be set incorrectly for inner functions. See http://www.crockford.com/javascript/private.html
+	var that=this;		
+	// keeps track of the initialization
+	var initialized=false;
+	// logging function
+	var logfunc = null;
+
+	/**
+	 * Sets the callback for security errors.
+	 * 
+	 * @param The callback for security errors.
+	 */
+	this.setSecurityListener=function(callback){
+		securityListener=callback;
+	}
+
+    function insertURLParams( uri, params ) {
+        var parts = uri.split( "?" );
+        if ( parts.length > 1 ) {
+            return parts[0] + "?" + params + "&" + parts[1];
+        }
+        parts = uri.split( "#" );
+        if ( parts.length > 1 ) {
+            return parts[0] + "?" + params + parts[1];
+        }
+        return uri + "?" + params;
+    }
+    
+	/**
+	 * Prepares for loading a component into an iframe.
+	 * @returns The modified URI
+	 */
+	this.prepareForLoad=function(componentId, frameURI, seHub, loadtimeout, logFunc)
+	{
+	    logfunc = logFunc;
+		this.log( "Parent connecting to : " + componentId );
+		// Store the SEHub
+		seHUB=seHub;
+		// Store the component Id
+		componentID=componentId;
+		loadTimeout = loadtimeout;
+		// Check if the tunnel is set
+		if (smash.SEComm.tunnelURI==null)throw smash.SECommErrors.tunnelNotSetError;
+		// modify the URI
+		securityTokenParent=smash._generateSecurityToken();
+		// include the token twice since the child token value does not matter yet
+// XXX revert r231
+//		componentURI = insertURLParams( frameURI, "id=" + encodeURIComponent(componentId) );
+//		var modifiedURIWithFragment = componentURI + "#100" + securityTokenParent + securityTokenParent + "000" + encodeURIComponent(componentId) + ":" + encodeURIComponent(smash.SEComm.tunnelURI);
+        // Since a server redirect does not take into account the fragment value
+        // (it is not transmitted by the browser to the server), the initial
+        // message must be sent as a URL param.
+        componentURI = insertURLParams( frameURI, "oahm=" + smash._protocolID + ":100" + securityTokenParent + securityTokenParent + "000" + encodeURIComponent(componentId) + ":" + encodeURIComponent(smash.SEComm.tunnelURI) );
+		// Make the instance available for the tunnel.
+		smash.SEComm.instances[componentId]=that;	
+		// Set a timer which detects if the component loaded successfully
+		// We are using an interval not to lose our evaluation context.
+		registrationTimerProcess=setInterval(pollForIncomingCommLibTimeout,loadTimeout);
+
+		return componentURI;
+	}
+
+	function pollForIncomingCommLibTimeout(){
+		clearInterval(registrationTimerProcess);
+		registrationTimerProcess = null;
+		//No CommLib has been registered.
+		if ( ! commLib ) {
+		     that.handleSecurityError( smash.SecurityErrors.COMPONENT_LOAD );
+		}
+	}
+	
+	function reconnectTimeout() {
+		clearInterval( reconnectTimerProcess );
+		that.handleSecurityError( smash.SecurityErrors.COMPONENT_LOAD );
+	}
+
+	/**
+	 * Gets the scope. Should only be used by the tunnel during INIT. 
+	 * @returns scope (object) the scope in which the callback needs to be called.
+	 **/
+	this.getScope=function(){
+		return this;
+	}
+
+	/**
+	 * Gets the callback. Should only be used by the tunnel during INIT. 
+	 * @param c (string) the name of the callback method	 
+	 **/
+	this.getCallback=function(){
+		return "messageReceived";
+	}
+
+	
+	/**
+	 * Called when the initialisaiton of the library is done and processes all messages in the queue
+	 */
+	this.initializationFinished=function(tunnelCommLib, token, currentClientURI, initialClientURI, tunnelWindow)
+	{
+		this.log( "Tunnel commLib initialization finished. Processing outgoing queue. Security token: " + token );
+// XXX revert r231
+//		// verify the security token and currentClientURI
+//		if ((securityTokenParent!=token) || (initialClientURI!=componentURI)) {
+        // verify the security token
+        if (securityTokenParent!=token) {
+			that.handleSecurityError(smash.SecurityErrors.TOKEN_VERIFICATION_FAILED);
+			return false;
+		}
+		else {
+			commLib=tunnelCommLib;		
+			initialized=true;
+			this.log( "Token verified." );
+			// register the onunload handler
+			tunnelWindow.onunload=tunnelUnloadHandler;
+			// switch the state to loaded in the seHUB. 
+			seHUB.componentLoaded(componentID, currentClientURI);
+			// process the current outgoing queue.
+			while (queueOut.length>0)commLib.send(queueOut.shift());
+			return true;
+		}
+	}
+	
+	this.prepareForUnload = function() {
+		// stop all timers
+		if (registrationTimerProcess != null) {
+			clearInterval(registrationTimerProcess);
+			registrationTimerProcess = null;
+		}
+	}
+	
+	function securityListenerClosure(error, componentId) {
+		return function() {
+			securityListener(error, componentId);
+		}
+	}
+
+	this.handleSecurityError = function( error ) {
+	    // if we have a timeout error, then overwrite initializationFinished()
+	    // to return false by default, in order to prevent client connection
+	    if ( error == smash.SecurityErrors.COMPONENT_LOAD ) {
+	        this.initializationFinished = function() {
+	            return false;
+	        }
+	    }
+	    
+		if (securityListener==null){
+			throw new Error (error);							
+		}
+		else{
+			securityListener(error,componentID);
+		}
+		return;
+	}
+
+	/** 
+	 * 
+	 */
+	function tunnelUnloadHandler(){		
+		if (securityListener==null){
+			setTimeout("throw tunnelUnloadError;", unloadTimer);
+		}
+		else{
+			setTimeout(securityListenerClosure(smash.SecurityErrors.TUNNEL_UNLOAD, componentID), unloadTimer);
+		}						
+	}
+	
+	/**
+	 * Function processing the incomming data from commLib
+	 *
+	 * @param message The message containing the incomming data
+	 */
+	this.messageReceived=function (message){
+		var msg=new smash.SECommMessage();
+		msg.deserialize(message);
+		switch(msg.type){
+		case smash.SECommMessage.PUBLISH:
+			if (msg.additionalHeader != null) {
+				var payload = msg.payload;
+				if (msg.additionalHeader.f == "J")
+					payload = JSON.parse(msg.payload);
+				seHUB.publishInternal(componentID, msg.topic, payload);
+			} // else no additionalHeader defining the payload format. hence ignore the message
+			break;
+		case smash.SECommMessage.SUBSCRIBE:
+			if (msg.additionalHeader != null)  {
+			    var isOk = true;
+			    var errMsg = "";
+			    try {
+				    seHUB.subscribeInternal(componentID, msg.additionalHeader.subId, msg.topic);
+			    } catch( e ) {
+			        isOk = false;
+			        errMsg = e.message;
+			    }
+				var msgack = new smash.SECommMessage();
+				msgack.type = smash.SECommMessage.SUBSCRIBE_ACK;
+				msgack.additionalHeader={subId: msg.additionalHeader.subId, isOk: isOk, err: errMsg};
+				send(msgack.serialize());
+			}
+			break;
+		case smash.SECommMessage.UNSUBSCRIBE:
+			if (msg.additionalHeader != null)
+				seHUB.unsubscribeInternal(componentID, msg.additionalHeader.subId);
+			break;
+		case smash.SECommMessage.CONNECT:
+		    clearInterval( reconnectTimerProcess );
+		    // switch the state to loaded in the seHUB. 
+			seHUB.componentLoaded( componentID, msg.payload );
+		    // send acknowledgement
+		    var msg = new smash.SECommMessage();
+		    msg.type = smash.SECommMessage.CONNECT_ACK;
+		    send( msg.serialize() );
+			break;
+		case smash.SECommMessage.DISCONNECT:
+		    seHUB.disconnect( componentID );
+		    // Set a timer which detects if the component reloaded
+    		// We are using an interval not to lose our evaluation context.
+    		reconnectTimerProcess = setInterval( reconnectTimeout, loadTimeout );
+		    // send acknowledgement
+		    var msg = new smash.SECommMessage();
+		    msg.type = smash.SECommMessage.DISCONNECT_ACK;
+		    send( msg.serialize() );
+		    break;
+		}
+	}
+	/**
+	 * Sends a published message to the partner component
+	 */
+	this.distribute=function(topic, matchingSubs, payload){
+		var msg=new smash.SECommMessage();
+		msg.type=smash.SECommMessage.DISTRIBUTE;
+		msg.topic=topic;
+		msg.additionalHeader = {s: matchingSubs};
+		if ((typeof payload) == "string") {
+			msg.additionalHeader.f = "S";
+			msg.payload=payload;
+		}
+		else {
+			msg.additionalHeader.f = "J";
+			msg.payload = JSON.stringify(payload);
+		}	
+		send(msg.serialize());
+	}
+
+	function send(message) {
+		// Queue the message if sending or if there is no communication partner yet
+		if (initialized==false){
+			queueOut.push(message);
+		}
+		else{
+			commLib.send(message);
+		}
+	}
+	
+	this.log = function( msg )
+	{
+	    logfunc( msg );
+	}
+}
+
+// Static array which contains the list of the currently loaded instances. The array is indexed by the url of the child component. 
+smash.SEComm.instances=[];
+
+//-----------------------------------------------------------------------------------------------
+
+/**
+ * SEHubClient implementation linking the SEComm together with the component side logic.
+ */
+smash.SECommClient = function( clientName, logfunc )
+{
+	// Storing the CommLib used for communicating
+	var controllers=[];
+	controllers["child"]=this;
+	var commLib=new smash.CommLib(true, controllers, clientName);
+	// This is used to make the object available to the private methods. This is a workaround for an error in the ECMAScript Language Specification which causes this to be set incorrectly for inner functions. See http://www.crockford.com/javascript/private.html
+	var that=this;
+	// A queue for outgoing messages. This queue is used when new send requests are done while we are still sending or receiving a message.
+	var queueOut=[];
+	// keeps track of the initialization
+	var initialized=false;
+	var securityListener=null;
+	var jsonPayloadHeader = {f: "J"};
+	var stringPayloadHeader = {f: "S"};
+	var parsedTunnelUrl = null;	
+	/**
+	 * Publishes a message to a certain topic
+	 * @param topic string
+	 * @param data JSON|string
+	 */
+	this.publish=function(topic, data){
+		var msg=new smash.SECommMessage();
+		msg.type=smash.SECommMessage.PUBLISH;
+		msg.topic=topic;
+		if ((typeof data) == "string") {
+			msg.additionalHeader = stringPayloadHeader;
+			msg.payload=data;
+		}
+		else {
+			msg.additionalHeader = jsonPayloadHeader;
+			msg.payload = JSON.stringify(data);
+		}	
+		send(msg.serialize());
+	}
+
+	/**
+	 * subscribes to a certain topic
+	 */
+	this.subscribe=function(subId, topic){
+		var msg=new smash.SECommMessage();
+		msg.type=smash.SECommMessage.SUBSCRIBE;
+		msg.topic=topic;
+		msg.additionalHeader = {subId: subId};
+		send(msg.serialize());
+	}
+	
+	this.connect = function( callback ) {
+        if ( initialized ) {
+            var msg = new smash.SECommMessage();
+            msg.type = smash.SECommMessage.CONNECT;
+            msg.payload = window.location.href.split("#")[0];
+            send( msg.serialize() );
+            return;
+        }
+        connectCallback = callback;
+	}
+	
+	this.disconnect = function() {
+	    var msg = new smash.SECommMessage();
+	    msg.type = smash.SECommMessage.DISCONNECT;
+	    send( msg.serialize() );
+	}
+	
+	/**
+	 * Called when the initialisaiton of the library is done and processes all messages in the queue
+	 */
+	this.initializationFinished=function(tunnelUrl)
+	{
+		this.log( "Initialization finished. Processing outgoing queue." );
+		parsedTunnelUrl = new ParsedUrl(tunnelUrl);
+
+		initialized=true;
+		connectCallback( true );
+		while (queueOut.length>0)commLib.send(queueOut.shift());
+	}
+	this.getParsedTunnelUrl=function() { return parsedTunnelUrl; }
+
+	var _regex = new RegExp("^((http|https):)?(//([^/?#:]*))?(:([0-9]*))?([^?#]*)(\\?([^#]*))?");
+	function ParsedUrl(url) {
+		var matchedurl = url.match(_regex);
+		this.scheme = (matchedurl[2] == "") ? null : matchedurl[2];
+		this.host = (matchedurl[4] == "") ? null : matchedurl[4];
+		this.port = (matchedurl[6] == "") ? null : matchedurl[6];
+		this.path = (matchedurl[7] == "") ? null : matchedurl[7];
+		this.query = (matchedurl[8] == "") ? null : matchedurl[8];
+	}
+
+	/**
+	 * unsubscribes
+	 */
+	this.unsubscribe=function(subId){
+		var msg=new smash.SECommMessage();
+		msg.type=smash.SECommMessage.UNSUBSCRIBE;
+		msg.additionalHeader={subId: subId};
+		send(msg.serialize());
+	}
+	
+	function send(message) {
+		// Queue the message if sending or if there is no communication partner yet
+		if (initialized==false){
+			queueOut.push(message);
+		}
+		else{
+			commLib.send(message);
+		}
+	}
+
+
+	/**
+	 * Function processing the incomming data from commLib
+	 *
+	 * @param message The message containing the incomming data
+	 */
+	this.messageReceived=function (message){
+		var msg=new smash.SECommMessage();
+		msg.deserialize(message);
+		// parse the JSON payload
+		if (msg.type == smash.SECommMessage.DISTRIBUTE) {
+			var header = msg.additionalHeader;
+			if ((header != null) && (header.f == "J"))
+				msg.payload = JSON.parse(msg.payload);
+		} 
+// For now, pass all messages to handleIncomingMessage()		
+//		if ((msg.type == smash.SECommMessage.DISTRIBUTE) || (msg.type == smash.SECommMessage.SUBSCRIBE_ACK))
+			that.handleIncomingMessage(msg);
+	}
+
+	
+	this.handleSecurityError=function (error){
+		if (securityListener==null){
+			throw new Error (error);							
+		}
+		else{
+			securityListener( error, clientName );
+		}
+		return;
+	}
+
+
+	/**
+	 * Sets the callback for security errors.
+	 * 
+	 * @param The callback for security errors.
+	 */
+	this.setSecurityListener=function(callback){
+		securityListener=callback;
+	}
+
+	/**
+	 * This method is the location for the callback to the SECommClient library.
+	 * The application using this library overrides this method with its own implementation.
+	 * HACK: this is terrible from a layering perspective. Ideally all message formatting details, such
+	 * as header formats should be handled at this layer alone.
+	 * The default behavior is to alert a message.
+	 *
+	 * @param message The actual message.
+	 */
+	this.handleIncomingMessage=function(message){
+		alert("SECommClient\n\nTopic: " + message.topic + "\n\nPayload: " + message.payload);
+	}
+	
+	this.log = function( msg ) {
+	    logfunc( msg );
+	}
+}
+
+/**
+ * Provides the low level communication layer.
+ * @param child (boolean) indicating if this is a child iframe or not.  
+ * @param controllers (object []) an array indexed by the clientName of objects implementing the controller interface.
+ * @param clientName - only explicitly passed for the child iframe
+ * 
+ * controller.messageReceived - called when the commlib recieves an incomming message.
+ * controller.initializationFinished - called when the commlib finished its initialzation.
+ * controller.handleSecurityError - called when a security error occurs.
+ * 
+ */
+smash.CommLib=function(child, controllers, clientName){
+    /**BEGIN of communcation protocol **/       
+    /*
+      Message format:
+     | Message Type | Message Sequence Number | Security Token Parent | Security Token Child | ACK          | ACK Message Sequence Number   | Payload         |
+     | 1 character  | 2 characters            |  x characters         | x characters         | 1 character  | 2 characters                  | varable length  | 
+    */
+	// Init message payload=communication partner url
+	var INIT="1";		
+	// An ack message without any payload. The reciever is not supposed to ack this message therefore the message sequence number will be 00.
+	var ACK="2";		
+	// The part message indicates that this is a message that needed to be split up. It will contain the payload of a part of the total message.
+	var PART="3";
+	// The end message indicates that this is the last part of a split up message. The full message has arrived after processing this message.
+	var END="4";		
+	
+	/** END of communcation protocol **/
+	// This is used to make the object available to the private methods. This is a workaround for an error in the ECMAScript Language Specification which causes this to be set incorrectly for inner functions. See http://www.crockford.com/javascript/private.html
+	var that=this;		
+	// polling and queue processing interval
+	var interval=100;
+	// The maximul length of a URL. If the message is longer it will be split into different parts.
+	var urlLimit = 4000;
+	// Protocol overhead excluding security token overhead
+	var protocolOverhead=6;
+	// Need to do an acknowledgement
+	var ack=0;
+	// Raw incoming data
+	var currentHash=null;
+	// The newly decoded incoming message
+	var messageIn=null;
+	// The last decoded incoming message
+	var previousIn=null;
+	// The currently transmitted message
+	var messageOut=null;
+	// The previously transmitted message
+	var previousOut=null;		
+	// The url of the  partner
+	var partnerURL=null;
+	// The window object of the partner
+	var partnerWindow=null;
+	// A queue for outgoing messages. This queue is used when new send requests are done while we are still sending or recieving a message.
+	var queueOut=[];
+	// Storing the last sent message number
+	var msn=00;
+	// Buffer for storing the incoming message parts
+	var messageBuffer="";
+	// Variable storing the timerId of the message timer.
+	var timerId=null;
+	// Two security tokens - One created by the parent frame (the manager) and one by the child frame (the client)
+	var securityTokenParent=null;
+	var securityTokenChild=null;
+	// 
+	var controller = null;
+	var logQ = [];
+	
+	/**
+	 * Sends a message to the communication partner
+	 * @param message (string) the message that needs to be delivered to the communication partner
+	 */
+	this.send=function(message){
+		// check if we are properly initialized
+		if (partnerURL==null){
+			log( "Trying to send without proper initialization. Message will be discarded. " +  message );
+			return;
+		}
+		log( "Sending: " + message );
+		// URL encode the message
+		// var encodedMessage=encodeURIComponent(message);
+		var encodedMessage=message;
+		// determine the payload size
+		var payloadLength=urlLimit-protocolOverhead-smash._securityTokenOverhead-partnerURL.length;
+		// DEBUG LARGE MESSAGES 
+		//if(oah_ifr_debug)payloadLength=1;
+		// Split up into separate messages if necessary
+		var currentMessage=encodedMessage;
+		while (currentMessage.length>0){
+			// split up and put in output queue
+			var part=currentMessage.substr(0,payloadLength);
+			currentMessage=currentMessage.substr(payloadLength);
+			if (currentMessage==0){
+				queueOut.push({type: END, payload: part});
+			}
+			else{
+				queueOut.push({type: PART, payload: part});
+			}
+		}
+	}
+	
+	/**
+	 * The timer triggering the flow of messages through the system.
+	 */
+	function messageTimer(){
+		// check if there is a new message
+		if(checkMessage()){
+			// check if it can be decoded properly
+			if (decodeMessage()){
+				// check if it is conform the security requirements
+				if (checkSecurity()){
+					// process it
+					processMessage();
+				}					
+			}				
+		}
+		// Only sent if an ack was received for the last transmitted message.
+		if (checkAck()){
+			// send anything that might be in the out queue
+			sendMessage();
+		}
+	}
+	
+	/**
+	 * Returns true if the previously transmitted message was acknowledged.
+	 * 
+	 * Possible exception situations to take into account: 
+	 * - One of the parties takes two turns in a row.
+	 *   p   p   c   
+	 * c p1  - 
+	 * p         p1'
+	 * 
+	 *   c   p   p   c
+	 * c     ac1 p1  
+	 * p c1          p1'
+ 	 * 
+	 */
+	function checkAck(){
+		// No ack is expected for an ack.
+		if (previousOut.type==ACK)return true;
+		// Ack is received. 
+		if ((previousOut.msn==messageIn.ackMsn) && (messageIn.ack==1)) return true;
+		// Wait for the ack to arrive.
+		log( "Waiting for ACK : " + previousOut.msn );
+		return false;
+	}
+	
+	/**
+	 * Helper method providing a new  message sequence number
+	 * @returns (string) the new sequence number
+	 */
+	function getNewMsn(){
+		msn++;
+		if (msn==100) msn=0;
+		if (msn<10) return "0" + msn;
+		return "" + msn;			
+	}
+	
+	/**
+	 * Checks the information after the hash to see if there is a new incomming message.
+	 */
+	function checkMessage(){
+		//Can't use location.hash because at least Firefox does a decodeURIComponent on it.
+		var urlParts = window.location.href.split("#");
+		if(urlParts.length == 2){
+			var newHash = urlParts[1];
+			if(newHash!="" && newHash != currentHash){
+				currentHash = newHash;
+				return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Decodes an incomming message and checks to see if it is syntactially valid.
+	 */		
+	function decodeMessage() {
+// new RegExp( "(\\d)(\\d{2})(.{" + smash._securityTokenLength + "})(.{" + smash._securityTokenLength + "})(\\d)(\\d{2})(.*)" )
+		var type=currentHash.substr(0,1);
+		var msn=currentHash.substr(1,2);
+		var nextStart = 3;
+		var tokenParent=currentHash.substr(nextStart,smash._securityTokenLength);
+		nextStart += smash._securityTokenLength;
+		var tokenChild=currentHash.substr(nextStart,smash._securityTokenLength);
+		nextStart += smash._securityTokenLength;
+		var ack=currentHash.substr(nextStart,1);
+		nextStart += 1;
+		var ackMsn=currentHash.substr(nextStart,2);
+		nextStart += 2;
+		// The payload needs to stay raw since the uri decoding needs to happen on the concatenated data in case of a large message
+		var payload=currentHash.substr(nextStart);
+		log( "In : Type: " + type + " msn: " + msn + " tokenParent: " + tokenParent + " tokenChild: " + tokenChild + " ack: " + ack + " msn: " + ackMsn + " payload: " + payload );
+		messageIn={type: type, msn: msn, tokenParent: tokenParent, tokenChild: tokenChild, ack: ack, ackMsn: ackMsn, payload: payload};
+		return true;
+	}
+
+	/**
+	 * Check if there have been any security breaches in the message.
+	 */				
+	function checkSecurity(){			
+		// Check the security tokens
+		if (messageIn.type!=INIT && (messageIn.tokenParent!=securityTokenParent || messageIn.tokenChild!=securityTokenChild)){
+			log( "Security token error: Invalid security token received. The message will be discarded." );
+			handleSecurityError(smash.SecurityErrors.INVALID_TOKEN);
+			return false;
+		}		
+		// Attacks should never pass the security check. Code below is to debug the implementation.
+//		if(oah_ifr_debug){
+//			if (messageIn.type!=INIT && messageIn.type!=ACK && messageIn.type!=PART && messageIn.type!=END){
+//				if(oah_ifr_debug)debug("Syntax error: Message Type. The message will be discarded.");
+//				return false;
+//			}
+//			if (!(messageIn.msn>=0 && messageIn.msn<=99)){
+//				if(oah_ifr_debug)debug("Syntax error: Message Sequence Number. The message will be discarded.");
+//				return false;
+//			}
+//			if (!(messageIn.ack==0 || messageIn.ack==1)){
+//				if(oah_ifr_debug)debug("Syntax error: ACK. The message will be discarded.");
+//				return false;
+//			}
+//			if (!(messageIn.ackMsn>=0 && messageIn.ackMsn<=99)){
+//				if(oah_ifr_debug)debug("Syntax error: ACK Message Sequence Number. The message will be discarded.");
+//				return false;
+//			}
+//		}
+		return true;
+	}
+
+	/**
+	 * Process the incoming message.
+	 */						
+	function processMessage(){
+		ack=1;
+		// The child is initialized as soon as there is an ack for the init message sent by the child.
+		if (messageIn.type!=INIT && child && previousOut.type==INIT && messageIn.ack=="1" && previousOut.msn==messageIn.ackMsn) {
+		    controller.initializationFinished(partnerURL);
+	    }
+							
+		// Call the actual processing functions
+		switch(messageIn.type){
+			case INIT:
+				processInit();
+				break;
+			case ACK:
+				processAck();
+				break;
+			case PART:
+				processPart();
+				break;
+			case END:
+				processEnd();
+				break;					
+		}
+		// Set the processed message as the previousIn message
+		previousIn=messageIn;		
+	}
+
+	/**
+	 * Implementation of the INIT message type
+	**/
+	function processInit(){
+		var parts = messageIn.payload.split(":");
+		var cname = decodeURIComponent(parts[0]);
+		partnerURL=decodeURIComponent(parts[1]);
+		securityTokenParent=messageIn.tokenParent;
+		securityTokenChild=messageIn.tokenChild;
+		// Initialize a component
+		if (child){
+			if (clientName != null) cname = clientName; // override what is read from the URL
+			// generate a real security token for the child
+			securityTokenChild = smash._generateSecurityToken();
+			// GUI which will be used to name the iFrame tunnel.
+			var tunnelGUID="3827816c-f3b1-11db-8314-0800200c9a66";
+			// Generate the hidden iframe for communicating
+			var iframe = document.createElement("iframe");
+			var currentClientURI = encodeURIComponent(window.location.href.split("#")[0]);
+			var initialClientURI = currentClientURI;
+//			if (smash._initialClientURI) {
+//				initialClientURI = encodeURIComponent(smash._initialClientURI);
+//			}
+			var initpayload = encodeURIComponent(cname) + ":" + currentClientURI + ":" + initialClientURI;
+
+			// sending an ack for msn "00" to the tunnel, since have processed the INIT message,
+			// and so that the INIT message the component is sending to the tunnel will result
+			// in an ack to be sent back.
+            // XXX Since server redirection breaks hash communication (the server does
+            //  not receive the fragment value, therefore the final URL does not contain
+            //  this information), the initial message is transmitted as a URL param.
+			partnerURL += (partnerURL.indexOf("?") != -1 ? "&" : "?") + "oahm=100" + securityTokenParent + securityTokenChild + "100" + initpayload;
+			iframe.src = partnerURL;
+			iframe.name=tunnelGUID;
+			iframe.id=tunnelGUID;
+			document.body.appendChild(iframe);
+			iframe.style.position = "absolute";
+			iframe.style.left = iframe.style.top = "-10px";
+			iframe.style.height = iframe.style.width = "1px";
+			iframe.style.visibility = "hidden";
+			// We do not send an ack directly to the parent frame since it is impossible to directly communicate with it in IE7
+			// The ack is done indirectly when the registerTunnelCommLib is done
+			ack=0;
+			// set up the partner window
+			partnerWindow=window.frames[tunnelGUID];
+			// store the last sent message - will be used to detect intialization and for detecting security breaches
+			previousOut={type: INIT, msn: "00", tokenParent: securityTokenParent, tokenChild: securityTokenChild, ack: "0", ackMsn: "00", payload: initpayload}; // only using type and msn of previousOut. presumably the rest is for FDK's retransmit stuff? should get rid of this complexity
+			// set the controller for this component
+			controller=controllers["child"];
+		}
+		// Initialize a tunnel
+		else{
+			var initialClientURI = decodeURIComponent(parts[2]);
+			// set up the partner window
+			partnerWindow=window.parent;
+			// set the controller for this component
+			controller=controllers[cname];
+			var success = controller.initializationFinished(that, securityTokenParent, partnerURL, initialClientURI, window);
+			if (!success) ack = 0; // don't send an ack signalling the completion of connection setup.
+			// store the last sent message - will be used to detect intialization and for detecting security breaches
+			previousOut={type: INIT, msn: "00", tokenParent: securityTokenParent, tokenChild: securityTokenChild, ack: "0", ackMsn: "00", payload: (encodeURIComponent(cname) + ":" + encodeURIComponent(window.location.href.split("#")[0]))}; // only using type and msn of previousOut. presumably the rest is for FDK's retransmit stuff? should get rid of this complexity				
+		}
+		if (partnerWindow==null) {
+			log( "Init failed." );
+		}
+	}	
+			
+	/**
+	 * Implementation of the ACK message type
+	**/
+	function processAck(){
+		// do not ack an ack
+		ack=0;
+	}
+
+	/**
+	 * Implementation of the PART message type
+	**/
+	function processPart(){
+		// Process message
+		messageBuffer+=messageIn.payload;
+	}		
+	
+	/**
+	 * Implementation the END message type
+	**/
+	function processEnd(){
+		// Process message
+		messageBuffer+=messageIn.payload;
+		// messageBuffer=decodeURIComponent(messageBuffer);
+		log( "Received: " + messageBuffer );
+		controller.messageReceived(messageBuffer);
+		messageBuffer="";
+	}
+	
+	/**
+	 * Send a reply to the incoming message.
+	 */								
+	function sendMessage(){						
+		// If there is nothing in the queue and an ack needs to be sent put the ack on the queue;
+		if (queueOut.length==0 && ack==1){
+			// The correct values will be filled in later. Just push a clean ack message
+			queueOut.push({type: ACK, payload: ""});
+		}
+		// Process the output queue
+		if (queueOut.length!=0){
+			messageOut=queueOut.shift();
+			// Fill in the security token
+			messageOut.tokenParent=securityTokenParent;
+			messageOut.tokenChild=securityTokenChild;
+			// Get a new sequence number
+			messageOut.msn=getNewMsn();
+			// Fill in the right ack values 
+			// The protocol keeps acking the last received message to ensure that there are no 
+			// problems with overwriting a pure ack message. Which could happen because there is 
+			// no waiting for an ack of an ack.			
+			messageOut.ack="1";
+			messageOut.ackMsn=previousIn.msn;
+			// turn of the ack
+			ack=0;			
+			writeToPartnerWindow();
+		}
+	}				
+	
+	/**
+	 * Writes the message to the partner window's fragment id
+	**/		
+	function writeToPartnerWindow(){			
+		var url = partnerURL + "#" + messageOut.type + messageOut.msn + messageOut.tokenParent + messageOut.tokenChild + messageOut.ack + messageOut.ackMsn + messageOut.payload;
+		partnerWindow.location.replace(url);
+		previousOut=messageOut;
+		log( "Out: Type: " + messageOut.type + " msn: " + messageOut.msn + " tokenParent: " + messageOut.tokenParent + " tokenChild: " + messageOut.tokenChild + " ack: " + messageOut.ack + " msn: " + messageOut.ackMsn + " payload: " + messageOut.payload );
+	}		
+	
+	/**
+	 * Default handler of the security listener. If a security error occurs, the CommLib is switched off. And communication is no longer possible.
+	 * 
+	 */
+	function handleSecurityError(error){
+		// Stop the communication
+		clearInterval(timerId);	
+		// If there	is a securityListener inform the controller of what happened.
+		controller.handleSecurityError(error);
+	}
+	
+	function log( msg )
+	{
+	    if ( controller ) {
+	        while ( logQ.length > 0 ) {
+	            controller.log( logQ.shift() );
+	        }
+	        controller.log( msg );
+	    } else {
+	        logQ.push( msg );
+	    }
+	}
+		
+	// Start listening for incoming messages
+	timerId=setInterval(messageTimer, interval);
+};
+
+})(); // end closure
diff --git a/UNGProject/openajaxhub/src/containers/iframe/crypto.js b/UNGProject/openajaxhub/src/containers/iframe/crypto.js
new file mode 100644
index 0000000000000000000000000000000000000000..52356bdf3ded95900fc0c1c7a3c41a7060730299
--- /dev/null
+++ b/UNGProject/openajaxhub/src/containers/iframe/crypto.js
@@ -0,0 +1,245 @@
+/*
+
+        Copyright 2006-2009 OpenAjax Alliance
+
+        Licensed under the Apache License, Version 2.0 (the "License"); 
+        you may not use this file except in compliance with the License. 
+        You may obtain a copy of the License at
+        
+                http://www.apache.org/licenses/LICENSE-2.0
+
+        Unless required by applicable law or agreed to in writing, software 
+        distributed under the License is distributed on an "AS IS" BASIS, 
+        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+        See the License for the specific language governing permissions and 
+        limitations under the License.
+*/
+// SMASH.CRYPTO
+//
+// Small library containing some minimal crypto functionality for a
+// - a hash-function: SHA-1 (see FIPS PUB 180-2 for definition)
+//     BigEndianWord[5] <- smash.crypto.sha1( BigEndianWord[*] dataWA, int lenInBits)
+//
+// - a message authentication code (MAC): HMAC-SHA-1 (RFC2104/2202)
+//     BigEndianWord[5] <- smash.crypto.hmac_sha1(
+//                            BigEndianWord[3-16] keyWA, 
+//                            Ascii or Unicode string dataS,
+//		 		 		       int chrsz (8 for Asci/16 for Unicode)
+//
+// - pseudo-random number generator (PRNG): HMAC-SHA-1 in counter mode, following
+//   Barak & Halevi, An architecture for robust pseudo-random generation and applications to /dev/random, CCS 2005
+//     rngObj <- smash.crypto.newPRNG( String[>=12] seedS)
+//   where rngObj has methods
+//     addSeed(String seed)
+//     BigEndianWord[len] <- nextRandomOctets(int len)
+//     Base64-String[len] <- nextRandomB64Str(int len)
+//   Note: HMAC-SHA1 in counter-mode does not provide forward-security on corruption. 
+//         However, the PRNG state is kept inside a closure. So if somebody can break the closure, he probably could
+//         break a whole lot more and forward-security of the prng is not the highest of concerns anymore :-)
+
+if ( typeof OpenAjax._smash == 'undefined' ) { OpenAjax._smash = {}; }
+
+OpenAjax._smash.crypto = {
+
+  // Some utilities
+  // convert a string to an array of big-endian words
+  'strToWA': function (/* Ascii or Unicode string */ str, /* int 8 for Asci/16 for Unicode */ chrsz){
+    var bin = Array();
+    var mask = (1 << chrsz) - 1;
+    for(var i = 0; i < str.length * chrsz; i += chrsz)
+      bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
+    return bin;
+  },
+
+
+  // MAC
+  'hmac_sha1' : function(
+        /* BigEndianWord[3-16]*/             keyWA,
+       /* Ascii or Unicode string */       dataS,
+       /* int 8 for Asci/16 for Unicode */ chrsz)
+  {
+    // write our own hmac derived from paj's so we do not have to do constant key conversions and length checking ...
+    var ipad = Array(16), opad = Array(16);
+    for(var i = 0; i < 16; i++) {
+      ipad[i] = keyWA[i] ^ 0x36363636;
+      opad[i] = keyWA[i] ^ 0x5C5C5C5C;
+    }
+
+    var hash = this.sha1( ipad.concat(this.strToWA(dataS, chrsz)), 512 + dataS.length * chrsz);
+    return     this.sha1( opad.concat(hash), 512 + 160);
+  },
+
+
+  // PRNG factory method
+  // see below 'addSeed', 'nextRandomOctets' & 'nextRandomB64Octets' for public methods of returnd prng object
+  'newPRNG' : function (/* String[>=12] */ seedS) {
+    that = this;
+
+    // parameter checking
+    // We cannot really verify entropy but obviously the string must have at least a minimal length to have enough entropy
+    // However, a 2^80 security seems ok, so we check only that at least 12 chars assuming somewhat random ASCII
+    if ( (typeof seedS != 'string') || (seedS.length < 12) ) {
+      alert("WARNING: Seed length too short ...");
+    }
+
+    // constants
+    var __refresh_keyWA = [ 0xA999, 0x3E36, 0x4706, 0x816A,
+    		 		 		     0x2571, 0x7850, 0xC26C, 0x9CD0,
+    		 		 		     0xBA3E, 0xD89D, 0x1233, 0x9525,
+    		 		 		     0xff3C, 0x1A83, 0xD491, 0xFF15 ]; // some random key for refresh ...
+
+    // internal state
+    var _keyWA = []; // BigEndianWord[5]
+    var _cnt = 0;  // int
+
+    function extract(seedS) {
+      return that.hmac_sha1(__refresh_keyWA, seedS, 8);
+    }
+
+    function refresh(seedS) {
+      // HMAC-SHA1 is not ideal, Rijndal 256bit block/key in CBC mode with fixed key might be better
+      // but to limit the primitives and given that we anyway have only limited entropy in practise
+      // this seems good enough
+      var uniformSeedWA = extract(seedS);
+      for(var i = 0; i < 5; i++) {
+        _keyWA[i] ^= uniformSeedWA[i];
+      }
+    }
+
+    // inital state seeding
+    refresh(seedS);
+
+    // public methods
+    return {
+      // Mix some additional seed into the PRNG state
+      'addSeed'         : function (/* String */ seed) {
+        // no parameter checking. Any added entropy should be fine ...
+        refresh(seed);
+      },
+
+
+      // Get an array of len random octets
+      'nextRandomOctets' : /* BigEndianWord[len] <- */ function (/* int */ len) {
+		 var randOctets = [];
+		 while (len > 0) {
+		   _cnt+=1;
+		   var nextBlock = that.hmac_sha1(_keyWA, (_cnt).toString(16), 8);
+		   for (i=0; (i < 20) & (len > 0); i++, len--) {
+		     randOctets.push( (nextBlock[i>>2] >> (i % 4) ) % 256);
+		   }
+		   // Note: if len was not a multiple 20, some random octets are ignored here but who cares ..
+		 }
+		 return randOctets;
+      },
+
+
+      // Get a random string of Base64-like (see below) chars of length len
+      // Note: there is a slightly non-standard Base64 with no padding and '-' and '_' for '+' and '/', respectively
+      'nextRandomB64Str' : /* Base64-String <- */ function (/* int */ len) {
+		 var b64StrMap = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+
+		 var randOctets = this.nextRandomOctets(len);
+		 var randB64Str = '';
+		 for (var i=0; i < len; i++) {
+		   randB64Str += b64StrMap.charAt(randOctets[i] & 0x3F);
+		 }
+        return randB64Str;
+      }
+
+    }
+  },
+
+
+  // Digest function:
+  // BigEndianWord[5] <- sha1( BigEndianWord[*] dataWA, int lenInBits)
+  'sha1' : function(){
+    // Note: all Section references below refer to FIPS 180-2.
+
+    // private utility functions
+
+    // - 32bit addition with wrap-around
+    var add_wa = function (x, y){
+      var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+      var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+      return (msw << 16) | (lsw & 0xFFFF);
+    }
+
+    // - 32bit rotatate left
+    var rol = function(num, cnt) {
+      return (num << cnt) | (num >>> (32 - cnt));
+    }
+
+    // - round-dependent function f_t from Section 4.1.1
+    function sha1_ft(t, b, c, d) {
+      if(t < 20) return (b & c) | ((~b) & d);
+      if(t < 40) return b ^ c ^ d;
+      if(t < 60) return (b & c) | (b & d) | (c & d);
+      return b ^ c ^ d;
+    }
+
+    // - round-dependent SHA-1 constants from Section 4.2.1
+    function sha1_kt(t) {
+      return (t < 20) ?  1518500249 :
+             (t < 40) ?  1859775393 :
+             (t < 60) ? -1894007588 :
+          /* (t < 80) */ -899497514 ;
+    }
+
+    // main algorithm. 
+    return function( /* BigEndianWord[*] */ dataWA, /* int */ lenInBits) {
+
+      // Section 6.1.1: Preprocessing
+      //-----------------------------
+      // 1. padding:  (see also Section 5.1.1)
+      //  - append one 1 followed by 0 bits filling up 448 bits of last (512bit) block
+      dataWA[lenInBits >> 5] |= 0x80 << (24 - lenInBits % 32);
+      //  - encode length in bits in last 64 bits
+      //    Note: we rely on javascript to zero file elements which are beyond last (partial) data-block
+      //    but before this length encoding!
+      dataWA[((lenInBits + 64 >> 9) << 4) + 15] = lenInBits;
+
+      // 2. 512bit blocks (actual split done ondemand later)
+      var W = Array(80);
+
+      // 3. initial hash using SHA-1 constants on page 13
+      var H0 =  1732584193;
+      var H1 = -271733879;
+      var H2 = -1732584194;
+      var H3 =  271733878;
+      var H4 = -1009589776;
+
+      // 6.1.2 SHA-1 Hash Computation
+      for(var i = 0; i < dataWA.length; i += 16) {
+        // 1. Message schedule, done below
+        // 2. init working variables
+        var a = H0; var b = H1; var c = H2; var d = H3; var e = H4;
+
+        // 3. round-functions
+        for(var j = 0; j < 80; j++)
+        {
+      		 // postponed step 2
+          W[j] = ( (j < 16) ? dataWA[i+j] : rol(W[j-3] ^ W[j-8] ^ W[j-14] ^ W[j-16], 1));
+
+          var T = add_wa( add_wa( rol(a, 5), sha1_ft(j, b, c, d)),
+                          add_wa( add_wa(e, W[j]), sha1_kt(j)) );
+          e = d;
+          d = c;
+          c = rol(b, 30);
+          b = a;
+          a = T;
+        }
+
+		 // 4. intermediate hash
+        H0 = add_wa(a, H0);
+        H1 = add_wa(b, H1);
+        H2 = add_wa(c, H2);
+        H3 = add_wa(d, H3);
+        H4 = add_wa(e, H4);
+      }
+
+      return Array(H0, H1, H2, H3, H4);
+    }
+  }()
+
+};
+
diff --git a/UNGProject/openajaxhub/src/containers/iframe/iframe.js b/UNGProject/openajaxhub/src/containers/iframe/iframe.js
new file mode 100644
index 0000000000000000000000000000000000000000..51ccd35a1bd321e4c84f76596ae286bb2ebe72a2
--- /dev/null
+++ b/UNGProject/openajaxhub/src/containers/iframe/iframe.js
@@ -0,0 +1,1243 @@
+/*
+
+        Copyright 2006-2009 OpenAjax Alliance
+
+        Licensed under the Apache License, Version 2.0 (the "License"); 
+        you may not use this file except in compliance with the License. 
+        You may obtain a copy of the License at
+        
+                http://www.apache.org/licenses/LICENSE-2.0
+
+        Unless required by applicable law or agreed to in writing, software 
+        distributed under the License is distributed on an "AS IS" BASIS, 
+        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+        See the License for the specific language governing permissions and 
+        limitations under the License.
+*/
+
+if ( typeof OpenAjax === "undefined" ) {
+    OpenAjax = { hub: {} };
+}
+
+/**
+ * Create a new Iframe Container.
+ * @constructor
+ * @extends OpenAjax.hub.Container
+ * 
+ * IframeContainer implements the Container interface to provide a container
+ * that isolates client components into secure sandboxes by leveraging the
+ * isolation features provided by browser iframes.
+ * 
+ * @param {OpenAjax.hub.ManagedHub} hub
+ *    Managed Hub instance to which this Container belongs
+ * @param {String} clientID
+ *    A string ID that identifies a particular client of a Managed Hub. Unique
+ *    within the context of the ManagedHub.
+ * @param {Object} params  
+ *    Parameters used to instantiate the IframeContainer.
+ *    Once the constructor is called, the params object belongs exclusively to
+ *    the IframeContainer. The caller MUST not modify it.
+ *    The following are the pre-defined properties on params:
+ * @param {Function} params.Container.onSecurityAlert
+ *    Called when an attempted security breach is thwarted.  Function is defined
+ *    as follows:  function(container, securityAlert)
+ * @param {Function} [params.Container.onConnect]
+ *    Called when the client connects to the Managed Hub.  Function is defined
+ *    as follows:  function(container)
+ * @param {Function} [params.Container.onDisconnect]
+ *    Called when the client disconnects from the Managed Hub.  Function is
+ *    defined as follows:  function(container)
+ * @param {Object} [params.Container.scope]
+ *    Whenever one of the Container's callback functions is called, references
+ *    to "this" in the callback will refer to the scope object. If no scope is
+ *    provided, default is window.
+ * @param {Function} [params.Container.log]
+ *    Optional logger function. Would be used to log to console.log or
+ *    equivalent. 
+ * @param {Object} params.IframeContainer.parent
+ *    DOM element that is to be parent of iframe
+ * @param {String} params.IframeContainer.uri
+ *    Initial Iframe URI (Container will add parameters to this URI)
+ * @param {String} params.IframeContainer.tunnelURI
+ *    URI of the tunnel iframe. Must be from the same origin as the page which
+ *    instantiates the IframeContainer.
+ * @param {Object} [params.IframeContainer.iframeAttrs]
+ *    Attributes to add to IFRAME DOM entity.  For example:
+ *              { style: { width: "100%",
+ *                         height: "100%" },
+ *                className: "some_class" }
+ * @param {Number} [params.IframeContainer.timeout]
+ *    Load timeout in milliseconds.  If not specified, defaults to 15000.  If
+ *    the client at params.IframeContainer.uri does not establish a connection
+ *    with this container in the given time, the onSecurityAlert callback is
+ *    called with a LoadTimeout error code.
+ * @param {Function} [params.IframeContainer.seed]
+ *    A function that returns a string that will be used to seed the
+ *    pseudo-random number generator, which is used to create the security
+ *    tokens.  An implementation of IframeContainer may choose to ignore this
+ *    value.
+ * @param {Number} [params.IframeContainer.tokenLength]
+ *    Length of the security tokens used when transmitting messages.  If not
+ *    specified, defaults to 6.  An implementation of IframeContainer may choose
+ *    to ignore this value.
+ *
+ * @throws {OpenAjax.hub.Error.BadParameters}   if required params are not
+ *          present or null
+ * @throws {OpenAjax.hub.Error.Duplicate}   if a Container with this clientID
+ *          already exists in the given Managed Hub
+ * @throws {OpenAjax.hub.Error.Disconnected}   if hub is not connected
+ */
+OpenAjax.hub.IframeContainer = function( hub, clientID, params )
+{
+    if ( ! hub || ! clientID || ! params ||
+            ! params.Container || ! params.Container.onSecurityAlert ||
+            ! params.IframeContainer || ! params.IframeContainer.parent ||
+            ! params.IframeContainer.uri || ! params.IframeContainer.tunnelURI ) {
+        throw new Error(OpenAjax.hub.Error.BadParameters);
+    }
+    
+    this._params = params;
+    this._id = clientID;
+
+    if ( window.postMessage ) {
+        this._delegate = new OpenAjax.hub.IframePMContainer( this, hub, clientID, params );
+    } else {
+        this._delegate = new OpenAjax.hub.IframeFIMContainer( this, hub, clientID, params );
+    }
+    
+    // Create IFRAME to hold the client
+    this._iframe = this._createIframe( params.IframeContainer.parent, this._delegate.getURI(),
+            params.IframeContainer.iframeAttrs );
+    
+    hub.addContainer( this );
+}
+
+    /*** OpenAjax.hub.Container interface implementation ***/
+
+OpenAjax.hub.IframeContainer.prototype.getHub = function()
+{
+    return this._delegate.getHub();
+}
+
+OpenAjax.hub.IframeContainer.prototype.sendToClient = function( topic, data, subscriptionID )
+{
+    this._delegate.sendToClient( topic, data, subscriptionID );
+}
+
+OpenAjax.hub.IframeContainer.prototype.remove = function()
+{
+    this._delegate.remove();
+    this._iframe.parentNode.removeChild( this._iframe );
+    delete this._iframe;
+}
+
+OpenAjax.hub.IframeContainer.prototype.isConnected = function()
+{
+    return this._delegate.isConnected();
+}
+
+OpenAjax.hub.IframeContainer.prototype.getClientID = function()
+{
+    return this._id;
+}
+
+OpenAjax.hub.IframeContainer.prototype.getPartnerOrigin = function()
+{
+    return this._delegate.getPartnerOrigin();
+}
+
+OpenAjax.hub.IframeContainer.prototype.getParameters = function()
+{
+    return this._params;
+}
+
+/**
+ * Get the iframe associated with this iframe container
+ * 
+ * This function returns the iframe associated with an IframeContainer,
+ * allowing the Manager Application to change its size, styles, scrollbars, etc.
+ * 
+ * CAUTION: The iframe is owned exclusively by the IframeContainer. The Manager
+ * Application MUST NOT destroy the iframe directly. Also, if the iframe is
+ * hidden and disconnected, the Manager Application SHOULD NOT attempt to make
+ * it visible. The Container SHOULD automatically hide the iframe when it is
+ * disconnected; to make it visible would introduce security risks. 
+ * 
+ * @returns iframeElement
+ * @type {Object}
+ */
+OpenAjax.hub.IframeContainer.prototype.getIframe = function() 
+{
+    return this._iframe;
+}
+
+    /*** Helper Functions ***/
+
+/**
+ * Return function that runs in given scope.
+ *
+ * @param {Object} toWhom  scope in which to run given function
+ * @param {Function} callback  function to run in given scope
+ * @returns {Function}
+ */
+OpenAjax.hub.IframeContainer.bind = function( toWhom, callback )
+{
+    var __method = callback;
+    return function() {
+        return __method.apply(toWhom, arguments);
+    }
+}
+
+
+    /*** Private Functions ***/
+
+OpenAjax.hub.IframeContainer.prototype._createIframe = function( parent, src, attrs )
+{
+    var iframe = document.createElement( "iframe" );
+    
+    // Add iframe attributes
+    if ( attrs ) {
+        for ( var attr in attrs ) {
+            if ( attr == "style" ) {
+                for ( var style in attrs.style ) {
+                    iframe.style[ style ] = attrs.style[ style ];
+                }
+            } else {
+                iframe[ attr ] = attrs[ attr ];
+            }
+        }
+    }
+
+    // initially hide IFRAME content, in order to lessen frame phishing impact
+    iframe.style.visibility = "hidden";
+    
+    // (1) Setting the iframe src after it has been added to the DOM can cause
+    // problems in IE6/7.  Specifically, if the code is being executed on a page
+    // that was served through HTTPS, then IE6/7 will see an iframe with a blank
+    // src as a non-secure item and display a dialog warning the user that "this
+    // page contains both secure and nonsecure items."  To prevent that, we
+    // first set the src to a dummy value, then add the iframe to the DOM, then
+    // set the real src value.
+    // (2) Trying to fix the above issue by setting the real src before adding
+    // the iframe to the DOM breaks Firefox 3.x.  For some reason, when
+    // reloading a page that has instantiated an IframeContainer, Firefox will
+    // load a previously cached version of the iframe content, whose source
+    // contains stale URL query params or hash.  This results in errors in the
+    // Hub code, which is expected different values.
+    iframe.src = 'javascript:"<html></html>"';
+    parent.appendChild( iframe );
+    iframe.src = src;
+    return iframe;
+}
+
+//------------------------------------------------------------------------------
+
+/**
+ * Create a new IframeHubClient.
+ * @constructor
+ * @extends OpenAjax.hub.HubClient
+ * 
+ * @param {Object} params
+ *    Once the constructor is called, the params object belongs to the
+ *    HubClient. The caller MUST not modify it.
+ *    The following are the pre-defined properties on params:
+ * @param {Function} params.HubClient.onSecurityAlert
+ *     Called when an attempted security breach is thwarted
+ * @param {Object} [params.HubClient.scope]
+ *     Whenever one of the HubClient's callback functions is called,
+ *     references to "this" in the callback will refer to the scope object.
+ *     If not provided, the default is window.
+ * @param {Function} [params.HubClient.log]
+ *     Optional logger function. Would be used to log to console.log or
+ *     equivalent. 
+ * @param {Function} [params.IframeHubClient.seed]
+ *     A function that returns a string that will be used to seed the
+ *     pseudo-random number generator, which is used to create the security
+ *     tokens.  An implementation of IframeHubClient may choose to ignore
+ *     this value.
+ * @param {Number} [params.IframeHubClient.tokenLength]
+ *     Length of the security tokens used when transmitting messages.  If
+ *     not specified, defaults to 6.  An implementation of IframeHubClient
+ *     may choose to ignore this value.
+ *     
+ * @throws {OpenAjax.hub.Error.BadParameters} if any of the required
+ *          parameters is missing, or if a parameter value is invalid in 
+ *          some way.
+ */
+OpenAjax.hub.IframeHubClient = function( params )
+{
+    if ( ! params || ! params.HubClient || ! params.HubClient.onSecurityAlert ) {
+        throw new Error( OpenAjax.hub.Error.BadParameters );
+    }
+    
+    this._params = params;
+    
+    if ( window.postMessage ) {
+        this._delegate = new OpenAjax.hub.IframePMHubClient( this, params );
+    } else {
+        this._delegate = new OpenAjax.hub.IframeFIMHubClient( this, params );
+    }
+}
+
+ /*** OpenAjax.hub.HubClient interface implementation ***/
+
+OpenAjax.hub.IframeHubClient.prototype.connect = function( onComplete, scope )
+{
+    scope = scope || window;
+    if ( this.isConnected() ) {
+        throw new Error( OpenAjax.hub.Error.Duplicate );
+    }
+    
+    this._delegate.connect( onComplete, scope );
+}
+
+OpenAjax.hub.IframeHubClient.prototype.disconnect = function( onComplete, scope )
+{
+    scope = scope || window;
+    if ( ! this.isConnected() ) {
+        throw new Error( OpenAjax.hub.Error.Disconnected );
+    }
+    
+    this._delegate.disconnect( onComplete, scope );
+}
+
+OpenAjax.hub.IframeHubClient.prototype.getPartnerOrigin = function()
+{
+    return this._delegate.getPartnerOrigin();
+}
+
+OpenAjax.hub.IframeHubClient.prototype.getClientID = function()
+{
+    return this._delegate.getClientID();
+}
+
+ /*** OpenAjax.hub.Hub interface implementation ***/
+
+OpenAjax.hub.IframeHubClient.prototype.subscribe = function( topic, onData, scope, onComplete, subscriberData )
+{
+    this._assertConn();
+    this._assertSubTopic( topic );
+    if ( ! onData ) {
+        throw new Error( OpenAjax.hub.Error.BadParameters );
+    }
+
+    scope = scope || window;
+    return this._delegate.subscribe( topic, onData, scope, onComplete, subscriberData );
+}
+
+OpenAjax.hub.IframeHubClient.prototype.publish = function( topic, data )
+{
+    this._assertConn();
+    this._assertPubTopic( topic );
+    this._delegate.publish( topic, data );
+}
+
+OpenAjax.hub.IframeHubClient.prototype.unsubscribe = function( subscriptionID, onComplete, scope )
+{
+    this._assertConn();
+    if ( typeof subscriptionID === "undefined" || subscriptionID == null ) {
+        throw new Error( OpenAjax.hub.Error.BadParameters );
+    }
+    scope = scope || window;
+    this._delegate.unsubscribe( subscriptionID, onComplete, scope );
+}
+
+OpenAjax.hub.IframeHubClient.prototype.isConnected = function()
+{
+    return this._delegate.isConnected();
+}
+
+OpenAjax.hub.IframeHubClient.prototype.getScope = function()
+{
+    return this._delegate.getScope();
+}
+
+OpenAjax.hub.IframeHubClient.prototype.getSubscriberData = function( subscriptionID )
+{
+    this._assertConn();
+    return this._delegate.getSubscriberData( subscriptionID );
+}
+
+OpenAjax.hub.IframeHubClient.prototype.getSubscriberScope = function( subscriptionID )
+{
+    this._assertConn();
+    return this._delegate.getSubscriberScope( subscriptionID );
+}
+
+OpenAjax.hub.IframeHubClient.prototype.getParameters = function()
+{
+    return this._params;
+}
+
+ /*** Private Functions ***/
+
+OpenAjax.hub.IframeHubClient.prototype._assertConn = function()
+{
+    if ( ! this.isConnected() ) {
+        throw new Error( OpenAjax.hub.Error.Disconnected );
+    }
+}
+
+OpenAjax.hub.IframeHubClient.prototype._assertSubTopic = function( topic )
+{
+    if ( ! topic ) {
+        throw new Error(OpenAjax.hub.Error.BadParameters);
+    }
+    var path = topic.split(".");
+    var len = path.length;
+    for (var i = 0; i < len; i++) {
+        var p = path[i];
+        if ((p == "") ||
+           ((p.indexOf("*") != -1) && (p != "*") && (p != "**"))) {
+            throw new Error(OpenAjax.hub.Error.BadParameters);
+        }
+        if ((p == "**") && (i < len - 1)) {
+            throw new Error(OpenAjax.hub.Error.BadParameters);
+        }
+    }
+}
+
+OpenAjax.hub.IframeHubClient.prototype._assertPubTopic = function( topic )
+{
+    if ((topic == null) || (topic == "") || (topic.indexOf("*") != -1) ||
+        (topic.indexOf("..") != -1) ||  (topic.charAt(0) == ".") ||
+        (topic.charAt(topic.length-1) == "."))
+    {
+        throw new Error(OpenAjax.hub.Error.BadParameters);
+    }
+}
+
+/******************************************************************************
+ *  PostMessage Iframe Container
+ *
+ *      Implementation of the Iframe Container which uses window.postMessage()
+ *      for communicating between an iframe and its parent.
+ ******************************************************************************/
+
+OpenAjax.hub.IframePMContainer = function( container, hub, clientID, params )
+{
+    this._container = container;
+    this._hub = hub;
+    this._id = clientID;
+    this._onSecurityAlert = params.Container.onSecurityAlert;
+    this._onConnect = params.Container.onConnect ? params.Container.onConnect : null;
+    this._onDisconnect = params.Container.onDisconnect ? params.Container.onDisconnect : null;
+    this._scope = params.Container.scope || window;
+    this._uri = params.IframeContainer.uri;
+    this._tunnelURI = params.IframeContainer.tunnelURI;
+    this._timeout = params.IframeContainer.timeout || 15000;
+    
+    if ( params.Container.log ) {
+        var scope = this._scope;
+        var logfunc = params.Container.log;
+        this._log = function( msg ) {
+            logfunc.call( scope, "IframeContainer::" + clientID + ": " + msg );
+        };
+    } else {
+        this._log = function() {};
+    }
+    
+    this._securityToken = this._generateSecurityToken( params );
+    
+    this._connected = false;
+    this._subs = {};
+    
+    // test if the postMessage impl of this browser is synchronous
+    if ( typeof OpenAjax.hub.IframePMContainer._pmCapabilities === "undefined" ) {
+        this._testPostMessage();
+    }
+    
+    // if postMessage is synchronous, wrap in a setTimeout
+    if ( OpenAjax.hub.IframePMContainer._pmCapabilities.indexOf("s") == -1 ) {
+        this._postMessage = function( win, msg, origin ) {
+            win.postMessage( msg, origin );
+        }
+    } else {
+        this._postMessage = function( win, msg, origin ) {
+            setTimeout(
+                function() {
+                    win.postMessage( msg, origin );
+                },
+                0
+            );
+        }
+    }
+    
+    // register this container with the singleton message listener
+    if ( ! OpenAjax.hub.IframePMContainer._pmListener ) {
+        OpenAjax.hub.IframePMContainer._pmListener =
+                new OpenAjax.hub.IframePMContainer.PMListener();
+    }
+    // the 'internal ID' is guaranteed to be unique within the page, not just
+    // the ManagedHub instance
+    this._internalID = OpenAjax.hub.IframePMContainer._pmListener.addContainer( this );
+    
+    this._startLoadTimer();
+}
+
+// communications protocol identifier
+OpenAjax.hub.IframePMContainer.protocolID = "openajax-2.0";
+
+// Singleton message listener
+OpenAjax.hub.IframePMContainer._pmListener = null;
+
+OpenAjax.hub.IframePMContainer.prototype.getHub = function() {
+	return this._hub;
+};
+
+OpenAjax.hub.IframePMContainer.prototype.sendToClient = function( topic, data, subscriptionID )
+{
+    this._sendMessage( "pub", { t: topic, d: data, s: subscriptionID } );
+}
+
+OpenAjax.hub.IframePMContainer.prototype.remove = function()
+{
+    this._disconnect();
+    OpenAjax.hub.IframePMContainer._pmListener.removeContainer( this._internalID );
+    clearTimeout( this._loadTimer );
+    delete this._iframe;
+}
+
+OpenAjax.hub.IframePMContainer.prototype.isConnected = function()
+{
+    return this._connected;
+}
+
+OpenAjax.hub.IframePMContainer.prototype.getPartnerOrigin = function()
+{
+    if ( this._connected ) {
+        // remove port, if it is present
+        return new RegExp( "^([a-zA-Z]+://[^:]+).*" ).exec( this._partnerOrigin )[1];
+    }
+    return null;
+}
+
+OpenAjax.hub.IframePMContainer.prototype.receiveMessage = function( event, msg )
+{
+    // check that security token and client window origin for incoming message
+    // are what we expect
+    if ( msg.t != this._securityToken ||
+            ( typeof this._partnerOrigin != "undefined" &&
+              ! OpenAjax.hub.IframePMContainer.originMatches( this, event )))
+    {
+        // security error -- incoming message is not valid; ignore
+        this._invokeSecurityAlert( OpenAjax.hub.SecurityAlert.ForgedMsg );
+        return;
+    }
+    
+    this._log( "received message: [" + event.data + "]" );
+
+    switch ( msg.m ) {
+        // subscribe
+        case "sub":
+            var errCode = "";  // empty string is success
+            try {
+                this._subs[ msg.p.s ] = this._hub.subscribeForClient( this._container, msg.p.t, msg.p.s );
+            } catch( e ) {
+                errCode = e.message;
+            }
+            this._sendMessage( "sub_ack", { s: msg.p.s, e: errCode } );
+            break;
+        
+        // publish
+        case "pub":
+            this._hub.publishForClient( this._container, msg.p.t, msg.p.d );
+            break;
+
+        // unsubscribe
+        case "uns":
+            var handle = this._subs[ msg.p.s ];
+            this._hub.unsubscribeForClient( this._container, handle );
+            delete this._subs[ msg.p.s ];
+            this._sendMessage( "uns_ack", msg.p.s );
+            break;
+
+        // connect is handled elsewhere -- see IframePMContainer.prototype.connect
+        
+        // disconnect
+        case "dis":
+            this._startLoadTimer();
+            this._disconnect();
+            this._sendMessage( "dis_ack", null );
+            if ( this._onDisconnect ) {
+                try {
+                    this._onDisconnect.call( this._scope, this._container );
+                } catch( e ) {
+                    OpenAjax.hub._debugger();
+                    this._log( "caught error from onDisconnect callback to constructor: " + e.message );
+                }
+            }
+            break;
+    }
+}
+
+/**
+ * Complete connection from HubClient to this Container.
+ *
+ * @param {String} origin  IframePMHubClient's window's origin
+ * @param {String} securityToken  Security token originally sent by Container
+ * @param {Object} tunnelWindow  window object reference of tunnel window
+ */
+OpenAjax.hub.IframePMContainer.prototype.connect = function( origin, securityToken, tunnelWindow )
+{
+    this._log( "client connecting to container " + this._id +
+            " :: origin = " + origin + " :: securityToken = " + securityToken );
+
+    // check that security token is what we expect
+    if ( securityToken != this._securityToken ) {
+        // security error -- incoming message is not valid
+        this._invokeSecurityAlert( OpenAjax.hub.SecurityAlert.ForgedMsg );
+        return;
+    }
+    
+    // set unload handler on tunnel window
+    var that = this;
+    tunnelWindow.onunload = function() {
+        if ( that.isConnected() ) {
+        	// Use a timer to delay the phishing message. This makes sure that
+        	// page navigation does not cause phishing errors.
+        	// Setting it to 1 ms is enough for it not to be triggered on
+        	// regular page navigations.
+            setTimeout(
+                function() {
+                    that._invokeSecurityAlert( OpenAjax.hub.SecurityAlert.FramePhish );
+                }, 1
+            );
+        }
+    };
+    
+    clearTimeout( this._loadTimer );
+
+    this._iframe = this._container.getIframe();
+    this._iframe.style.visibility = "visible";
+
+    this._partnerOrigin = origin;
+    // if "message" event doesn't support "origin" property, then save hostname
+    // (domain) also
+    if ( OpenAjax.hub.IframePMContainer._pmCapabilities.indexOf("d") != -1 ) {
+        this._partnerDomain = new RegExp( "^.+://([^:]+).*" ).exec( this._partnerOrigin )[1];
+    }
+    
+    this._sendMessage( "con_ack", null );
+    this._connected = true;
+    if ( this._onConnect ) {
+        try {
+            this._onConnect.call( this._scope, this._container );
+        } catch( e ) {
+            OpenAjax.hub._debugger();
+            this._log( "caught error from onConnect callback to constructor: " + e.message );
+        }
+    }
+}
+
+OpenAjax.hub.IframePMContainer.prototype.getURI = function()
+{
+    // add the client ID and a security token as URL query params when loading
+    // the client iframe
+    var paramStr =
+            "oahpv=" + encodeURIComponent( OpenAjax.hub.IframePMContainer.protocolID ) +
+            "&oahi=" + encodeURIComponent( this._internalID ) +
+            "&oaht=" + this._securityToken +
+            "&oahu=" + encodeURIComponent( this._tunnelURI ) +
+            "&oahpm=" + OpenAjax.hub.IframePMContainer._pmCapabilities;
+    if ( this._id !== this._internalID ) {
+        paramStr += "&oahj=" + this._internalID;
+    }
+    paramStr += OpenAjax.hub.enableDebug ? "&oahd=true" : ""; // REMOVE ON BUILD
+
+    var parts = this._uri.split("#");
+    parts[0] = parts[0] + ((parts[0].indexOf( "?" ) != -1) ? "&" : "?") + paramStr;
+    if ( parts.length == 1 ) {
+        return parts[0];
+    }
+    return parts[0] + "#" + parts[1];
+}
+
+ /*** Helper Functions ***/
+
+OpenAjax.hub.IframePMContainer.originMatches = function( obj, event )
+{
+  if ( event.origin ) {
+      return event.origin == obj._partnerOrigin;
+  } else {
+      return event.domain == obj._partnerDomain;
+  }
+}
+
+ /*** Private Function ***/
+
+OpenAjax.hub.IframePMContainer.prototype._generateSecurityToken = function( params )
+{
+    if ( ! OpenAjax.hub.IframePMContainer._prng ) {
+        // create pseudo-random number generator with a default seed
+        var seed = new Date().getTime() + Math.random() + document.cookie;
+        OpenAjax.hub.IframePMContainer._prng = OpenAjax._smash.crypto.newPRNG( seed );
+    }
+    
+    if ( params.IframeContainer.seed ) {
+        try {
+            var extraSeed = params.IframeContainer.seed.call( this._scope );
+            OpenAjax.hub.IframePMContainer._prng.addSeed( extraSeed );
+        } catch( e ) {
+            OpenAjax.hub._debugger();
+            this._log( "caught error from 'seed' callback: " + e.message );
+        }
+    }
+    
+    var tokenLength = params.IframeContainer.tokenLength || 6;
+    return OpenAjax.hub.IframePMContainer._prng.nextRandomB64Str( tokenLength );
+}
+
+/**
+ * Some browsers (IE, Opera) have an implementation of postMessage that is
+ * synchronous, although HTML5 specifies that it should be asynchronous.  In
+ * order to make all browsers behave consistently, we run a small test to detect
+ * if postMessage is asynchronous or not.  If not, we wrap calls to postMessage
+ * in a setTimeout with a timeout of 0.
+ * Also, Opera's "message" event does not have an "origin" property (at least,
+ * it doesn't in version 9.64;  presumably, it will in version 10).  If
+ * event.origin does not exist, use event.domain.  The other difference is that
+ * while event.origin looks like <scheme>://<hostname>:<port>, event.domain
+ * consists only of <hostname>.
+ */
+OpenAjax.hub.IframePMContainer.prototype._testPostMessage = function()
+{
+    // String identifier that specifies whether this browser's postMessage
+    // implementation differs from the spec:
+    //      contains "s" - postMessage is synchronous
+    //      contains "d" - "message" event does not have an "origin" property;
+    //                     the code looks for the "domain" property instead
+    OpenAjax.hub.IframePMContainer._pmCapabilities = "";
+
+    var hit = false;
+    
+    function receiveMsg(event) {
+        if ( event.data == "postmessage.test" ) {
+            hit = true;
+            if ( typeof event.origin === "undefined" ) {
+                OpenAjax.hub.IframePMContainer._pmCapabilities += "d";
+            }
+        }
+    }
+    
+    if ( window.addEventListener ) {
+        window.addEventListener( "message", receiveMsg, false );
+    } else if ( window.attachEvent ) {
+        window.attachEvent( "onmessage", receiveMsg );
+    }
+    window.postMessage( "postmessage.test", "*" );
+    
+    // if 'hit' is true here, then postMessage is synchronous
+    if ( hit ) {
+        OpenAjax.hub.IframePMContainer._pmCapabilities += "s";
+    }
+
+    if ( window.removeEventListener ) {
+        window.removeEventListener( "message", receiveMsg, false );
+    } else {
+        window.detachEvent( "onmessage", receiveMsg );
+    }
+}
+
+OpenAjax.hub.IframePMContainer.prototype._startLoadTimer = function()
+{
+    var that = this;
+    this._loadTimer = setTimeout(
+        function() {
+            // don't accept any messages from client
+            OpenAjax.hub.IframePMContainer._pmListener.removeContainer( that._internalID );
+            // alert the security alert callback
+            that._invokeSecurityAlert( OpenAjax.hub.SecurityAlert.LoadTimeout );
+        },
+        this._timeout
+    );
+}
+
+/**
+ * Send a string message to the associated hub client.
+ *
+ * The message is a JSON representation of the following object:
+ *      {
+ *          m: message type,
+ *          i: client id,
+ *          t: security token,
+ *          p: payload (depends on message type)
+ *      }
+ *
+ * The payload for each message type is as follows:
+ *      TYPE        DESCRIPTION                     PAYLOAD
+ *      "con_ack"    connect acknowledgment          N/A
+ *      "dis_ack"    disconnect acknowledgment       N/A
+ *      "sub_ack"    subscribe acknowledgment        { s: subscription id, e: error code (empty string if no error) }
+ *      "uns_ack"    unsubscribe acknowledgment      { s: subscription id }
+ *      "pub"        publish (i.e. sendToClient())   { t: topic, d: data, s: subscription id }
+ */
+OpenAjax.hub.IframePMContainer.prototype._sendMessage = function( type, payload )
+{
+    var msg = JSON.stringify({
+        m: type,
+        i: this._internalID,
+        t: this._securityToken,
+        p: payload
+    });
+    this._postMessage( this._iframe.contentWindow, msg, this._partnerOrigin );
+}
+
+OpenAjax.hub.IframePMContainer.prototype._disconnect = function()
+{
+    if ( this._connected ) {
+        this._connected = false;
+        this._iframe.style.visibility = "hidden";
+    
+        // unsubscribe from all subs
+        for ( var sub in this._subs ) {
+            this._hub.unsubscribeForClient( this._container, this._subs[ sub ] );
+        }
+        this._subs = {};
+    }
+}
+
+OpenAjax.hub.IframePMContainer.prototype._invokeSecurityAlert = function( errorMsg )
+{
+    try {
+        this._onSecurityAlert.call( this._scope, this._container, errorMsg );
+    } catch( e ) {
+        OpenAjax.hub._debugger();
+        this._log( "caught error from onSecurityAlert callback to constructor: " + e.message );
+    }
+}
+
+
+//------------------------------------------------------------------------------
+
+OpenAjax.hub.IframePMContainer.PMListener = function()
+{
+    this._containers = {};
+    
+    if ( window.addEventListener ) {
+        window.addEventListener( "message",
+                OpenAjax.hub.IframeContainer.bind( this, this._receiveMessage ), false); 
+    } else if ( window.attachEvent ) {
+        window.attachEvent( "onmessage",
+                OpenAjax.hub.IframeContainer.bind( this, this._receiveMessage ) );
+    }
+}
+
+/**
+ * Add an IframePMContainer to listen for messages.  Returns an ID for the given
+ * container that is unique within the PAGE, not just the ManagedHub instance.
+ */
+OpenAjax.hub.IframePMContainer.PMListener.prototype.addContainer = function( container )
+{
+    var id = container._id;
+    while ( this._containers[ id ] ) {
+        // a client with the specified ID already exists on this page;
+        // create a unique ID
+        id = ((0x7fff * Math.random()) | 0).toString(16) + "_" + id;
+    }
+
+    this._containers[ id ] = container;
+    return id;
+}
+
+OpenAjax.hub.IframePMContainer.PMListener.prototype.removeContainer = function( internalID )
+{
+    delete this._containers[ internalID ];
+    // XXX TODO If no more postMessage containers, remove listener?
+}
+
+/**
+ * Complete connection between HubClient and Container identified by "id".  This
+ * function is only called by the tunnel window.
+ */
+OpenAjax.hub.IframePMContainer.PMListener.prototype.connectFromTunnel = function( internalID, origin, securityToken, tunnelWindow )
+{
+    if ( this._containers[ internalID ] ) {
+        this._containers[ internalID ].connect( origin, securityToken, tunnelWindow );
+    }
+}
+
+OpenAjax.hub.IframePMContainer.PMListener.prototype._receiveMessage = function( event )
+{
+    // If the received message isn't JSON parseable or if the resulting
+    // object doesn't have the structure we expect, then just return.
+    try {
+        var msg = JSON.parse( event.data );
+    } catch( e ) {
+        return;
+    }
+    if ( ! this._verifyMsg( msg ) ) {
+        return;
+    }
+    
+    if ( this._containers[ msg.i ] ) {
+        var container = this._containers[ msg.i ].receiveMessage( event, msg );
+    }
+}
+
+OpenAjax.hub.IframePMContainer.PMListener.prototype._verifyMsg = function( msg )
+{
+    return typeof msg.m == "string" && typeof msg.i == "string" &&
+            "t" in msg && "p" in msg;
+}
+
+//------------------------------------------------------------------------------
+
+OpenAjax.hub.IframePMHubClient = function( client, params )
+{
+    // check communications protocol ID
+    this._checkProtocolID();
+    
+    this._client = client;
+    this._onSecurityAlert = params.HubClient.onSecurityAlert;
+    this._scope = params.HubClient.scope || window;
+    this._id = OpenAjax.hub.IframePMHubClient.queryURLParam( "oahi" );
+    this._internalID = OpenAjax.hub.IframePMHubClient.queryURLParam( "oahj" ) || this._id;
+    this._securityToken = OpenAjax.hub.IframePMHubClient.queryURLParam( "oaht" );
+    this._tunnelURI = OpenAjax.hub.IframePMHubClient.queryURLParam( "oahu" );
+    OpenAjax.hub.IframePMContainer._pmCapabilities = OpenAjax.hub.IframePMHubClient.queryURLParam( "oahpm" );
+    
+    // if any of the URL params are missing, throw WrongProtocol error
+    if ( ! this._id || ! this._securityToken || ! this._tunnelURI ) {
+        throw new Error( OpenAjax.hub.Error.WrongProtocol );
+    }
+    
+    if ( OpenAjax.hub.IframePMHubClient.queryURLParam("oahd") )  OpenAjax.hub.enableDebug = true; // REMOVE ON BUILD
+    
+    this._partnerOrigin = new RegExp( "^([a-zA-Z]+://[^/?#]+).*" ).exec( this._tunnelURI )[1];
+    // if "message" event doesn't support "origin" property, then save hostname
+    // (domain) also
+    if ( OpenAjax.hub.IframePMContainer._pmCapabilities.indexOf("d") != -1 ) {
+        this._partnerDomain = new RegExp( "^.+://([^:]+).*" ).exec( this._partnerOrigin )[1];
+    }
+    
+    if ( params.HubClient.log ) {
+        var id = this._id;
+        var scope = this._scope;
+        var logfunc = params.HubClient.log;
+        this._log = function( msg ) {
+            logfunc.call( scope, "IframeHubClient::" + id + ": " + msg );
+        };
+    } else {
+        this._log = function() {};
+    }
+    
+    this._connected = false;
+    this._subs = {};
+    this._subIndex = 0;
+    
+    // if postMessage is synchronous, wrap in a setTimeout
+    if ( OpenAjax.hub.IframePMContainer._pmCapabilities.indexOf("s") == -1 ) {
+        this._postMessage = function( win, msg, origin ) {
+            win.postMessage( msg, origin );
+        }
+    } else {
+        this._postMessage = function( win, msg, origin ) {
+            setTimeout(
+                function() {
+                    win.postMessage( msg, origin );
+                },
+                0
+            );
+        }
+    }
+}
+
+// communications protocol identifier
+OpenAjax.hub.IframePMHubClient.protocolID = "openajax-2.0";
+
+    /*** OpenAjax.hub.HubClient interface implementation ***/
+
+OpenAjax.hub.IframePMHubClient.prototype.connect = function( onComplete, scope )
+{
+    if ( onComplete ) {
+        this._connectOnComplete = { cb: onComplete, sc: scope };
+    }
+    
+    // start listening for messages
+    this._msgListener = OpenAjax.hub.IframeContainer.bind( this, this._receiveMessage );
+    if ( window.addEventListener ) {
+        window.addEventListener( "message", this._msgListener, false); 
+    } else if ( window.attachEvent ) {
+        window.attachEvent( "onmessage", this._msgListener );
+    }
+    
+    // create tunnel iframe, which will finish connection to container
+    var origin = window.location.protocol + "//" + window.location.host;
+    var iframe = document.createElement( "iframe" );
+    document.body.appendChild( iframe );
+    iframe.src = this._tunnelURI +
+            (this._tunnelURI.indexOf("?") == -1 ? "?" : "&") +
+            "oahj=" + encodeURIComponent( this._internalID ) +
+            "&oaht=" + this._securityToken + 
+            "&oaho=" + encodeURIComponent( origin );
+	iframe.style.position = "absolute";
+	iframe.style.left = iframe.style.top = "-10px";
+	iframe.style.height = iframe.style.width = "1px";
+	iframe.style.visibility = "hidden";
+	this._tunnelIframe = iframe;
+}
+
+OpenAjax.hub.IframePMHubClient.prototype.disconnect = function( onComplete, scope )
+{
+    this._connected = false;
+    if ( onComplete ) {
+        this._disconnectOnComplete = { cb: onComplete, sc: scope };
+    }
+    this._sendMessage( "dis", null );
+}
+
+OpenAjax.hub.IframePMHubClient.prototype.getPartnerOrigin = function()
+{
+    if ( this._connected ) {
+        // remove port, if it is present
+        return new RegExp( "^([a-zA-Z]+://[^:]+).*" ).exec( this._partnerOrigin )[1];
+    }
+    return null;
+}
+
+OpenAjax.hub.IframePMHubClient.prototype.getClientID = function()
+{
+    return this._id;
+}
+
+    /*** OpenAjax.hub.Hub interface implementation ***/
+
+OpenAjax.hub.IframePMHubClient.prototype.subscribe = function( topic, onData, scope, onComplete, subscriberData )
+{
+    var subID = "" + this._subIndex++;
+    this._subs[ subID ] = { cb: onData, sc: scope, d: subscriberData, oc: onComplete };
+    this._sendMessage( "sub", { t: topic, s: subID } );
+    return subID;
+}
+
+OpenAjax.hub.IframePMHubClient.prototype.publish = function( topic, data )
+{
+    this._sendMessage( "pub", { t: topic, d: data } );
+}
+
+OpenAjax.hub.IframePMHubClient.prototype.unsubscribe = function( subID, onComplete, scope )
+{
+    // if no such subID, or in process of unsubscribing given ID, throw error
+    if ( ! this._subs[ subID ] || this._subs[ subID ].uns ) {
+        throw new Error( OpenAjax.hub.Error.NoSubscription );
+    }
+    this._subs[ subID ].uns = { cb: onComplete, sc: scope };
+    this._sendMessage( "uns", { s: subID } );
+}
+
+OpenAjax.hub.IframePMHubClient.prototype.isConnected = function()
+{
+    return this._connected;
+}
+
+OpenAjax.hub.IframePMHubClient.prototype.getScope = function()
+{
+    return this._scope;
+}
+
+OpenAjax.hub.IframePMHubClient.prototype.getSubscriberData = function( subID )
+{
+    var sub = this._subs[ subID ];
+    if ( sub ) {
+        return sub.d;
+    }
+    throw new Error( OpenAjax.hub.Error.NoSubscription );
+}
+
+OpenAjax.hub.IframePMHubClient.prototype.getSubscriberScope = function( subID )
+{
+    var sub = this._subs[ subID ];
+    if ( sub ) {
+        return sub.sc;
+    }
+    throw new Error( OpenAjax.hub.Error.NoSubscription );
+}
+
+    /*** Helper Functions ***/
+
+OpenAjax.hub.IframePMHubClient.queryURLParam = function( param )
+{
+    var result = new RegExp( "[\\?&]" + param + "=([^&#]*)" ).exec( window.location.search );
+    if ( result ) {
+        return decodeURIComponent( result[1].replace( /\+/g, "%20" ) );
+    }
+    return null;
+};
+
+    /*** Private Functions ***/
+
+OpenAjax.hub.IframePMHubClient.prototype._checkProtocolID = function()
+{
+    var partnerProtocolID = OpenAjax.hub.IframePMHubClient.queryURLParam( "oahpv" );
+    if ( partnerProtocolID != OpenAjax.hub.IframePMHubClient.protocolID ) {
+        throw new Error( OpenAjax.hub.Error.WrongProtocol );
+    }
+}
+
+OpenAjax.hub.IframePMHubClient.prototype._receiveMessage = function( event )
+{
+    // If the received message isn't JSON parseable or if the resulting
+    // object doesn't have the structure we expect, then just return.  This
+    // message might belong to some other code on the page that is also using
+    // postMessage for communication.
+    try {
+        var msg = JSON.parse( event.data );
+    } catch( e ) {
+        return;
+    }
+    if ( ! this._verifyMsg( msg ) ) {
+        return;
+    }
+    
+    // check that security token and window source for incoming message
+    // are what we expect
+    if ( msg.i != this._internalID ) {
+        // this message might belong to an IframeContainer on this page
+        return;
+    } else if ( ! OpenAjax.hub.IframePMContainer.originMatches( this, event ) ||
+            msg.t != this._securityToken )
+    {
+        // security error -- incoming message is not valid
+        try{
+            this._onSecurityAlert.call( this._scope, this._client,
+                    OpenAjax.hub.SecurityAlert.ForgedMsg );
+        } catch( e ) {
+            OpenAjax.hub._debugger();
+            this._log( "caught error from onSecurityAlert callback to constructor: " + e.message );
+        }
+        return;
+    }
+
+    this._log( "received message: [" + event.data + "]" );
+
+    switch ( msg.m ) {
+        // subscribe acknowledgement
+        case "sub_ack":
+            var subID = msg.p.s;
+            var onComplete = this._subs[ subID ].oc;
+            if ( onComplete ) {
+                try {
+                    delete this._subs[ subID ].oc;
+                    var scope = this._subs[ subID ].sc;
+                    onComplete.call( scope, msg.p.s, msg.p.e == "", msg.p.e );
+                } catch( e ) {
+                    OpenAjax.hub._debugger();
+                    this._log( "caught error from onComplete callback to HubClient.subscribe(): " + e.message );
+                }
+            }
+            break;
+        
+        // publish event
+        case "pub":
+            var subID = msg.p.s;
+            // if subscription exists and we are not in process of unsubscribing...
+            if ( this._subs[ subID ] && ! this._subs[ subID ].uns ) {
+                var onData = this._subs[ subID ].cb;
+                var scope = this._subs[ subID ].sc;
+                var subscriberData = this._subs[ subID ].d;
+                try {
+                    onData.call( scope, msg.p.t, msg.p.d, subscriberData );
+                } catch( e ) {
+                    OpenAjax.hub._debugger();
+                    this._log( "caught error from onData callback to HubClient.subscribe(): " + e.message );
+                }
+            }
+            break;
+        
+        // unsubscribe acknowledgement
+        case "uns_ack":
+            var subID = msg.p;
+            if ( this._subs[ subID ] ) {
+                var onComplete = this._subs[ subID ].uns.cb;
+                if ( onComplete ) {
+                    try {
+                        var scope = this._subs[ subID ].uns.sc;
+                        onComplete.call( scope, subID, true );
+                    } catch( e ) {
+                        OpenAjax.hub._debugger();
+                        this._log( "caught error from onComplete callback to HubClient.unsubscribe(): " + e.message );
+                    }
+                }
+                delete this._subs[ subID ];
+            }
+            break;
+        
+        // connect acknowledgement
+        case "con_ack":
+            this._connected = true;
+            if ( this._connectOnComplete ) {
+                var onComplete = this._connectOnComplete.cb;
+                var scope = this._connectOnComplete.sc;
+                try {
+                    onComplete.call( scope, this._client, true );
+                } catch( e ) {
+                    OpenAjax.hub._debugger();
+                    this._log( "caught error from onComplete callback to HubClient.connect(): " + e.message );
+                }
+                delete this._connectOnComplete;
+            }
+            break;
+        
+        // disconnect acknowledgment
+        case "dis_ack":
+            // stop listening for messages
+            if ( window.removeEventListener ) {
+                window.removeEventListener( "message", this._msgListener, false );
+            } else {
+                window.detachEvent( "onmessage", this._msgListener );
+            }
+            delete this._msgListener;
+            
+            this._tunnelIframe.parentNode.removeChild( this._tunnelIframe );
+            delete this._tunnelIframe;
+            
+            if ( this._disconnectOnComplete ) {
+                try {
+                    var onComplete = this._disconnectOnComplete.cb;
+                    var scope = this._disconnectOnComplete.sc;
+                    onComplete.call( scope, this._client, true );
+                } catch( e ) {
+                    OpenAjax.hub._debugger();
+                    this._log( "caught error from onComplete callback to HubClient.disconnect(): " + e.message );
+                }
+                delete this._disconnectOnComplete;
+            }
+            break;
+    }
+}
+
+OpenAjax.hub.IframePMHubClient.prototype._verifyMsg = function( msg )
+{
+    return typeof msg.m == "string" && "t" in msg && "p" in msg;
+}
+
+/**
+ * Send a string message to the associated container.
+ *
+ * The message is a JSON representation of the following object:
+ *      {
+ *          m: message type,
+ *          i: client id,
+ *          t: security token,
+ *          p: payload (depends on message type)
+ *      }
+ *
+ * The payload for each message type is as follows:
+ *      TYPE    DESCRIPTION     PAYLOAD
+ *      "con"    connect         N/A
+ *      "dis"    disconnect      N/A
+ *      "sub"    subscribe       { t: topic, s: subscription id }
+ *      "uns"    unsubscribe     { s: subscription id }
+ *      "pub"    publish         { t: topic, d: data }
+ */
+OpenAjax.hub.IframePMHubClient.prototype._sendMessage = function( type, payload )
+{
+    var msg = JSON.stringify({
+        m: type,
+        i: this._internalID,
+        t: this._securityToken,
+        p: payload
+    });
+    this._postMessage( window.parent, msg, this._partnerOrigin );
+}
diff --git a/UNGProject/openajaxhub/src/containers/iframe/json2.js b/UNGProject/openajaxhub/src/containers/iframe/json2.js
new file mode 100644
index 0000000000000000000000000000000000000000..241a27198eb3758d81dc2d45eb3bfa065acbca07
--- /dev/null
+++ b/UNGProject/openajaxhub/src/containers/iframe/json2.js
@@ -0,0 +1,478 @@
+/*
+    http://www.JSON.org/json2.js
+    2008-11-19
+
+    Public Domain.
+
+    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+
+    See http://www.JSON.org/js.html
+
+    This file creates a global JSON object containing two methods: stringify
+    and parse.
+
+        JSON.stringify(value, replacer, space)
+            value       any JavaScript value, usually an object or array.
+
+            replacer    an optional parameter that determines how object
+                        values are stringified for objects. It can be a
+                        function or an array of strings.
+
+            space       an optional parameter that specifies the indentation
+                        of nested structures. If it is omitted, the text will
+                        be packed without extra whitespace. If it is a number,
+                        it will specify the number of spaces to indent at each
+                        level. If it is a string (such as '\t' or '&nbsp;'),
+                        it contains the characters used to indent at each level.
+
+            This method produces a JSON text from a JavaScript value.
+
+            When an object value is found, if the object contains a toJSON
+            method, its toJSON method will be called and the result will be
+            stringified. A toJSON method does not serialize: it returns the
+            value represented by the name/value pair that should be serialized,
+            or undefined if nothing should be serialized. The toJSON method
+            will be passed the key associated with the value, and this will be
+            bound to the object holding the key.
+
+            For example, this would serialize Dates as ISO strings.
+
+                Date.prototype.toJSON = function (key) {
+                    function f(n) {
+                        // Format integers to have at least two digits.
+                        return n < 10 ? '0' + n : n;
+                    }
+
+                    return this.getUTCFullYear()   + '-' +
+                         f(this.getUTCMonth() + 1) + '-' +
+                         f(this.getUTCDate())      + 'T' +
+                         f(this.getUTCHours())     + ':' +
+                         f(this.getUTCMinutes())   + ':' +
+                         f(this.getUTCSeconds())   + 'Z';
+                };
+
+            You can provide an optional replacer method. It will be passed the
+            key and value of each member, with this bound to the containing
+            object. The value that is returned from your method will be
+            serialized. If your method returns undefined, then the member will
+            be excluded from the serialization.
+
+            If the replacer parameter is an array of strings, then it will be
+            used to select the members to be serialized. It filters the results
+            such that only members with keys listed in the replacer array are
+            stringified.
+
+            Values that do not have JSON representations, such as undefined or
+            functions, will not be serialized. Such values in objects will be
+            dropped; in arrays they will be replaced with null. You can use
+            a replacer function to replace those with JSON values.
+            JSON.stringify(undefined) returns undefined.
+
+            The optional space parameter produces a stringification of the
+            value that is filled with line breaks and indentation to make it
+            easier to read.
+
+            If the space parameter is a non-empty string, then that string will
+            be used for indentation. If the space parameter is a number, then
+            the indentation will be that many spaces.
+
+            Example:
+
+            text = JSON.stringify(['e', {pluribus: 'unum'}]);
+            // text is '["e",{"pluribus":"unum"}]'
+
+
+            text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
+            // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
+
+            text = JSON.stringify([new Date()], function (key, value) {
+                return this[key] instanceof Date ?
+                    'Date(' + this[key] + ')' : value;
+            });
+            // text is '["Date(---current time---)"]'
+
+
+        JSON.parse(text, reviver)
+            This method parses a JSON text to produce an object or array.
+            It can throw a SyntaxError exception.
+
+            The optional reviver parameter is a function that can filter and
+            transform the results. It receives each of the keys and values,
+            and its return value is used instead of the original value.
+            If it returns what it received, then the structure is not modified.
+            If it returns undefined then the member is deleted.
+
+            Example:
+
+            // Parse the text. Values that look like ISO date strings will
+            // be converted to Date objects.
+
+            myData = JSON.parse(text, function (key, value) {
+                var a;
+                if (typeof value === 'string') {
+                    a =
+/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
+                    if (a) {
+                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+                            +a[5], +a[6]));
+                    }
+                }
+                return value;
+            });
+
+            myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
+                var d;
+                if (typeof value === 'string' &&
+                        value.slice(0, 5) === 'Date(' &&
+                        value.slice(-1) === ')') {
+                    d = new Date(value.slice(5, -1));
+                    if (d) {
+                        return d;
+                    }
+                }
+                return value;
+            });
+
+
+    This is a reference implementation. You are free to copy, modify, or
+    redistribute.
+
+    This code should be minified before deployment.
+    See http://javascript.crockford.com/jsmin.html
+
+    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
+    NOT CONTROL.
+*/
+
+/*jslint evil: true */
+
+/*global JSON */
+
+/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
+    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
+    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
+    lastIndex, length, parse, prototype, push, replace, slice, stringify,
+    test, toJSON, toString, valueOf
+*/
+
+// Create a JSON object only if one does not already exist. We create the
+// methods in a closure to avoid creating global variables.
+
+if (!this.JSON) {
+    JSON = {};
+}
+(function () {
+
+    function f(n) {
+        // Format integers to have at least two digits.
+        return n < 10 ? '0' + n : n;
+    }
+
+    if (typeof Date.prototype.toJSON !== 'function') {
+
+        Date.prototype.toJSON = function (key) {
+
+            return this.getUTCFullYear()   + '-' +
+                 f(this.getUTCMonth() + 1) + '-' +
+                 f(this.getUTCDate())      + 'T' +
+                 f(this.getUTCHours())     + ':' +
+                 f(this.getUTCMinutes())   + ':' +
+                 f(this.getUTCSeconds())   + 'Z';
+        };
+
+        String.prototype.toJSON =
+        Number.prototype.toJSON =
+        Boolean.prototype.toJSON = function (key) {
+            return this.valueOf();
+        };
+    }
+
+    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+        gap,
+        indent,
+        meta = {    // table of character substitutions
+            '\b': '\\b',
+            '\t': '\\t',
+            '\n': '\\n',
+            '\f': '\\f',
+            '\r': '\\r',
+            '"' : '\\"',
+            '\\': '\\\\'
+        },
+        rep;
+
+
+    function quote(string) {
+
+// If the string contains no control characters, no quote characters, and no
+// backslash characters, then we can safely slap some quotes around it.
+// Otherwise we must also replace the offending characters with safe escape
+// sequences.
+
+        escapable.lastIndex = 0;
+        return escapable.test(string) ?
+            '"' + string.replace(escapable, function (a) {
+                var c = meta[a];
+                return typeof c === 'string' ? c :
+                    '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+            }) + '"' :
+            '"' + string + '"';
+    }
+
+
+    function str(key, holder) {
+
+// Produce a string from holder[key].
+
+        var i,          // The loop counter.
+            k,          // The member key.
+            v,          // The member value.
+            length,
+            mind = gap,
+            partial,
+            value = holder[key];
+
+// If the value has a toJSON method, call it to obtain a replacement value.
+
+        if (value && typeof value === 'object' &&
+                typeof value.toJSON === 'function') {
+            value = value.toJSON(key);
+        }
+
+// If we were called with a replacer function, then call the replacer to
+// obtain a replacement value.
+
+        if (typeof rep === 'function') {
+            value = rep.call(holder, key, value);
+        }
+
+// What happens next depends on the value's type.
+
+        switch (typeof value) {
+        case 'string':
+            return quote(value);
+
+        case 'number':
+
+// JSON numbers must be finite. Encode non-finite numbers as null.
+
+            return isFinite(value) ? String(value) : 'null';
+
+        case 'boolean':
+        case 'null':
+
+// If the value is a boolean or null, convert it to a string. Note:
+// typeof null does not produce 'null'. The case is included here in
+// the remote chance that this gets fixed someday.
+
+            return String(value);
+
+// If the type is 'object', we might be dealing with an object or an array or
+// null.
+
+        case 'object':
+
+// Due to a specification blunder in ECMAScript, typeof null is 'object',
+// so watch out for that case.
+
+            if (!value) {
+                return 'null';
+            }
+
+// Make an array to hold the partial results of stringifying this object value.
+
+            gap += indent;
+            partial = [];
+
+// Is the value an array?
+
+            if (Object.prototype.toString.apply(value) === '[object Array]') {
+
+// The value is an array. Stringify every element. Use null as a placeholder
+// for non-JSON values.
+
+                length = value.length;
+                for (i = 0; i < length; i += 1) {
+                    partial[i] = str(i, value) || 'null';
+                }
+
+// Join all of the elements together, separated with commas, and wrap them in
+// brackets.
+
+                v = partial.length === 0 ? '[]' :
+                    gap ? '[\n' + gap +
+                            partial.join(',\n' + gap) + '\n' +
+                                mind + ']' :
+                          '[' + partial.join(',') + ']';
+                gap = mind;
+                return v;
+            }
+
+// If the replacer is an array, use it to select the members to be stringified.
+
+            if (rep && typeof rep === 'object') {
+                length = rep.length;
+                for (i = 0; i < length; i += 1) {
+                    k = rep[i];
+                    if (typeof k === 'string') {
+                        v = str(k, value);
+                        if (v) {
+                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
+                        }
+                    }
+                }
+            } else {
+
+// Otherwise, iterate through all of the keys in the object.
+
+                for (k in value) {
+                    if (Object.hasOwnProperty.call(value, k)) {
+                        v = str(k, value);
+                        if (v) {
+                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
+                        }
+                    }
+                }
+            }
+
+// Join all of the member texts together, separated with commas,
+// and wrap them in braces.
+
+            v = partial.length === 0 ? '{}' :
+                gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
+                        mind + '}' : '{' + partial.join(',') + '}';
+            gap = mind;
+            return v;
+        }
+    }
+
+// If the JSON object does not yet have a stringify method, give it one.
+
+    if (typeof JSON.stringify !== 'function') {
+        JSON.stringify = function (value, replacer, space) {
+
+// The stringify method takes a value and an optional replacer, and an optional
+// space parameter, and returns a JSON text. The replacer can be a function
+// that can replace values, or an array of strings that will select the keys.
+// A default replacer method can be provided. Use of the space parameter can
+// produce text that is more easily readable.
+
+            var i;
+            gap = '';
+            indent = '';
+
+// If the space parameter is a number, make an indent string containing that
+// many spaces.
+
+            if (typeof space === 'number') {
+                for (i = 0; i < space; i += 1) {
+                    indent += ' ';
+                }
+
+// If the space parameter is a string, it will be used as the indent string.
+
+            } else if (typeof space === 'string') {
+                indent = space;
+            }
+
+// If there is a replacer, it must be a function or an array.
+// Otherwise, throw an error.
+
+            rep = replacer;
+            if (replacer && typeof replacer !== 'function' &&
+                    (typeof replacer !== 'object' ||
+                     typeof replacer.length !== 'number')) {
+                throw new Error('JSON.stringify');
+            }
+
+// Make a fake root object containing our value under the key of ''.
+// Return the result of stringifying the value.
+
+            return str('', {'': value});
+        };
+    }
+
+
+// If the JSON object does not yet have a parse method, give it one.
+
+    if (typeof JSON.parse !== 'function') {
+        JSON.parse = function (text, reviver) {
+
+// The parse method takes a text and an optional reviver function, and returns
+// a JavaScript value if the text is a valid JSON text.
+
+            var j;
+
+            function walk(holder, key) {
+
+// The walk method is used to recursively walk the resulting structure so
+// that modifications can be made.
+
+                var k, v, value = holder[key];
+                if (value && typeof value === 'object') {
+                    for (k in value) {
+                        if (Object.hasOwnProperty.call(value, k)) {
+                            v = walk(value, k);
+                            if (v !== undefined) {
+                                value[k] = v;
+                            } else {
+                                delete value[k];
+                            }
+                        }
+                    }
+                }
+                return reviver.call(holder, key, value);
+            }
+
+
+// Parsing happens in four stages. In the first stage, we replace certain
+// Unicode characters with escape sequences. JavaScript handles many characters
+// incorrectly, either silently deleting them, or treating them as line endings.
+
+            cx.lastIndex = 0;
+            if (cx.test(text)) {
+                text = text.replace(cx, function (a) {
+                    return '\\u' +
+                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+                });
+            }
+
+// In the second stage, we run the text against regular expressions that look
+// for non-JSON patterns. We are especially concerned with '()' and 'new'
+// because they can cause invocation, and '=' because it can cause mutation.
+// But just to be safe, we want to reject all unexpected forms.
+
+// We split the second stage into 4 regexp operations in order to work around
+// crippling inefficiencies in IE's and Safari's regexp engines. First we
+// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
+// replace all simple value tokens with ']' characters. Third, we delete all
+// open brackets that follow a colon or comma or that begin the text. Finally,
+// we look to see that the remaining characters are only whitespace or ']' or
+// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
+
+            if (/^[\],:{}\s]*$/.
+test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
+replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
+replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+
+// In the third stage we use the eval function to compile the text into a
+// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
+// in JavaScript: it can begin a block or an object literal. We wrap the text
+// in parens to eliminate the ambiguity.
+
+                j = eval('(' + text + ')');
+
+// In the optional fourth stage, we recursively walk the new structure, passing
+// each name/value pair to a reviver function for possible transformation.
+
+                return typeof reviver === 'function' ?
+                    walk({'': j}, '') : j;
+            }
+
+// If the text is not JSON parseable, then a SyntaxError is thrown.
+
+            throw new SyntaxError('JSON.parse');
+        };
+    }
+})();
diff --git a/UNGProject/openajaxhub/src/containers/iframe/tunnel.html b/UNGProject/openajaxhub/src/containers/iframe/tunnel.html
new file mode 100644
index 0000000000000000000000000000000000000000..7a68ae12121a5ddf965624a6f494a4af25f64a80
--- /dev/null
+++ b/UNGProject/openajaxhub/src/containers/iframe/tunnel.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+
+        Copyright 2006-2009 OpenAjax Alliance
+
+        Licensed under the Apache License, Version 2.0 (the "License"); 
+        you may not use this file except in compliance with the License. 
+        You may obtain a copy of the License at
+        
+                http://www.apache.org/licenses/LICENSE-2.0
+
+        Unless required by applicable law or agreed to in writing, software 
+        distributed under the License is distributed on an "AS IS" BASIS, 
+        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+        See the License for the specific language governing permissions and 
+        limitations under the License.
+-->
+
+<html>
+	<head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+        <title>Hub Tunnel</title>
+        <script src="iframe.js"></script><script src="FIM.js"></script>
+        <script type="text/javascript">
+            function init()
+            {
+                if ( window.postMessage ) {
+                    var internalID = OpenAjax.hub.IframePMHubClient.queryURLParam( "oahj" );
+                    var origin = OpenAjax.hub.IframePMHubClient.queryURLParam( "oaho" );
+                    var securityToken = OpenAjax.hub.IframePMHubClient.queryURLParam( "oaht" );
+                    window.parent.parent.OpenAjax.hub.IframePMContainer._pmListener
+                            .connectFromTunnel( internalID, origin, securityToken, window );
+                } else {
+                    var commLib = new smash.CommLib( false,
+                            window.parent.parent.smash.SEComm.instances );
+                }
+            }
+        </script>
+    </head>
+    <body onload="init();"></body>
+</html>
diff --git a/UNGProject/ung.html b/UNGProject/ung.html
index 597d101315d0475569b2c2062a4b6fd7e1a6527b..6ba665e3396a3ec710c065e2dfd5bcdf59ac6802 100644
--- a/UNGProject/ung.html
+++ b/UNGProject/ung.html
@@ -16,6 +16,15 @@
     <link type="text/css" rel="stylesheet" href="css/ung.css" />
     <link type="text/css" rel="stylesheet" href="css/jquery-ui.css" />
     <link type="text/css" rel="stylesheet" href="css/gadget.css" />
+    <script type="text/javascript" src="openajaxhub/src/OpenAjax-mashup.js"></script>
+    <script type="text/javascript" src="dojo/dojo/dojo.js"></script>
+    <script type="text/javascript" src="openajaxhub/src/containers/inline/inline.js"></script>
+    <script type="text/javascript" src="openajaxhub/src/containers/iframe/iframe.js"></script>
+    <script type="text/javascript" src="openajaxhub/src/containers/iframe/FIM.js"></script>
+    <script type="text/javascript" src="openajaxhub/src/containers/iframe/json2.js"></script>
+    <script type="text/javascript" src="openajaxhub/src/containers/iframe/crypto.js"></script>
+
+
     <script type="text/javascript" src="js/jquery/jquery.js"></script>
     <script type="text/javascript" src="js/jquery/jquery-ui.js"></script>
     <script type="text/javascript" src="js/tools.js"></script>
@@ -23,11 +32,35 @@
 
     <script type="text/javascript" src="js/theme.js"></script>
     <script type="text/javascript" src="js/ung.js"></script>
+    <script type="text/javascript" src="js/loader.js"></script>
+
+    <link href="dojo/dijit/themes/tundra/tundra.css" rel="stylesheet">
+    <!--link href="dojo/dojo/resources/dojo.css" rel="stylesheet"-->
+
+    <link href="gadgets/layout/css/whitebox/whitebox.css" rel="stylesheet"/>
+    <link href="gadgets/layout/css/default/mashup.css" rel="stylesheet"/>
+    <script src="gadgets/layout/absolutelayout/absolutelayout.js"></script>
+    <script src="gadgets/layout/browser.js"></script>
+    <script src="gadgets/layout/gadgetsite.js"></script>
+    <link href="gadgets/layout/absolutelayout/absolutelayout.css" rel="stylesheet"/>
+
+    <script type="text/javascript" src="js/minimashup.js"></script>
+    <script>
+        mashupMaker.layout = new AbsoluteLayout();
+    </script>
+
+    <script src="gadgets/refimpldojo.js"></script>
+    <script type="text/javascript" src="gadgets/toolbar.js"></script>
+    <script>
+        var baseURL = window.location.protocol + "//" + window.location.host + window.location.pathname.substring( 0, window.location.pathname.lastIndexOf("/")+1 );
+        djConfig = { usePlainJson: true, parseOnLoad: false, isDebug: false,
+                modulePaths: { "nomad": baseURL + "nomad"} };
+    </script>
+
 
-    <link rel="icon" type="image/x-icon"
-        href="images/ung/favicon.ico" />
-    <link rel="shortcut icon" type="image/x-icon"
-        href="images/ung/favicon.ico" />
+
+    <link rel="icon" type="image/x-icon" href="images/ung/favicon.ico" />
+    <link rel="shortcut icon" type="image/x-icon" href="images/ung/favicon.ico" />
 
     <script type="text/javascript">
 
@@ -348,7 +381,16 @@
                                                         </div>
 
                                                         <div id="add_new_gadget_link">
-                                                            <a title="Add gadgets" id="add-gadgets" href="..."><span>Add gadgets</span></a>
+                                                            <div id="mashupToolbarContainer">
+                                                                <div id="mashupToolbar" dojoType="dijit.Toolbar">
+                                                                    <div id="searchResults" dojoType="dijit.form.DropDownButton" showLabel="true" iconClass="nomadToolbarIcon nomadIconSearchResults">
+                                                                        <span>Add gadgets</span>
+                                                                        <div id="searchResultsMenu" dojoType="nomad.widget.PaletteMenu">
+                                                                        </div>
+                                                                    </div>
+                                                                </div>
+                                                            </div>
+                                                            <!--a title="Add gadgets" id="add-gadgets"><span>Add gadgets</span></a-->
                                                         </div>
 
                                                 </div>
@@ -363,7 +405,10 @@
                                                     <div id="page_wrapper">
 
                                                         <!-- No gadgets message -->
-                                                        <div>
+                                                        <div id="gadget_container">
+                                                        <div id="__replaceablecontent__">
+                                                        <!-- Here is where the gadgets appear-->
+                                                        </div>
                                                             <h3> Your tab is empty. </h3>
                                                             <h4> Please  use link (<b>Add gadgets</b>) to prepare it yourself. </h4>
                                                         </div>
diff --git a/buildout.cfg b/buildout.cfg
index 91993ec70d7f23e4f367b4d690922d691d4b6fd1..454cb6af9f8137af833366cd6dd16e5c68ec8f2c 100644
--- a/buildout.cfg
+++ b/buildout.cfg
@@ -1,11 +1,12 @@
 [buildout]
 extensions = mr.developer
-auto-checkout = xinha
+auto-checkout = dojo xinha
 parts = jsquery jsquery-ui
 sources-dir =
 
 [sources]
 xinha = svn http://svn.xinha.org/tags/0.96.1 path=UNGProject egg=false
+dojo = svn http://svn.dojotoolkit.org/src/branches/1.6/ path=UNGProject egg=false
 
 [jsquery]
 recipe = hexagonit.recipe.download